DIY disco laser pointer and arduino installation
For the New Year's dance party, I decided to make a simple laser installation, which would demonstrate something in time with the music. At hand was a laser pointer with a set of interchangeable rotating caps that allowed you to get nice effects on the ceiling. Adding a couple of servos and arduino mini pro - I got what I wanted.
The circuit is very simple (one key that controls the laser pointer; a pair of silicon diodes to lower the voltage for the pointer; a resistor for the electret microphone and a ready-made DC-DC module for converting the voltage from the battery to five volts), performed on a piece of the breadboard.
The microphone with such a simple inclusion - has a fairly low sensitivity, so the device must be placed close enough to the speakers.
It should be noted that despite the presence of a key to control the laser pointer - it is actually not used for me (always on), so you can just throw it away. Well, or add some blinking if you want.
Theoretically, it would be much better to use a motor with a gearbox to rotate the cap (to avoid noticeable jitter), but with a servo drive it turned out easier (I printed a couple of gears on the printer and that's it).
Servos - Turnigy TGY-R5180MG (180 degrees, for rotating the cap) and some kind of old 9 gram servo (for rotating the device itself). The stand is a tripod from a fan, which hobbyking once sold for a penny.
Video work:
Sketch:
Thanks for attention!
The circuit is very simple (one key that controls the laser pointer; a pair of silicon diodes to lower the voltage for the pointer; a resistor for the electret microphone and a ready-made DC-DC module for converting the voltage from the battery to five volts), performed on a piece of the breadboard.
The microphone with such a simple inclusion - has a fairly low sensitivity, so the device must be placed close enough to the speakers.
It should be noted that despite the presence of a key to control the laser pointer - it is actually not used for me (always on), so you can just throw it away. Well, or add some blinking if you want.
Theoretically, it would be much better to use a motor with a gearbox to rotate the cap (to avoid noticeable jitter), but with a servo drive it turned out easier (I printed a couple of gears on the printer and that's it).
Servos - Turnigy TGY-R5180MG (180 degrees, for rotating the cap) and some kind of old 9 gram servo (for rotating the device itself). The stand is a tripod from a fan, which hobbyking once sold for a penny.
Video work:
Sketch:
#include
// yaw servo - PWM
#define SERVO_YAW 5
// roll servo - PWM
#define SERVO_ROLL 6
// Laser pin - PWM or DO
#define LASER 9
// Microphone input - A0
#define MIC A0
// Yaw servo period (in ms)
#define YAW_PERIOD 40
// Roll servo period (in ms)
#define ROLL_PERIOD 100
// MIN value for yaw servo
#define MIN_YAW 40
// MAX value for yaw servo
#define MAX_YAW 130
// MIN value for roll servo
#define MIN_ROLL 10
// MAX value for roll servo
#define MAX_ROLL 150
Servo yaw_servo;
Servo roll_servo;
// Current position and direction for servos
int16_t roll_pos = MIN_ROLL;
int8_t roll_dir = 1;
int16_t yaw_pos = MIN_YAW;
int8_t yaw_dir = 1;
// Sound peak detected
boolean flag_sound = false;
// Internal sound volume average stuff
int16_t arr_vol[32];
int8_t arr_pos = 0;
unsigned long last_sound = 0;
// Detect sound volume peaks
void check_sound() {
int16_t volume = analogRead(MIC);
int i;
int32_t sum;
int16_t average;
// Calculate average from last reads
arr_vol[arr_pos] = volume;
arr_pos++;
if (arr_pos > (sizeof(arr_vol) / sizeof(arr_vol[0])))
arr_pos = 0;
sum = 0;
for (i = 0; i < (sizeof(arr_vol) / sizeof(arr_vol[0])); i++)
sum += arr_vol[i];
average = sum / (sizeof(arr_vol) / sizeof(arr_vol[0]));
if (flag_sound && ((millis() - last_sound) > 200))
flag_sound = false;
if ((millis() - last_sound) < 300)
return;
if (volume > (average + 4)) {
flag_sound = true;
last_sound = millis();
}
} // void check_sound()
unsigned long last_yaw = 0;
// Rotate yaw servo
void rotate_yaw() {
if ((millis() - last_yaw) < YAW_PERIOD)
return;
last_yaw = millis();
yaw_pos += yaw_dir;
// Change rotate direction when reached limit
if ((yaw_pos >= MAX_YAW) || (yaw_pos <= MIN_YAW))
yaw_dir = -yaw_dir;
yaw_servo.write(yaw_pos);
} // void rotate_yaw()
unsigned long last_roll = 0;
// Rotate roll servo
void rotate_roll() {
if ((millis() - last_roll) < ROLL_PERIOD)
return;
last_roll = millis();
roll_pos += roll_dir;
// Rotate faster when we detect sound peaks
if (flag_sound) {
roll_pos += (8 * roll_dir);
if (roll_pos < MIN_ROLL)
roll_pos = MIN_ROLL;
if (roll_pos > MAX_ROLL)
roll_pos = MAX_ROLL;
}
// Change rotate direction when reached limit
if ((roll_pos >= MAX_ROLL) || (roll_pos <= MIN_ROLL))
roll_dir = -roll_dir;
roll_servo.write(roll_pos);
} // void rotate_roll()
void setup() {
// put your setup code here, to run once:
pinMode(LASER, OUTPUT);
digitalWrite(LASER, HIGH);
yaw_servo.attach(SERVO_YAW);
yaw_servo.write(yaw_pos);
roll_servo.attach(SERVO_ROLL);
roll_servo.write(roll_pos);
Serial.begin(115200);
delay(300);
} // void setup()
void loop() {
// put your main code here, to run repeatedly:
check_sound();
rotate_yaw();
rotate_roll();
delay(10);
} // void loop()
Thanks for attention!