Цветомузыка Arduino + FFT на 3 полосы
- Войдите на сайт для отправки комментариев
Ср, 18/11/2015 - 00:02
Всем доброго времени суток! Пытаюсь сделать цветомузыку на ардуине, копаюсь в библиотеке FFT, пока на основе примеров (гугляться по Arduino FFT) преобразовал скетч, в сериал мониторе все шорошо, при том что значения считываю с выходных пинов, но на реальных пинах 1,77В и лента горит белым. Уже все что только в голову пришло перепробывал, всеравно белым горит. Не понимаю, почему реальное значение выходным пинам не устанавляваеться, при этом сериал с этих пинов выводит правильные и красивые значения... =(
Скетч:
#include <fix_fft.h> // include the library
char im[128], data[128], lastpass[64];
char x=32, ylim=90;
int i=0,val;
int r = 5; // красный пин
int g = 6; // зеленый пин
int b = 3; // синий пин
int rv = 0;
int bv = 0;
int gv = 0;
//int a = 0;
void setup() {
for (int z=0; z<64; z++) {lastpass[z]=80;}
Serial.begin(9600);
pinMode(b, OUTPUT);
pinMode(r, OUTPUT);
pinMode(g, OUTPUT);
}
void loop() {
for (i=0; i < 128; i++){
val = analogRead(0);
data[i] = val/4 - 3;
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]);
//for (a=0; a<=3; a++)
rv = (i+x,lastpass[i],i+x,ylim);
gv = (i+x,lastpass[i],i+x,ylim);
bv = (i+x,lastpass[i],i+x,ylim);
/*(r, (i+x,ylim,i+x,ylim-data[i],255));
(g, (i+x,ylim,i+x,ylim-data[i],255));
(b, (i+x,ylim,i+x,ylim-data[i],255));*/
lastpass[i]=ylim-data[i];
}
analogWrite (r, rv); //вывод на пины
analogWrite (g, gv);
analogWrite (b, bv);
Serial.print ("B - ");
Serial.print (analogRead(b));
Serial.println (" ");
Serial.print ("R - ");
Serial.print (analogRead(r));
Serial.println (" ");
Serial.print ("G - ");
Serial.print (analogRead(g));
Serial.println (" ");
delay(5); // всеравно какое значение, не помогает
}
Вывод в сериал музыки:
R - 22
G - 38
B - 0
R - 8
G - 25
B - 190
R - 111
G - 98
B - 30
R - 73
G - 87
B - 0
R - 32
G - 53
B - 62
R - 56
G - 65
B - 0
R - 25
G - 37
B - 0
R - 9
G - 26
B - 53
R - 43
G - 49
B - 75
R - 66
G - 70
B - 0
R - 33
G - 48
B - 0
R - 9
G - 29
B - 38
R - 35
G - 45
B - 43
R - 45
G - 55
B - 37
R - 48
G - 60
B - 154
R - 108
G - 101
B - 15
R - 63
G - 76
B - 0
R - 24
G - 44
B - 0
R - 21
G - 38
B - 63
R - 49
G - 57
B - 0
R - 22
G - 37
B - 0
R - 5
G - 21
B - 75
R - 53
G - 56
B - 179
R - 122
G - 113
B - 28
R - 74
G - 87
B - 0
R - 33
G - 52
B - 55
R - 52
G - 62
B - 81
R - 73
G - 78
B - 67
R - 75
G - 83
B - 0
R - 40
G - 60
B - 204
R - 135
G - 120
B - 31
R - 82
G - 95
B - 47
R - 70
G - 84
B - 93
R - 88
G - 93
B - 0
R - 45
G - 64
B - 0
R - 31
G - 49
B - 0
R - 25
G - 40
B - 0
R - 9
G - 28
B - 0
R - 0
G - 20
B - 0
R - 0
G - 16
B - 16
R - 21
G - 32
B - 0
R - 5
G - 21
B - 0
R - 0
G - 16
B - 37
R - 30
G - 39
B - 0
R - 10
G - 27
B - 0
R - 11
G - 27
B - 58
R - 44
G - 50
B - 0
R - 27
G - 44
B - 0
R - 12
G - 31
B - 1
R - 16
G - 32
B - 0
R - 7
G - 24
B - 63
R - 44
G - 49
B - 0
R - 19
G - 36
B - 64
R - 51
G - 58
B - 0
R - 23
G - 42
B - 0
R - 18
G - 34
B - 99
R - 69
G - 70
B - 93
R - 85
G - 87
B - 0
R - 43
G - 61
B - 26
R - 43
G - 57
B - 0
Вывод в сериал тишины:
R - 43
G - 57
B - 27
R - 40
G - 55
B - 26
R - 42
G - 55
B - 27
R - 42
G - 56
B - 27
R - 42
G - 55
B - 29
R - 42
G - 56
B - 27
R - 42
G - 55
B - 28
R - 41
G - 55
B - 27
Почему реальное значение на пинах не меняеться? =(
Код примеров:
http://www.polesite.ru/?p=1260
#include <glcd.h> #include <fix_fft.h> char im[128], data[128], lastpass[64]; char x=32, ylim=64; int i=0,val; void setup() { GLCD.Init(); GLCD.ClearScreen(); for (int z=0; z<64; z++) {lastpass[z]=80;} } void loop() { for (i=0; i < 128; i++){ val = analogRead(0); data[i] = val -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]); GLCD.DrawLine(i+x,lastpass[i],i+x,ylim,WHITE); GLCD.DrawLine(i+x,ylim,i+x,ylim-data[i],BLACK); lastpass[i]=ylim-data[i]; } }http://arduino.ru/projects/analizator-spektra-zvuka-na-arduino
#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. };Я, если честно, не совсем понял ваш вопрос. Но обычно, если у человека не работает как надо rgb-светодиод - наиболее вероятно, что он пытается управлять им, как светодиодом с общин катодом, когда тот, на сомом деле имеет общий анод.
Строки
Serial.print ("B - "); Serial.print (analogRead(b)); Serial.println (" "); Serial.print ("R - "); Serial.print (analogRead(r)); Serial.println (" "); Serial.print ("G - "); Serial.print (analogRead(g)); Serial.println (" ");достаточно бессмыслены, поскольку analogRead() - это функция, считывающая значение с аналогового входа (а у Вас цифровые пины в режиме output).
Напишите лучше Serial.print(b); и т.п. и посмотрите, какие значения имеют r,g,b на самом деле.
Да, действительно, глупая ошибка, сорри :) поправил, теперь пины дергаються исправно, правда значение на них при аудио сигнале стало колебаться 72-89, при тишине 72+-2. Я вообще слабо понимаю как с ффт работать :( подскажете чегонить? ^.^
Для начала: https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%A4%D1%83%D1%80%D1%8C%D0%B5
А для самого начала: https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2...
Здравствуйте, изучаю библиотеку FFT на одном из примеров из интернета
#include <fix_fft.h> #define AUDIOPIN 5//пин подключения аудиосигнала char im[128], data[128]; char data_avgs[14]; int i=0,val; void setup() { } 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]); }; //Если я правильно понимаю, то здесь я получаю переменную data(0,1,2,3...64) со значениями от 0 до 30, верно? for (i=0; i<14; i++) { data_avgs[i] = data[i*4] + data[i*4 + 1] + data[i*4 + 2] + data[i*4 + 3]; //что происходит в этой строке? А если столбцов не 14? data_avgs[i] = map(data_avgs[i], 0, 30, 0, 9); //здесь понятно, маштабируем значения 0-30 в 0-9 } for (int x=0; x < 14; x++) { for (int y=0; y < 9; y++) { if (y < data_avgs[13-x]) { // 13-x меняет порядок строк так, чтобы частоты от низких к высоким показывались слева направо. LedSign::Set(x,y,1); // set the LED on } else { LedSign::Set(x,y,0); // set the LED off } } } }Подключила источник аудиосигнала к Gnd и A5
for (i=0; i< 64;i++){ data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); Serial.print("Kanal: "); Serial.print(i); Serial.print(" Signal: "); Serial.print(data[i]); Serial.println("") ; };Получаю пустые строки data[i]
Посмотрите ЭТО , меня впечатлило. Может быть Вам не мучаться, а повторить ?
Хочу разобраться с вышеуказанной библиотекой
Вот так в сериал монитор сыпятся цыфры
#include <fix_fft.h> #define AUDIOPIN 5 char im[128], data[128]; char data_avgs[14]; int i=0,val; void setup() { Serial.begin(9600); } 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]); }; 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); } for (int x=0; x < 14; x++) { Serial.print("Kanal: "); Serial.print(x); Serial.print(" Signal: "); Serial.print(data_avgs[x], HEX); Serial.println("") ; delay(100); } }Ерунда какая-то получается
#include <SPI.h> #include <Adafruit_GFX.h> #include <Max72xxPanel.h> int pinCS = 9; int numberOfHorizontalDisplays = 4; // количество матриц по-горизонтали int numberOfVerticalDisplays = 1; // количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); #include <fix_fft.h> #define AUDIOPIN 5 char im[128], data[128]; char data_avgs[14]; int i=0,val; void setup() { Serial.begin(9600); matrix.setIntensity(4); // яркость от 0 до 15 } 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]); }; 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, 7); } for (int x=0; x < 8; x++) { String str(data_avgs[x],HEX); matrix.fillScreen(LOW); //for (int y=0; y<data_avgs[x]; y++){ matrix.drawPixel(data_avgs[x], x, HIGH); // вертикаль, горизонталь matrix.write(); // } } }Как мне усилить звуковой сигнал чтобы получить от до 5 вольт?
Аппаратно, усилителем любого класса на транзисторе или микросхеме; или программно, перемножить массив сигнала на соответствующую константу.
Но здесь динамик подключен к плюсу, а мне нужно подать плюс на А5
Взглянул на схемку повыше, а вы там сейчас подаёте сигнал напрямую с динамика на А0, что ли? Ой, вэй ))) И Фурье не работает, как полагается? Ну дык, так и должно быть :)
Так я и поняла уже, что без усиленияработать не будет
Какие всё-таки молодцы инженеры из avr, порт насилуют, а он не горит, ещё и трепыхается как-то =)
Вот смотрите, динамик качается туда-сюда, издаёт звук, а качает катушку в разные стороны переменный ток. С точки зрения порта А5, на входе у него много раз в секунду меняется плюс с минусом, с размахом амплитуды того, что на выходе усилителя для динамика. Если заглянуть в даташит атмеги, то там сказано, что нельзя подавать минус на АЦП, иначе может произойти ай-ай-ай. Поэтому, прежде, чем подать сигнал на ацп, его надо "приподнять", неплохим выбором для начала может стать значение 2.5 Вольта. И усиливать тоже пока ничего не нужно, там наверное и так вполне достаточно на выходе. Это я не вспоминаю, что ещё и развязки нету, теки постоянное, всё что хочешь, с исходного девайса на бедный пин...
Смысл выших слов полностью мне понятен, не понятно как это реализовать.
Подтяжку - делителем напряжения, развязку - конденсатором.
Так как то?
Как-то так. Посмотрел код, там у вас тоже ого-го, демодуляцию даже прикрутили для магнитуд ) И для ардуины попробуйте лучше Хартли вместо Фурье: http://wiki.openmusiclabs.com/wiki/ArduinoFHT
for (i=0; i < 16; i++){ val = analogRead(AUDIOPIN); data[i] = val; };Помогите создать вункцию определения наибольшего и наименьшего числа в массиве
Kanal: 0 Signal: 531
int vals[16] = {532,530,525,519,516,518,522,520,564,509,511,514,517,518,513}; int val_max = 0; for(int i = 0; i < 16; i++) val_max = max(vals[i], val_max); Serial.println(val_max);Максимальное нашла
int vals[16] = {532,530,525,519,516,518,522,520,564,509,511,514,517,518,513}; int val_min = 0; for(int i = 0; i < 16; i++) val_mmin = min(vals[i], val_min); Serial.println(val_min);Почему минимальное пишет 0?
:) потому что исходное int val_min = 0 всегда меньше, чем 500. Инициализируйте его значением 1024.
Благодарю
Сделала я вот так. Эффек нууууу на 3 с +
#define AUDIOPIN 5 //Пин подключения аудиосигнала #include <SPI.h> #include <Adafruit_GFX.h> #include <Max72xxPanel.h> int pinCS = 9; int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали int numberOfVerticalDisplays = 4; // количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); int data[32]; int i=0,val; int val_max = 0; int val_min = 1024; void setup() { Serial.begin(9600); matrix.setIntensity(3); // яркость от 0 до 15 } void loop() { for (i=0; i < 32; i++){ val = analogRead(AUDIOPIN); data[i] = val; }; for(int i = 0; i < 32; i++) val_max = max(data[i], val_max); for(int i = 0; i < 32; i++) val_min = min(data[i], val_min); for (i=0; i< 32;i++){ //Serial.print("Kanal: "); //Serial.print(i); //Serial.print(" Signal: "); data[i] = map(data[i], val_min, val_max, 0, 7); Serial.print(data[i]); //Serial.println("") ; matrix.fillScreen(LOW); for (int r=0; r< data[i];r++){ matrix.drawPixel(r, i, HIGH); matrix.write(); }; }; } Подключила вместо одного из динамиков компьютерных калонок, вход А5 через 1кОм к минусу.Можно и не вместо, а вместе. Ну отлично, поздравляю, с амплитудой разобрались, 72ХХ показывает размах громче-тише (на квадратном дисплее, в одну строку, гм, ну да, наверное на троечку и должно смотреться). Теперь переходите к частотному анализу, делайте над аудиобуфером Фурье или Хартли, децимируйте до количества вертикальных бинов на матрице, и рисуйте.
// небольшое примечаньице, делайте уж лучше вот так for(int i = 0; i < 32; i++) { val_max = max(data[i], val_max); val_min = min(data[i], val_min); }https://youtu.be/llRJdJ8Rf8s
Видео
Если громкость, то есть мощгность недостаточная, эффект плохой, в начале видео видно. Как с этим бороться?
Ну как в коде написано - так и выводится. В начале амплитуда маленькая и всего один из 32 отсчётов раскачивает одну точку.