DIY дискотечная лазерная установка из указки и ардуинки

Для танцевальной новогодней вечеринки решил сделать простую лазерную установку, которая бы в такт музыке что-нибудь демонстрировала. Под рукой была лазерная указка с набором сменных вращающихся колпачков, которые позволяли получать симпатичные эффекты на потолке. Добавив пару сервоприводов и arduino mini pro — получил искомое.


Схема очень простая (один ключ, управляющий лазерной указкой; пара кремниевых диодов, для понижения напряжения для указки; резистор для электретного микрофона и готовый модуль DC-DC преобразователя напряжения от аккумулятора в пять вольт), выполнил на отрезке макетной платы.

Микрофон при таком простейшем включении — имеет довольно низкую чувствительность, так что устройство нужно ставить достаточно близко к колонкам.


Надо заметить, что несмотря на наличие ключа для управления лазерной указкой — он у меня фактически не используется (всегда включен), так что можно просто выкинуть. Ну или добавить какое-нибудь моргание, если хочется.

Теоретически, гораздо лучше было бы использовать двигатель с редуктором для вращения колпачка (чтобы избежать заметного дрожания), но с сервоприводом получилось проще (напечатал пару шестеренок на принтере и все).

Сервоприводы — Turnigy TGY-R5180MG (180 градусов, для вращения колпачка) и какая-то старая 9 граммовая серва (для вращения самого устройства). Подставка — треножник от вентилятора, которые hobbyking продавала как-то за копейки.

Видео работы:





Скетч:

#include <Servo.h>
// 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()

Спасибо за внимание!
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 23

    0
    резковато движется. Думаю два лазера давали бы интереснее эффекты
      0
      А если три, да еще и разных цветов, то вообще дисплей получится
        0
        Скорость движения можно уменьшать (повышая задержки YAW_PERIOD/ROLL_PERIOD), хотя там есть выраженная ступенчатость из-за ограничений ардуиновской библиотеки Servo (шаг в один градус только).
        +1

        Ничего непонятно, расскажите нормально про механику (схемы и скейчи — вторичны).

          0
          Да, наверное стоило бы более подробно разобрать. Там один сервопривод вращает шестеренку, которая вращает другую шестеренку на колпачке указки. На валу второго сервопривода прикреплена платформа, на которой закреплены упомянутые элементы.
            0

            на фото точно ничего не разобрать

              0
              Я добавил второе видео, где видно как что крутится.
                0

                спасибо
                рисунок выцарапан на стекле просто?

                  0
                  В колпачке — стекляшки и линзы какие-то. Китайцы продают такие указки, с наборами колпачков для разных рисунков.
          0
          Можно сделать колесо-кассету со стеклами и вращать его. Будет смена картинки.
            +1
            лет 5 назад делал что-то похожее но без ардуинки
              0
              Красиво, но тут механика точная нужна, не для меня. :)
                0
                Все очень просто!!! Все из хлама. Лазер из DVD RW привода, линза из лазерной указки, 3 моторчика из CD и DVD приводов, три круглых зеркала из точилок купленных в кацтоварах, маленькая схема управления двигателями и… и все
                0
                тоже делал, только лет 20 назад, естесственно тоже без ардуины. Тупо до невозможности — два зеркальца, два моторчика и указка.
                http://impetus.obninsk.ru/pricol/prazdn.html
                тоже — «на соплях».
                всё хотел лазер зелёный помощнее и в небо на облака, но пока тормозил — лазеры в небо запретили.
                imageimage
                  +1
                  Я с начала тоже так собрал. Потом прицепил третий моторчик и схему управления моторами по аналогии с цветомузыкой, только с моторами вместо лампочек.image
                  0
                  0
                  Для повышения точности управления сервоприводом можно использовать полушаговый режим (выше токи, выше разрешение), самому набросать функцию шагания не так тяжело.
                  image
                    0
                    Это сервы для моделей, с управлением PWM, там к мотору не подкопаться. На самом деле можно ардуину заставить более точные импульсы выдавать, точность раза в четыре возрастет.
                      +1
                      Сделать оказалось проще чем написать, заменил везде write на writeMicroseconds, уменьшил задержки в несколько раз и минимум/максимум на микросекунды, оно двигаться гораздо плавнее стало (не идеально все равно).
                        0
                        Нет там PWM, вместо включения A-B-C-D включается A-AB-B-BC-C-CD-D-DA-A, прямо вручную через digitalWrite и какой-нибудь ULN2004
                  0
                  У вас микрофон как-то странно подключен.

                  Включение электретного микрофона. Вам надо было сигнал через кондёр снимать.
                    0
                    У меня там постоянная составляющая все равно отфильтровывается процедурой вычисления среднего уровня, так что лишняя деталь. :)

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое