Для данного проекта потребуется LOL Shield. Приобрести его можно в Sparkfun, но можно сделать и самому. Печатная плата и схема в свободном доступе лежит здесь. LOLShield представляет из себя светодиодную матрицу размерностью 14 x 9, сделанную как шилд к Arduino. В LOL Shield применяется довольно оригинальный метод управления светодиодами, так называемый Charlieplexing. Данный шилд был разработан Джимми Роджерсом.
Для анализа аудио-сигнала используется метод FFT (быстрого преобразования Фурье), который раскладывает сигнал на частоты и затем при помощи контроллера отображает на LED-матрице. Описание библиотеки FFT можно найти на форуме Arduino. Быстродействия контроллера Arduino вполне хватает для вычислений FFT, поэтому каких-либо проблем с отображением не возникает.
Итак, мы купили или собрали LOL Shield, затем припаиваем 3.5мм мини джэк (или другой разьем, который нужен вам для вашей аудиосистемы)
В LOL шилде свободны 2 пина: это аналоговые 4 и 5. Для входа аудиосигнала я использовал 5-ый пин. Общий от миниджека подключаем к пину GND.
Программная часть
Для скетча нам потребуется 2 библиотеки:
библиотека FFT
библиотека Charlieplexing для LoL шилда
Алгоритм FFT разбивает звуковой диапазон на 64 частотных диапазона. Однако наш LOL Shield содержит матрицу 14 x 9 LED. Поэтому нам надо вывести среднее и переназначить 64 частотных диапазона в 14 (проще говоря сделать remap). Уровень мы также приводим к диапазону от 0 до 9.
Код программы:
/* FFT for LoL Shield v0.9 by Andy Doro http://andydoro.com/ based on FFT library and code from the Arduino forums and the Charlieplexing library for the LoL Shield. */ #include Charliplexing.h #include fix_fft.h #define AUDIOPIN 5 // Аудиовход char im[128], data[128]; char data_avgs[14]; int i=0,val; void setup() { LedSign::Init(); //Инициализация LoL Shield } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val; im[i] = 0; }; fix_fft(data,im,7,0); for (i=0; i< 64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // this gets the absolute value of the values in the array, so we're only dealing with positive numbers }; // average bars together for (i=0; i<14; i++) { data_avgs[i] = data[i*4] + data[i*4 + 1] + data[i*4 + 2] + data[i*4 + 3]; // вычисляем среднее data_avgs[i] = map(data_avgs[i], 0, 30, 0, 9); // делаем remap для LoL } // set LoLShield for (int x=0; x < 14; x++) { for (int y=0; y < 9; y++) { if (y < data_avgs[13-x]) { // 13-x reverses the bars so low to high frequences are represented from left to right. LedSign::Set(x,y,1); // включаем LED } else { LedSign::Set(x,y,0); // выключаем LED } } } }
Скетч, библиотеки и Eagle-файл PCB вы можете скачать внизу
- audio_spectrum.zip (89 Кб)
Комментарии (6) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
val = analogRead(AUDIOPIN);
разве даёт частоту сигнала, а не его уровень (громкость) в конкретный момент снятия показаний? То есть матрица LED по-просту рисует дискретный уровень сигнала взятый в 128-и точках времени, а не его частотное разложение?
Это делается, судя по всему, тут
fix_fft(data,im,7,0);
Только непонятно, вот это зачем?
data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // this gets the absolute value of the values in the array, so we're only dealing with positive numbers
Я так понимаю, далее достаточно умножить массив im[] на константу (при наличии отрицательных чисел - взять по модулю)
https://youtu.be/keCJKKUaBrk
https://youtu.be/xJ1NpfPlric