Цветомузыка Arduino + FFT на 3 полосы

hypersash
Offline
Зарегистрирован: 07.12.2011

Всем доброго времени суток! Пытаюсь сделать цветомузыку на ардуине, копаюсь в библиотеке 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 
 
 
Почему реальное значение на пинах не меняеться? =(

 

hypersash
Offline
Зарегистрирован: 07.12.2011

Код примеров:

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.
    };

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Я, если честно, не совсем понял ваш вопрос. Но обычно, если у человека не работает как надо rgb-светодиод - наиболее вероятно, что он пытается управлять им, как светодиодом с общин катодом, когда тот, на сомом деле имеет общий анод.

Araris
Offline
Зарегистрирован: 09.11.2012

Строки

  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 на самом деле.

 

hypersash
Offline
Зарегистрирован: 07.12.2011

Да, действительно, глупая ошибка, сорри :) поправил, теперь пины дергаються исправно, правда значение на них при аудио сигнале стало колебаться 72-89, при тишине 72+-2. Я вообще слабо понимаю как с ффт работать :( подскажете чегонить? ^.^

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

hypersash пишет:
Я вообще слабо понимаю как с ффт работать :( подскажете чегонить? ^.^

Для начала: 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...

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Здравствуйте, изучаю библиотеку 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
     }
   } 
  }
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Подключила источник аудиосигнала к 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]

inspiritus
Offline
Зарегистрирован: 17.12.2012

Посмотрите ЭТО , меня впечатлило. Может быть Вам не мучаться, а повторить ?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Хочу разобраться с вышеуказанной библиотекой

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вот так в сериал монитор сыпятся цыфры

#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);    
}
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ерунда какая-то получается

#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();  
//  }


}

}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Как мне усилить звуковой сигнал чтобы получить от  до 5 вольт?

negavoid
Offline
Зарегистрирован: 09.07.2016

Аппаратно, усилителем любого класса на транзисторе или микросхеме; или программно, перемножить массив сигнала на соответствующую константу.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Но здесь динамик подключен к плюсу, а мне нужно подать плюс на А5

negavoid
Offline
Зарегистрирован: 09.07.2016

Взглянул на схемку повыше, а вы там сейчас подаёте сигнал напрямую с динамика на А0, что ли? Ой, вэй ))) И Фурье не работает, как полагается? Ну дык, так и должно быть :)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Так я и поняла уже, что без усиленияработать не будет

negavoid
Offline
Зарегистрирован: 09.07.2016

Какие всё-таки молодцы инженеры из avr, порт насилуют, а он не горит, ещё и трепыхается как-то =)

Вот смотрите, динамик качается туда-сюда, издаёт звук, а качает катушку в разные стороны переменный ток. С точки зрения порта А5, на входе у него много раз в секунду меняется плюс с минусом, с размахом амплитуды того, что на выходе усилителя для динамика. Если заглянуть в даташит атмеги, то там сказано, что нельзя подавать минус на АЦП, иначе может произойти ай-ай-ай. Поэтому, прежде, чем подать сигнал на ацп, его надо "приподнять", неплохим выбором для начала может стать значение 2.5 Вольта. И усиливать тоже пока ничего не нужно, там наверное и так вполне достаточно на выходе. Это я не вспоминаю, что ещё и развязки нету, теки постоянное, всё что хочешь, с исходного девайса на бедный пин...

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Смысл выших слов полностью мне понятен, не понятно как это реализовать.

negavoid
Offline
Зарегистрирован: 09.07.2016

Подтяжку - делителем напряжения, развязку - конденсатором.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Так как то?

negavoid
Offline
Зарегистрирован: 09.07.2016

Как-то так. Посмотрел код, там у вас тоже ого-го, демодуляцию даже прикрутили для магнитуд ) И для ардуины попробуйте лучше Хартли вместо Фурье: http://wiki.openmusiclabs.com/wiki/ArduinoFHT

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
 for (i=0; i < 16; i++){                                     
val = analogRead(AUDIOPIN);                                    
data[i] = val;                                       
};

Помогите создать вункцию определения наибольшего и наименьшего числа в массиве

Kanal: 0 Signal: 531

Kanal: 1 Signal: 532
Kanal: 2 Signal: 530
Kanal: 3 Signal: 525
Kanal: 4 Signal: 519
Kanal: 5 Signal: 516
Kanal: 6 Signal: 518
Kanal: 7 Signal: 522
Kanal: 8 Signal: 520
Kanal: 9 Signal: 514
Kanal: 10 Signal: 509
Kanal: 11 Signal: 511
Kanal: 12 Signal: 514
Kanal: 13 Signal: 517
Kanal: 14 Signal: 518
Kanal: 15 Signal: 513

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
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?

negavoid
Offline
Зарегистрирован: 09.07.2016

:) потому что исходное int val_min = 0 всегда меньше, чем 500. Инициализируйте его значением 1024.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Благодарю 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Сделала я вот так. Эффек нууууу на 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кОм к минусу.

 

negavoid
Offline
Зарегистрирован: 09.07.2016

Можно и не вместо, а вместе. Ну отлично, поздравляю, с амплитудой разобрались, 72ХХ показывает размах громче-тише (на квадратном дисплее, в одну строку, гм, ну да, наверное на троечку и должно смотреться). Теперь переходите к частотному анализу, делайте над аудиобуфером Фурье или Хартли, децимируйте до количества вертикальных бинов на матрице, и рисуйте.

// небольшое примечаньице, делайте уж лучше вот так
for(int i = 0; i < 32; i++) 
{
    val_max = max(data[i], val_max);
    val_min = min(data[i], val_min);
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Если громкость, то есть мощгность недостаточная, эффект плохой, в начале видео видно. Как с этим бороться?

negavoid
Offline
Зарегистрирован: 09.07.2016

Ну как в коде написано - так и выводится. В начале амплитуда маленькая и всего один из 32 отсчётов раскачивает одну точку.