Skip to content Skip to main navigation Skip to footer

Светомузыка на RGB ленте

Задача


  • Подключиться к динамику, считать с него звук и управлять яркостью и цветом светодиодной ленты под музыку
  • Несколько эффектов (режимов)
  • Переключать режимы кнопкой

Базовые уроки


Компоненты не из набора


  • 12V RGB светодиодная лента
  • Источник питания 12V (блок питания или аккумулятор)

Подключение


  • +12V питания подключается к ленте, по желанию на Vin Arduino (для питания платы)
  • Звук имеет довольно низкое напряжение, поэтому используем внешнее опорное и подключаем Aref например к пину 3.3V на плате
  • “Плюс” звука пропускаем через RC фильтр R3 и C1. Если звук идёт с нормального усилителя (A-B класса), то фильтр скорее всего будет не нужен
  • Резистор R2 нужен для ограничения тока, по земле динамика в том случае, если у усилителя и Ардуины общее питание! При раздельном питании можно не ставить
  • По хорошему нужен ещё разделительный конденсатор (10-100 мкФ) между выходом с фильтра и пином А7, но без него анализ работает лучше
  • Пины драйвера подключаем к ШИМ пинам

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

Вариант из набора


В рамках набора GyverKIT можно собрать схему без ленты, заменив её RGB светодиодом чисто в качестве эксперимента, демонстрации или отладки. Подключаем к тем же пинам, прошивка будет та же самая, питание – от USB.

Вариант с RGB светодиодом и микрофоном работает вот так:

Библиотеки


  • GRGB для удобного управления цветом и яркостью ленты
  • VolAnalyzer для амплитудного анализа звука
  • EncButton для удобной работы с кнопкой

Программа


Подключаем библиотеки, создаём объекты согласно документации и подключению:

#include <GRGB.h>
GRGB led(COMMON_CATHODE, 9, 10, 11);  // RGB на пинах D9,D10,D11

#include "VolAnalyzer.h"
VolAnalyzer analyzer(A7);   // вход звука на А7

#include <EncButton.h>
EncButton<EB_TICK, 3> btn;  // кнопка на D3

В setup() нам нужно настроить АЦП на внешнее опорное напряжение

analogReference(EXTERNAL);

Далее “разгоняем” ШИМ до 8 кГц (чтобы не гудело и не мерцало на камеру. В принципе можно и без этого). Урок по разгону ШИМ

TCCR2B = 0b00000010;  // x8
TCCR2A = 0b00000011;  // fast pwm

// Пины D9 и D10 - 7.8 кГц
TCCR1A = 0b00000001;  // 8bit
TCCR1B = 0b00001010;  // x8 fast pwm

Далее я настраиваю анализатор звука под себя – плавность громкости и нижний порог тишины, при котором считается что звука нет

analyzer.setVolK(25);     // плавность громкости (0-31)
analyzer.setTrsh(50);     // порог тишины

Продолжаю настраивать анализатор, задаю минимум и максимум “громкости” – значения, которое будет выдавать библиотека. Также настраиваю “пульс” – реакцию на резкое изменение громкости. Библиотека будет считать пульсом значение громкости, которое было ниже значения 80, а потом стало больше 200, и с последнего срабатывания прошло больше 200 мс:

analyzer.setVolMin(10);   // мин. громкость 10
analyzer.setVolMax(255);  // макс. громкость 255

analyzer.setPulseTrsh(200);     // верхний порог пульса
analyzer.setPulseMin(80);       // нижний порог пульса
analyzer.setPulseTimeout(200);  // таймаут пульсов

Далее идёт основной цикл программы. В самом начале опрашиваем кнопку на “клик” и по нему меняем значение переменной режима от 0 до 3:

btn.tick();
static byte mode = 0;
if (btn.isClick()) {
  if (++mode >= 4) mode = 0;
}

Анализ звука происходит автоматически при вызове analyzer.tick(), причём она возвращает true, когда завершён анализ текущей выборки. Внутри этого условия применяем яркость и цвет к ленте согласно текущему режиму:

if (analyzer.tick()) {    
  static byte color = 0;

  // эффекты
  switch (mode) {
    case 0:
      if (analyzer.getPulse()) color += 151;
      led.setWheel8(color, analyzer.getVol());
      break;
    case 1:
      if (analyzer.getPulse()) color += 129;
      led.setWheel8(color, analyzer.getVol());
      break;
    case 2:
      led.setWheel8(color++, analyzer.getVol());
      break;
    case 3:
      led.setHSVfast((analyzer.getVol() - 10) / 6, 255, analyzer.getVol());
      break;
  }
  • Режим 1: по пульсу увеличиваем переменную цвета на 151 и отправляем как цвет с яркостью, равной громкости. Откуда такое число? Получено вот из этой программы на Processing, чтобы смена цвета была максимально гармоничной (см. картинку ниже)
  • Режим 2: всё то же самое, но меняем цвет на 129. Число также подобрано в программе, эффект – чередующиеся цвета, плавно движущиеся по палитре
  • Режим 3: просто плавно меняем цвет, инкрементируя переменную на 1, а яркость задаём по громкости
  • Режим 4: огненная палитра. В пространстве HSV меняем цвет от 0 (красный) до 40 (жёлтый), насыщенность 255, яркость – по громкости
Полный код программы
#include <GRGB.h>
GRGB led(COMMON_CATHODE, 9, 10, 11);  // RGB на пинах D9,D10,D11

#include "VolAnalyzer.h"
VolAnalyzer analyzer(A7);   // вход звука на А7

#include <EncButton.h>
EncButton<EB_TICK, 3> btn;  // кнопка на D3

void setup() {
  analogReference(EXTERNAL);  // внешнее опорное

  // разгоняем ШИМ чтобы не стробило на камеру
  // Пины D3 и D11 - 8 кГц
  TCCR2B = 0b00000010;  // x8
  TCCR2A = 0b00000011;  // fast pwm
  
  // Пины D9 и D10 - 7.8 кГц
  TCCR1A = 0b00000001;  // 8bit
  TCCR1B = 0b00001010;  // x8 fast pwm

  analyzer.setVolK(25);     // плавность громкости (0-31)
  analyzer.setTrsh(50);     // порог тишины
  analyzer.setVolMin(10);   // мин. громкость 10
  analyzer.setVolMax(255);  // макс. громкость 255

  analyzer.setPulseTrsh(200);     // верхний порог пульса
  analyzer.setPulseMin(80);       // нижний порог пульса
  analyzer.setPulseTimeout(200);  // таймаут пульсов
}

void loop() {
  // опрос кнопки, смена режимов по клику
  btn.tick();
  static byte mode = 0;
  if (btn.isClick()) {
    if (++mode >= 4) mode = 0;
  }

  // анализ звука
  if (analyzer.tick()) {    
    static byte color = 0;

    // эффекты
    switch (mode) {
      case 0:
        if (analyzer.getPulse()) color += 151;
        led.setWheel8(color, analyzer.getVol());
        break;
      case 1:
        if (analyzer.getPulse()) color += 129;
        led.setWheel8(color, analyzer.getVol());
        break;
      case 2:
        led.setWheel8(color++, analyzer.getVol());
        break;
      case 3:
        led.setHSVfast((analyzer.getVol() - 10) / 6, 255, analyzer.getVol());
        break;
    }
  }
}

Проект также доступен на GitHub

Возможные доработки


  • R1 на схеме нужен для задания внешнего опорного напряжения. Можно подключить вместо него потенциометр (средней точкой с 5V и GND) для широкой настройки опорного напряжения. При использовании низковольтного (до 1V) источника звукового сигнала можно переключиться на внутреннее опорное (1.1V)
  • В рамках набора можно заменить 12V RGB ленту на 5V адресную с теми же эффектами, либо написать гораздо более интересные эффекты под адресную ленту

Видео


Полезный пример?

Похожие примеры
Подписаться
Уведомить о
3 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии