Многоканальная цветомузыка. Методы обработки сигнала
- Войдите на сайт для отправки комментариев
Пнд, 25/03/2013 - 22:35
Всем доброго времени суток!
Задался целью сваять годную цветомузыку, на основе УНО (328). Хочеться все сделать качественно и красиво, а для этого как ни крути надо ФФТ использовать, но никак не воткну как она работает. Поэтому пока сделано относительно громкости входящего сигнала, но, сами понимаете, это не комильфо =) Прошу помощи с ффт, ткните носом куда нужно, очень уж охота сделать по уму =)
Тут две версии моего говнокода светомузыки для ргб ленты, лазерного проэктора и строба.
Вариант 1
int MicPin = 0; // audio in int redPin = 5; int greenPin = 6; int bluePin = 3; int MicValue = 0; //значение аудиосигнала int correction = 370 //коррекция по громкости для разных устройств void setup() { Serial.begin(9600); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); analogWrite(redPin, 0); analogWrite(greenPin, 0); analogWrite(bluePin, 0); } void loop() { MicValue = analogRead(MicPin)+correction; Serial.println(MicValue); // это для отладки if (MicValue > 500) { analogWrite(bluePin,255); analogWrite(redPin, 0); delay(15); } if (MicValue > 540) { analogWrite(bluePin,0); analogWrite(greenPin, 255); delay(15); } if (MicValue > 560) { analogWrite(greenPin,0); analogWrite(redPin, 255); delay(15); } analogWrite(greenPin, 0); //все гасим для стобо-эффекта analogWrite(redPin, 0); analogWrite(bluePin,0); delay(5); // увеличивает период темноты - лучший стробо-эффект }
Видео первого варианта - см ниже (от модератора)
Вариант 2
int MicPin = 0; // пин входа int input = 0; int redPin = 5; int greenPin = 6; int bluePin = 3; int laserPin = 11; int stroboPin = 2; int MicValue = 0; // значение аудиосигнала int correction = 360; void setup() { Serial.begin(9600); pinMode(MicPin, INPUT); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); pinMode(laserPin, OUTPUT); pinMode(stroboPin, OUTPUT); // ЭТО ДЛЯ ПРОСТОЙ ПРОВЕРКИ, ВСЕ ЛИ КАНАЛЫ РАБОТАЮТ! analogWrite(11, 0); analogWrite(redPin, 255); analogWrite(10, 200); delay(500); analogWrite(redPin, 0); analogWrite(10, 0); delay(200); analogWrite(greenPin, 255); analogWrite(10, 200); delay(500); analogWrite(greenPin, 0); analogWrite(10, 0); delay(200); analogWrite(bluePin, 255); analogWrite(10, 200); delay(500); analogWrite(bluePin, 0); analogWrite(10, 0); delay(200); analogWrite(laserPin, 150); analogWrite(10, 200); delay(500); analogWrite(laserPin, 0); analogWrite(10, 0); delay(200); digitalWrite(stroboPin, HIGH); analogWrite(10, 200); delay(500); digitalWrite(stroboPin, LOW); analogWrite(10, 0); } // конец теста // 10й пин - пьезопищалка void loop() { MicValue = analogRead(MicPin)+correction; Serial.println(MicValue); // для отладки if (MicValue > 610) { digitalWrite(stroboPin, HIGH); delay(3); } else { digitalWrite(stroboPin, LOW); delay(5); } if (MicValue > 450 && MicValue <490) { analogWrite(bluePin,255); delay(10); } else { analogWrite(bluePin,0); delay(10); } if (MicValue > 480 && MicValue <520) { analogWrite(greenPin,255); delay(10); } else { analogWrite(greenPin,0); delay(10); } delay(10); if (MicValue > 510 && MicValue <600) { analogWrite(redPin,255); delay(10); } else { analogWrite(redPin,0); delay(10); } if (MicValue < 400) { analogWrite(laserPin, 255); } else { analogWrite(laserPin, 0); delay(5); } }
Ссылка на ютуб из первого поста - http://youtu.be/s92hXKmjHiw
Тут нельзя редактировать сообщения? ^_^
---------
Понял, только шапку нельзя менять =)
Совсем забыл, кто может подсказать как сделать автокоррекцию входящего сигнала, что-бы не надо было настраивать на разные уровни громкости (ноут и телефон, например). БЛАГОДАРСТВУЮ ЗАРАНЕЕ =)
Alexander, спасибо =)
Что кто может подсказать по поводу ФФТ и автокоррекции громкости?
Сорри, не пинайте, но ап! =)
То есть как-то "не пинайте"? :) А как же еще развлекатся?
А если серъезней, то если "все молчат", значит возможные варианты
1. Тема не интерестна
2. Никто не знает ответа
3. Никто не понял что вы хотите
Как видим, ни одни пункт не лечится простым "ап".
С вариантом (2) - вы врядли что-то сделаете, а вот (3) - можете посидеть и подумать, "как бы спросить по другому" (интересней/понятней).
Ну например попытатся объяснить что вы понимаете под "автокоррекцией громкости".
Возможно что-то вот типа такого вам подойдет:
Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Всем снова доброго времени суток! Спасибо за пример автокоррекции, пока еще не пробывал, не хватает времени =)
Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Простите, но вы ошибаетесь, он работает как аналоговый вход, тут все в порядке, через серийник все видно =)
Раз уж с ФФТ ничего не выходит, подскажите пожалуйста чем можно было-бы заменить delay() в моем коде, для более своевременного реагирования на бит. Пробовал с millis(), по образцу стандартного примера, но видимо не так я одарен в коде =) Заранее благодарю!
>чем можно было-бы заменить delay()
функцией millis(). После прочтения примеров из документации. В шапке сайта линк "Програмирование", потом смотрим в правую колонку, там есть раздел "примеры", ищем пример который вроде подходит по смыслу. Пытаемся понять принцип его работы. Так же поиск по форуму может помоч.
Вот что у меня есть:
Всем снова доброго времени суток! Спасибо за пример автокоррекции, пока еще не пробывал, не хватает времени =)
А зачем тогда "поехали дальше" если этот этап не прошли?
Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Простите, но вы ошибаетесь, он работает как аналоговый вход, тут все в порядке, через серийник все видно =)
Спорим на биткоины что ошибаетесь вы? Я же не сказал "работать не будет", я сказал что "делает оно не то что вы думаете". К счастью эти ошибочные танцевальные движения - не приводят к неработоспособности в этом конкретном скетче. Но если вы не разберетесь с этим вопре рано или поздно вы таким образом либо словите глюк, либо когда перепутаете какому именно пиноу вы настраиваете режим при настройке на Output, - упалите ногу.
Итак: У вас есть два пина. D0 и A0. Оба уже включены на INPUT. И вообщем-то не требует инкаких настроек. Но вы захотели все-таки еще раз, явно указать. Это ничего не меняет, но является нормальной практикой. Для читабельности кода - вполне полезно. Но... pinMode вы сделали для D0, а не A0!!! И "ничего не поломалось", только потому что они уже оба были включены на INPUT.
Далее, вы пытаетесь делать analogRead с цифрового входа. Но... к счастью вы не первый кто так делают, поэтому те кто писал функцию analogRead - уже предусмотрели это. И внутри себя она имеет "защиту от дурака", если есть скормили цифровой пин, она сама, внутри поправляет его на аналоговый. Только поэтому у вас и работает. Но вот это "логика поправления" - не документирована, следовательно, хоть и маловероятно но в будущих версиях - ее могут убрать. Или появятся новые платы, в которых просто по номеру будет не просто понять про какой же пин идет речь (и сделать "поправку" станет не возможным).
Вот что у меня есть:
И где тут видно попытки применить millis()? Даже delay() что-бы понять что вы хотите - и то нет.
Вот что у меня есть:
Вот это какраз и есть то, что я не смог понять в ффт. i понятное дело перебирает каналы, с 1 по 63, а вот как поймать значение нужного канала? Например значение канала 1, 25, 50, 60? Мне-то по сути 3-5 каналов и нужно, правда широких. Допустим первый до 500Гц (низ), второй от 500Гц до 1500Гц , третий от 1500 до 3000Гц и т.п..
Покажите пожалуйсто пример с одним каналом и выводом его в серийник, мне хочеться разобраться как оно работает, а тогда я уже смогу подогнать все под свои нужды =) Естественно результатом поделюсь, думаю не мне одному такое интересно =) Заранее благодарю!
Уважаемый leshak, пробывал как вы советовали, тоже правда не до конца воткнул как работает этот алгоритм. Все время 0 после обработки. И пофиг ему что на входе =(
Тема умерла?
Прикрутил к Arduino три RGB ленты через TLC5940NT
Сейчас думаю, какие эффекты зашить, в том числе и от звука.
С преобразованием фурье на три канала кто-то разобрался?
Или проще заюзать три аналоговых порта с частотными фильтрами?
http://yadi.sk/d/cyD8GFReCbbh4
качайте библиотеку. рабочая проверял
это спектр если пальцем дотронутся до входа ардуины на которой проверял
http://yadi.sk/d/cyD8GFReCbbh4
качайте библиотеку. рабочая проверял
Не нашел описание на библиотеку.
Как задать частотные полосы для фильтра?
Как вариант.
http://wiki.openmusiclabs.com/wiki/ArduinoFFT
http://wiki.openmusiclabs.com/wiki/ArduinoFHT
http://yadi.sk/d/cyD8GFReCbbh4
качайте библиотеку. рабочая проверял
Не нашел описание на библиотеку.
Как задать частотные полосы для фильтра?
честно сказать незнаю. я просто проверил рабочая или нет
К коду Zhyravlev_AS, попробывал на скорую руку выловить три канала из 64, правда у меня почему-то значения канала колеблються от 0 до 3. Пока работает так-себе, но вроде частоты смутненько проклевываються) Со временем еще поковыряюсь в этом направлении, может кому еще поможет =)
Код:
Вывод в серийник (тут попались 0 и 1 значения на каналах, но бывает еще проскакивает 2 и изредка даже 3):
И на закусочку видео, как оно работает...
https://youtu.be/6JAfFBUcNUw
Может у более опытных форумчан есть мнение - в том ли направлении я мучаюсь? :)
Есть мнение. Перед строкой 19 вставить delayMicroseconds(200);
Есть мнение. Перед строкой 19 вставить delayMicroseconds(200);
Попробывал - ситуацию не изменило.
Вобщем есть идея суммировать значения каналов с 1 по 21, с 22 по 41, с 42 по 63, и эти три суммы и использывать как нч/сч/вч.
Вопрос в том, что я не знаю, как написать такие циклы =( Попробывал пару вариантов, не бейте, самому стыдно =)
Вариант 1 (циклично бегает по цветам, не особо реагируя на сигнал):
Вариант 2 (вообще не работает, тут я понял, что не врубаюсь в циклы):
Ну незнаю даже.
Либу дернул тут https://github.com/Robmaister/LEDMusicVisualizer.
Скетч взял Ваш, поправил как советовал, номер пина да вывод поудобней сделал, получил такой
Ткнул пальцем во вход, он у меня 50Гц ;) Получил при тыкании такое
На правду похоже в общем.
Logik, только что затестил Вашу версию, единственная разница "
for
(i=0; i<3;i++)
", если там 10, вывод серийника не меняеться, кстати.Бод-рэйт пробывал разный, в скетче и мониторе порта он одинаковый
На выходе серийника либо пустота, либо каша, если потеребить пальцами или вставить/вынуть штекер в комп:
В чем может быть косяк?
Кстати компилирую и заливаю все на 0023, на 1.6.8 ругаеться сильно на библиотеку ффт, не удалось подружить..
Различия я перечислил. Номер ввода у Вас 10, он не аналоговый, delayMicroseconds(200) и вывод. Каша в выводе от отсутствия приведения к байту. Внимательней сравнивайте, или загрузите мой, проверте и затем поправте вывод как в вашем.
На всякий случай есть еще вариант полу-рабочий, однако уже заметнее разделение по частотам))
Еще заметил, что входящий сигнал делиться на 4 и из него вычитаетсья 128, убрал это, стало гораздо лучше:
Код:
Вывод в серийник при динамичной музыке:
Видео:
https://youtu.be/GVfffSM_Mjc
Различия я перечислил. Номер ввода у Вас 10, он не аналоговый, delayMicroseconds(200) и вывод. Каша в выводе от отсутствия приведения к байту. Внимательней сравнивайте, или загрузите мой, проверте и затем поправте вывод как в вашем.
Ввод во всех скетчах у меня А0, тоесть нулевой аналоговый, или я что-то упустил?
Вот код, я его тупо скопировал с Вашего поста, изменив только порт и количество циклов:
Точно, не 10 пин у Вас, а 0-й. #define AUDIOPIN 0
но и это тоже не А0, не аналоговый.
Точно, не 10 пин у Вас, а 0-й. #define AUDIOPIN 0
но и это тоже не А0, не аналоговый.
Окей, сделал #define AUDIOPIN A0
Как я и думал - причина не в этом, хотя порт и так читал (выдавал) данные 0-1023
Еще варианты? =) У меня уже идеи заканчиваються, почему идентичный код не хочет работать, еще и таким образом...
Ради хохмы сейчас перекину на A2, как у Вас =)
------------------------------------------------------------------------------
UPD Естественно смена порта ничего не дала - вывод серийника все такая-же каша или пустота при подключенном компе
каша при
Serial
.print((
byte
)(sqrt(data[i] * data[i]+im[i]*im[i]))); ?
каша при
Serial
.print((
byte
)(sqrt(data[i] * data[i]+im[i]*im[i]))); ?
Ну да, я же говорю, я скопировал код из Вашего поста, все в точности так, своего ничего не добавлял...
И скорости обмена скетча и монитора согласованы? Либу брали где? Хотя на кашу это не влияет. Там выше ссылка на github. Я запускал под ИДЕ 1.0.6.
Ладно, вечером поэксперементирую еще.
У меня другой вопрос - допустим изначальный код, который из примера спектроанализатора, рисует 64 столбика и делит диапазон частот на эти 64 столбика (интервала) (кстати с каким диапазоном он работает? 0-20000Гц?). Если мы меняем количество столбиков, допустим, на 3, он перерассчитывает всю анализируюмую полосу под 3 интервала?
Оригинальный код:
Пример под 3 интервала:
Всем доброго времени суток! Вобщем пока работает, не известно как, но работает =) Дальше буду пробывать реализовать плавное вкл/выкл каждого цвета, чтоб не мельтешила так...
Код:
Видео:
https://youtu.be/2cp0oxr5q2U
Всем здравствуйте! Тоже захотелось сделать цветомузыку, всё собрал, всё работает. Спасибо за код! Но как было написано выше, нехватает плавности. Когда долго смотришь, глаза устают. Сам не силён программировании, пытался разобраться, но пока ничего не нашел. Может кто разобрался и сможет подсказать как сделать или где почитать, как сделать?
Коль тему приподняли, а ответа не было - отвечу.
У меня другой вопрос - допустим изначальный код, который из примера спектроанализатора, рисует 64 столбика и делит диапазон частот на эти 64 столбика (интервала) (кстати с каким диапазоном он работает? 0-20000Гц?).
Это зависит от частоты дискретизации, с которой заполнен массив данных.
Если исхождить из параметров АЦП Атмеги, то примерно 0-4500. Интервалы равные в Герцах, т.е. полосы примерно по 70 Гц.
Если мы меняем количество столбиков, допустим, на 3, он перерассчитывает всю анализируюмую полосу под 3 интервала?
"Он" - это кто? FFT посчитал 64 значения, Вы выбрали из них только 3 нижних, т.е. полосы 0-70Гц, 70-140Гц и 140-210Гц, остальные не использовали.
Пытаюсь повторить
выдает ошибку
D:\ARDUINO\Sketch\libraries\fix_FFT\fix_fft.cpp:51:7: error: 'prog_int8_t' does not name a type