Audio Spectrum Analyzer Arduino + LCD 2x16 - Jika sebelumnya artikel yang saya bahas tentang sensor suhu digital yang ditampilkan dengan menggunakan sebuah LCD 2x16, artikel kali ini juga saya masih berhubungan dengan LCD 2x16 sebagai penampilnya, alat yang dibuat yaitu Audio Spectrum Analyzer yang berbasis mikrokontroller Aduino.
Audio Spectrum Analyzer berfungsi sebagai indikator frekuensi sinyal dari suara yang bisa di gunakan pada amplifier.
Wiring Arduino :
Untuk coding arduino silahkan copy code berikut ke software arduino
/* FFT_TEST4 Ray Burnette 20130810 function clean-up & 1284 port (328 verified) Uses 2x16 Parallel LCD in 4-bit mode, see LiquidCrystal lib call for details http://forum.arduino.cc/index.php?PHPSESSID=4karr49jlndufvtlqs9pdd4g96&topic=38153.15 Modified by varind in 2013: this code is public domain, enjoy! http://www.variableindustries.com/audio-spectrum-analyzer/ 328P = Binary sketch size: 5,708 bytes (of a 32,256 byte maximum) 1284P= Binary sketch size: 5,792 bytes (of a 130,048 byte maximum) Free RAM = 15456 Binary sketch size: 8,088 bytes (of a 130,048 byte maximum) (Debug) */ #include <LiquidCrystal.h> #include <fix_fft.h> #define DEBUG 0 #define L_IN 1 // Audio input A0 Arduino #define R_IN 0 // Audio input A1 Arduino const int Yres = 8; const int gain = 3; float peaks[64]; char im[64], data[64]; char Rim[64], Rdata[64]; char data_avgs[64]; int debugLoop; int i; int load; LiquidCrystal lcd(11, 10, 7, 6, 5, 4); // pins to LCD // Custom CHARACTERS byte v1[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111 }; byte v2[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111 }; byte v3[8] = { B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 }; byte v4[8] = { B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111 }; byte v5[8] = { B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111 }; byte v6[8] = { B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111 }; byte v7[8] = { B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; byte v8[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; void setup() { if (DEBUG) { Serial.begin(9600); // hardware serial Serial.print("Debug ON"); Serial.println(""); } lcd.begin(16, 2); lcd.clear(); lcd.createChar(1, v1); lcd.createChar(2, v2); lcd.createChar(3, v3); lcd.createChar(4, v4); lcd.createChar(5, v5); lcd.createChar(6, v6); lcd.createChar(7, v7); lcd.createChar(8, v8); for (i=0;i<80;i++) { for (load = 0; load < i / 5; load++) { lcd.setCursor(load, 1); lcd.write(5); } if (load < 1) { lcd.setCursor(0, 1); lcd.write(5); } lcd.setCursor(load + 1, 1); lcd.write((i - i / 5 * 5) + 1); for (load = load + 2; load < 16; load++) { lcd.setCursor(load, 1); lcd.write(9); } lcd.setCursor(0, 0); lcd.print("LOADING........."); delay(50); } lcd.clear(); delay(500); } void loop() { for (int i = 0; i < 64; i++) { // 64 bins = 32 bins of usable spectrum data data[i] = ((analogRead(L_IN) / 4 ) - 128); // chose how to interpret the data from analog in im[i] = 0; // imaginary component Rdata[i] = ((analogRead(R_IN) / 4 ) - 128); // chose how to interpret the data from analog in Rim[i] = 0; // imaginary component } fix_fft(data, im, 6, 0); // Send Left channel normalized analog values through fft fix_fft(Rdata, Rim, 6, 0); // Send Right channel normalized analog values through fft // At this stage, we have two arrays of [0-31] frequency bins deep [32-63] duplicate // calculate the absolute values of bins in the array - only want positive values for (int i = 0; i < 32; i++) { data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); Rdata[i] = sqrt(Rdata[i] * Rdata[i] + Rim[i] * Rim[i]); // COPY the Right low-band (0-15) into the Left high-band (16-31) for display ease if (i < 16) { data_avgs[i] = data[i]; } else { data_avgs[i] = Rdata[i - 16]; } // Remap values to physical display constraints... that is, 8 display custom character indexes + "_" data_avgs[i] = constrain(data_avgs[i], 0, 9 - gain); //data samples * range (0-9) = 9 data_avgs[i] = map(data_avgs[i], 0, 9 - gain, 0, Yres); // remap averaged values } Two16_LCD(); decay(1); } void Two16_LCD() { lcd.setCursor(0, 0); lcd.print("L"); // Channel ID replaces bin #0 due to hum & noise lcd.setCursor(0, 1); lcd.print("R"); // ditto for (int x = 1; x < 16; x++) { // init 0 to show lowest band overloaded with hum int y = x + 16; // second display line if (data_avgs[x] > peaks[x]) peaks[x] = data_avgs[x]; if (data_avgs[y] > peaks[y]) peaks[y] = data_avgs[y]; lcd.setCursor(x, 0); // draw first (top) row Left if (peaks[x] == 0) { lcd.print("_"); // less LCD artifacts than " " } else { lcd.write(peaks[x]); } lcd.setCursor(x, 1); // draw second (bottom) row Right if (peaks[y] == 0) { lcd.print("_"); } else { lcd.write(peaks[y]); } } debugLoop++; if (DEBUG && (debugLoop > 99)) { Serial.print( "Free RAM = " ); Serial.println( freeRam(), DEC); Serial.println( millis(), DEC); debugLoop = 0; } } int freeRam () { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } void decay(int decayrate) { int DecayTest = 1; // reduce the values of the last peaks by 1 if (DecayTest == decayrate) { for (int x = 0; x < 32; x++) { peaks[x] = peaks[x] - 1; // subtract 1 from each column peaks DecayTest = 0; } } DecayTest++; }
Download Library FFT fix_fft
Hi , thank you for this tutorial , froma where you get sound , are you using a mic module
ReplyDeleteHii..
Deleteno, i use jack audio in connect with a laptop.
PODRIAS DARME EL LINK DIRECTO PARA DESCARGAR LA LIBRERIA DE fix_fft
ReplyDelete
ReplyDeleteYOU CAN GIVE THE DIRECT LINK TO DOWNLOAD THE fix_fft LIBRARY
I have provided above the download link, please share and like to open the link
DeleteSorry my english is not good .. hehe :)
This comment has been removed by the author.
ReplyDeleteHi. I've just found this and I'm trying to get it to work. It's tricky understanding with you capitalising things wrongly and adding spaces but my main problem is the decay function.
ReplyDeleteThe code won't compile with the (int decayrate) declaration at the start of the function. Should this have been declared eleswhere? I also can't see any mention of the variables DecayTest or decayrate used anywhere else in the code, (apart from calling the function at the end of the loop). What exactly is this function doing?
I made a post both in facebook and in google+. But I still can't get access.
ReplyDeleteHi Mr, I need to display spectrum FFT for Arduino by read SAMPLES ADC for calculator frequency ? help me
ReplyDeletedisculpa amigo en el arduino en el diagrama a que se refiere con L R que salen de los pines analógicos...
ReplyDeletetidak ada kalibrasinya ya mas
ReplyDeletehi man, i tried this code , is working well.
ReplyDeletethanks
how to solve the problem please see in the screenshot http://prntscr.com/l5eayk
ReplyDeleteinvalid digit "8" in octal constant
ReplyDeleteHi Can you help me? please. Did you use frequency 70 Hz right? How I change this frequency 70 Hz to 50 Hz? Thank you.
ReplyDeleteI'm sorry. My english is not good.
Great , wonderful project. Ther's a little problem: I tryed the circuit wuth an audio generator and i have discovered that it works in linear way , audio should be in logaritmic, I mean, more or less:
ReplyDelete"Y" start 50Hz --- "Y" center 1KHz ---- "Y" stop 15KHz
Now it works : "Y" start 0Hz --- "Y" center 500Hz -- "Y" stop 1KHz
Compliments again for your code
Hi! Thank you so much.
ReplyDelete