Многоканальная цветомузыка. Методы обработки сигнала
- Войдите на сайт для отправки комментариев
Пнд, 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) - можете посидеть и подумать, "как бы спросить по другому" (интересней/понятней).
Ну например попытатся объяснить что вы понимаете под "автокоррекцией громкости".
Возможно что-то вот типа такого вам подойдет:
#define MIC_PIN A0 int maxRawValue=300; // начальное значение диапазано int minRawValue=700; void loop(){ int rawValue=analogRead(MIC_PIN); // уточняем диапазон if(rawValue>maxRawValue)maxRawValue=rawValue; if(rawValue<minRawValue)minRawValue=rawValue; // приводым "сырое значение" к какому-то нашему "условному диапазон" от 0 до 1000 int micValue=map(rawValue, minRawValue,maxRawValue,0,1000); // тут идет ваша остальная логика. micValue будет в диапазоне от 0 до 1000 // 0 - значит "самое тихое что когда-либо было", 1000 - самый громкий звук что мы слышали }Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Всем снова доброго времени суток! Спасибо за пример автокоррекции, пока еще не пробывал, не хватает времени =)
Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Простите, но вы ошибаетесь, он работает как аналоговый вход, тут все в порядке, через серийник все видно =)
Раз уж с ФФТ ничего не выходит, подскажите пожалуйста чем можно было-бы заменить delay() в моем коде, для более своевременного реагирования на бит. Пробовал с millis(), по образцу стандартного примера, но видимо не так я одарен в коде =) Заранее благодарю!
int MicPin = 0; // пин аудиовхода int redPin = 5; int greenPin = 6; int bluePin = 3; int laserPin = 11; int stroboPin = 2; int MicValue = 0; int correction = 390; void setup() { Serial.begin(9600); pinMode(MicPin, INPUT); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); pinMode(laserPin, OUTPUT); pinMode(stroboPin, OUTPUT); } void loop() { MicValue = analogRead(MicPin)+correction; //входящий сигнал + ручная коррекция громкости Serial.println(MicValue); if (MicValue > 610) { digitalWrite(stroboPin, LOW); analogWrite(greenPin,0); analogWrite(bluePin,0); analogWrite(redPin,0); delay(3); // стробоскопным 10Вт диодом временно управляет реле, поэтому 5 или 0, впринципе и транзистором также можно управлять, только резистор подобрать } else { digitalWrite(stroboPin, HIGH); delay(8); } if (MicValue > 450 && MicValue <490) { analogWrite(bluePin,255); delay(10); } else { analogWrite(bluePin,0); delay(3); } if (MicValue > 480 && MicValue <520) { analogWrite(greenPin,255); delay(15); } else { analogWrite(greenPin,0); delay(3); } delay(10); if (MicValue > 510 && MicValue <600) { analogWrite(redPin,255); delay(10); } else { analogWrite(redPin,0); delay(3); } if (MicValue > 400) { digitalWrite(laserPin, LOW); delay(5); } else { digitalWrite(laserPin, HIGH); delay(10); }>чем можно было-бы заменить delay()
функцией millis(). После прочтения примеров из документации. В шапке сайта линк "Програмирование", потом смотрим в правую колонку, там есть раздел "примеры", ищем пример который вроде подходит по смыслу. Пытаемся понять принцип его работы. Так же поиск по форуму может помоч.
Вот что у меня есть:
#include <fix_fft.h> #define AUDIOPIN 5 char im[128], data[128]; int i=0, val; void setup() { Serial.begin(9600); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // здесь i это канал от 1 до 64, каждый канал принимает значение от 0 до 15 насколько я сам это понял. } }Всем снова доброго времени суток! Спасибо за пример автокоррекции, пока еще не пробывал, не хватает времени =)
А зачем тогда "поехали дальше" если этот этап не прошли?
Кстати, вам вашем варианте
pinMode(MicPin, INPUT);
включит на вход не аналогвый пин, а цифровой.
Кстати2, по умолчанию все пины и так включены на вход, так что делать pinMode(...,INPUT) - не обазательно.
Простите, но вы ошибаетесь, он работает как аналоговый вход, тут все в порядке, через серийник все видно =)
Спорим на биткоины что ошибаетесь вы? Я же не сказал "работать не будет", я сказал что "делает оно не то что вы думаете". К счастью эти ошибочные танцевальные движения - не приводят к неработоспособности в этом конкретном скетче. Но если вы не разберетесь с этим вопре рано или поздно вы таким образом либо словите глюк, либо когда перепутаете какому именно пиноу вы настраиваете режим при настройке на Output, - упалите ногу.
Итак: У вас есть два пина. D0 и A0. Оба уже включены на INPUT. И вообщем-то не требует инкаких настроек. Но вы захотели все-таки еще раз, явно указать. Это ничего не меняет, но является нормальной практикой. Для читабельности кода - вполне полезно. Но... pinMode вы сделали для D0, а не A0!!! И "ничего не поломалось", только потому что они уже оба были включены на INPUT.
Далее, вы пытаетесь делать analogRead с цифрового входа. Но... к счастью вы не первый кто так делают, поэтому те кто писал функцию analogRead - уже предусмотрели это. И внутри себя она имеет "защиту от дурака", если есть скормили цифровой пин, она сама, внутри поправляет его на аналоговый. Только поэтому у вас и работает. Но вот это "логика поправления" - не документирована, следовательно, хоть и маловероятно но в будущих версиях - ее могут убрать. Или появятся новые платы, в которых просто по номеру будет не просто понять про какой же пин идет речь (и сделать "поправку" станет не возможным).
Вот что у меня есть:
И где тут видно попытки применить millis()? Даже delay() что-бы понять что вы хотите - и то нет.
Вот что у меня есть:
#include <fix_fft.h> #define AUDIOPIN 5 char im[128], data[128]; int i=0, val; void setup() { Serial.begin(9600); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // здесь i это канал от 1 до 64, каждый канал принимает значение от 0 до 15 насколько я сам это понял. } }Вот это какраз и есть то, что я не смог понять в ффт. i понятное дело перебирает каналы, с 1 по 63, а вот как поймать значение нужного канала? Например значение канала 1, 25, 50, 60? Мне-то по сути 3-5 каналов и нужно, правда широких. Допустим первый до 500Гц (низ), второй от 500Гц до 1500Гц , третий от 1500 до 3000Гц и т.п..
Покажите пожалуйсто пример с одним каналом и выводом его в серийник, мне хочеться разобраться как оно работает, а тогда я уже смогу подогнать все под свои нужды =) Естественно результатом поделюсь, думаю не мне одному такое интересно =) Заранее благодарю!
Уважаемый leshak, пробывал как вы советовали, тоже правда не до конца воткнул как работает этот алгоритм. Все время 0 после обработки. И пофиг ему что на входе =(
#define MIC_PIN A0 int maxRawValue=300; // начальное значение диапазано int minRawValue=700; void loop(){ int rawValue=analogRead(MIC_PIN); // уточняем диапазон if(rawValue>maxRawValue)maxRawValue=rawValue; if(rawValue<minRawValue)minRawValue=rawValue; // приводым "сырое значение" к какому-то нашему "условному диапазон" от 0 до 1000 int micValue=map(rawValue, minRawValue,maxRawValue,0,1000); // тут идет ваша остальная логика. micValue будет в диапазоне от 0 до 1000 // 0 - значит "самое тихое что когда-либо было", 1000 - самый громкий звук что мы слышали }Тема умерла?
Прикрутил к 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. Пока работает так-себе, но вроде частоты смутненько проклевываються) Со временем еще поковыряюсь в этом направлении, может кому еще поможет =)
Код:
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int out = 0; int br = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(9600); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); if (i == 21) { out = data[i]; Serial.print("low - "); Serial.println(out); Serial.println(val); if (out == 0) {analogWrite(redPin,0);} if (out == 1) {analogWrite(redPin,100);} if (out == 2) {analogWrite(redPin,200);} if (out > 3) {analogWrite(redPin,255);}} if (i == 42) { out = data[i]; Serial.print("mid - "); Serial.println(out); Serial.println(val); if (out == 0) {analogWrite(bluePin,0);} if (out == 1) {analogWrite(bluePin,100);} if (out == 2) {analogWrite(bluePin,200);} if (out > 3) {analogWrite(bluePin,255);}} if (i == 60) { out = data[i]; Serial.print("hi - "); Serial.println(out); Serial.println(val); if (out == 0) {analogWrite(greenPin,0);} if (out == 1) {analogWrite(greenPin,100);} if (out == 2) {analogWrite(greenPin,200);} if (out > 3) {analogWrite(greenPin,255);}} } }Вывод в серийник (тут попались 0 и 1 значения на каналах, но бывает еще проскакивает 2 и изредка даже 3):
И на закусочку видео, как оно работает...
https://youtu.be/6JAfFBUcNUw
Может у более опытных форумчан есть мнение - в том ли направлении я мучаюсь? :)
Есть мнение. Перед строкой 19 вставить delayMicroseconds(200);
Есть мнение. Перед строкой 19 вставить delayMicroseconds(200);
Попробывал - ситуацию не изменило.
Вобщем есть идея суммировать значения каналов с 1 по 21, с 22 по 41, с 42 по 63, и эти три суммы и использывать как нч/сч/вч.
Вопрос в том, что я не знаю, как написать такие циклы =( Попробывал пару вариантов, не бейте, самому стыдно =)
Вариант 1 (циклично бегает по цветам, не особо реагируя на сигнал):
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int outlow = 0; int outmid = 0; int outhi = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // здесь i это канал от 1 до 64, каждый канал принимает значение от 0 до 15 насколько я сам это понял. if (i > 0 && i < 22) {outlow = outlow + data[i];} Serial.print("low - "); Serial.println(outlow); Serial.println(val); analogWrite(redPin, outlow * 5); if (i > 22 && i < 42) {outmid = outmid + data[i];} Serial.print("mid - "); Serial.println(outmid); Serial.println(val); analogWrite(bluePin, outmid * 5); if (i > 42 && i < 63) {outhi = outhi + data[i];} Serial.print("hi - "); Serial.println(outhi); Serial.println(val); analogWrite(greenPin, outhi * 5); } outlow = 0; outmid = 0; outhi = 0; }Вариант 2 (вообще не работает, тут я понял, что не врубаюсь в циклы):
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int outlow = 0; int outmid = 0; int outhi = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // здесь i это канал от 1 до 64, каждый канал принимает значение от 0 до 15 насколько я сам это понял. do {outlow = outlow + data[i];} while (i<22); Serial.print("low - "); Serial.println(outlow); Serial.println(val); analogWrite(redPin, outlow * 5); do {outmid = outmid + data[i];} while (i<42); Serial.print("mid - "); Serial.println(outmid); Serial.println(val); analogWrite(bluePin, outmid * 5); do {outhi = outhi + data[i];} while (i<63); Serial.print("hi - "); Serial.println(outhi); Serial.println(val); analogWrite(greenPin, outhi * 5); } outlow = 0; outmid = 0; outhi = 0; }Ну незнаю даже.
Либу дернул тут https://github.com/Robmaister/LEDMusicVisualizer.
Скетч взял Ваш, поправил как советовал, номер пина да вывод поудобней сделал, получил такой
#include <fix_fft.h> #define AUDIOPIN A2 char im[128], data[128]; int i=0, val; int outlow = 0; int outmid = 0; int outhi = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); delayMicroseconds(200); data[i] = val/4 -128; im[i] = 0; } fix_fft(data,im,7,0); for (i=0; i<10;i++) { Serial.print((byte)(sqrt(data[i] * data[i]+im[i]*im[i]))); Serial.print("\t"); } Serial.println(); }Ткнул пальцем во вход, он у меня 50Гц ;) Получил при тыкании такое
На правду похоже в общем.
Logik, только что затестил Вашу версию, единственная разница "
for(i=0; i<3;i++)", если там 10, вывод серийника не меняеться, кстати.Бод-рэйт пробывал разный, в скетче и мониторе порта он одинаковый
На выходе серийника либо пустота, либо каша, если потеребить пальцами или вставить/вынуть штекер в комп:
В чем может быть косяк?
Кстати компилирую и заливаю все на 0023, на 1.6.8 ругаеться сильно на библиотеку ффт, не удалось подружить..
Различия я перечислил. Номер ввода у Вас 10, он не аналоговый, delayMicroseconds(200) и вывод. Каша в выводе от отсутствия приведения к байту. Внимательней сравнивайте, или загрузите мой, проверте и затем поправте вывод как в вашем.
На всякий случай есть еще вариант полу-рабочий, однако уже заметнее разделение по частотам))
Еще заметил, что входящий сигнал делиться на 4 и из него вычитаетсья 128, убрал это, стало гораздо лучше:
for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); data[i] = val/4-128; im[i] = 0;Код:
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int out = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); } 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=1; i<64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); if (i == 2) { out = data[i]; Serial.print("low - "); Serial.println(out); Serial.println(val); if (out <= 6) {analogWrite(redPin,0);} if (out >= 8) {analogWrite(redPin,255);}} if (i == 30) { out = data[i]; Serial.print("mid - "); Serial.println(out); Serial.println(val); if (out <= 2) {analogWrite(bluePin,0);} if (out >= 4) {analogWrite(bluePin,255);}} if (i == 58) { out = data[i]; Serial.print("hi - "); Serial.println(out); Serial.println(val); if (out <= 3) {analogWrite(greenPin,0);} if (out >= 5) {analogWrite(greenPin,255);}} } }Вывод в серийник при динамичной музыке:
Видео:
https://youtu.be/GVfffSM_Mjc
Различия я перечислил. Номер ввода у Вас 10, он не аналоговый, delayMicroseconds(200) и вывод. Каша в выводе от отсутствия приведения к байту. Внимательней сравнивайте, или загрузите мой, проверте и затем поправте вывод как в вашем.
Ввод во всех скетчах у меня А0, тоесть нулевой аналоговый, или я что-то упустил?
Вот код, я его тупо скопировал с Вашего поста, изменив только порт и количество циклов:
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int out = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); } void loop() { for (i=0; i < 128; i++){ val = analogRead(AUDIOPIN); delayMicroseconds(200); data[i] = val/4-128; im[i] = 0; } fix_fft(data,im,7,0); for (i=1; i<3;i++){ Serial.print((byte)(sqrt(data[i] * data[i]+im[i]*im[i]))); Serial.print("\t");} Serial.println(); }Точно, не 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 интервала?
Оригинальный код:
#include <TVout.h> #include <fix_fft.h> TVout TV; char im[128], data[128], lastpass[64]; char x=32, ylim=90; int i=0,val; void setup() { TV.begin(_NTSC,128,96); // Initialize TV output, 128x96. TV.print_str(2,2," Realtime Arduino"); // TVout lib uses x,y for print TV.print_str(2,11," Spectrum Analyzer"); // statements. 8x8 default font. analogReference(DEFAULT); // Use default (5v) aref voltage. for (int z=0; z<64; z++) {lastpass[z]=80;}; // fill the lastpass[] array with dummy data }; void loop() { for (i=0; i < 128; i++){ // We don't go for clean timing here, it's val = analogRead(0); // better to get somewhat dirty data fast data[i] = val/4 -128; // than to get data that's lab-accurate im[i] = 0; // but too slow, for this application. }; fix_fft(data,im,7,0); for (i=1; i< 64;i++){ // In the current design, 60Hz and noise data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // in general are a problem. Future designs TV.draw_line(i+x,lastpass[i],i+x,ylim,0); // and code may fix this, but for now, I TV.draw_line(i+x,ylim,i+x,ylim-data[i],1); // skip displaying the 0-500hz band completely. lastpass[i]=ylim-data[i]; // if you insist, initialize the loop with 0 }; // rather than 1. };Пример под 3 интервала:
#include <TVout.h> #include <fix_fft.h> TVout TV; char im[128], data[128], lastpass[64]; char x=32, ylim=90; int i=0,val; void setup() { TV.begin(_NTSC,128,96); // Initialize TV output, 128x96. TV.print_str(2,2," Realtime Arduino"); // TVout lib uses x,y for print TV.print_str(2,11," Spectrum Analyzer"); // statements. 8x8 default font. analogReference(DEFAULT); // Use default (5v) aref voltage. for (int z=0; z<64; z++) {lastpass[z]=80;}; // fill the lastpass[] array with dummy data }; void loop() { for (i=0; i < 128; i++){ // We don't go for clean timing here, it's val = analogRead(0); // better to get somewhat dirty data fast data[i] = val/4 -128; // than to get data that's lab-accurate im[i] = 0; // but too slow, for this application. }; fix_fft(data,im,7,0); for (i=1; i< 3;i++){ // In the current design, 60Hz and noise data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // in general are a problem. Future designs TV.draw_line(i+x,lastpass[i],i+x,ylim,0); // and code may fix this, but for now, I TV.draw_line(i+x,ylim,i+x,ylim-data[i],1); // skip displaying the 0-500hz band completely. lastpass[i]=ylim-data[i]; // if you insist, initialize the loop with 0 }; // rather than 1. };Всем доброго времени суток! Вобщем пока работает, не известно как, но работает =) Дальше буду пробывать реализовать плавное вкл/выкл каждого цвета, чтоб не мельтешила так...
Код:
#include <fix_fft.h> #define AUDIOPIN 0 char im[128], data[128]; int i=0, val; int out = 0; int br = 0; int redPin = 5; // pins that the LED are attached to int greenPin = 6; int bluePin = 3; void setup() { Serial.begin(19200); analogWrite(redPin,0); // just test connections analogWrite(greenPin,0); analogWrite(bluePin,0); delay(500); analogWrite(redPin,255); delay(500); analogWrite(redPin,0); analogWrite(greenPin,255); delay(500); analogWrite(greenPin,0); analogWrite(bluePin,255); delay(500); analogWrite(bluePin,0); } 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<3;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); if (i == 0) { out = data[i]; Serial.print("low - "); Serial.println(out); Serial.println(val); if (out <= 9) {analogWrite(redPin,0);} if (out >= 13) {analogWrite(redPin,out*10);}} if (i == 1) { out = data[i]; Serial.print("mid - "); Serial.println(out); Serial.println(val); if (out <= 5) {analogWrite(bluePin,0);} if (out >= 10) {analogWrite(bluePin,out*10);}} if (i == 2) { out = data[i]; Serial.print("hi - "); Serial.println(out); Serial.println(val); if (out <= 4) {analogWrite(greenPin,0);} if (out >= 8) {analogWrite(greenPin,out*10);}} } }Видео:
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