The audio input to the Arduino is on A0, with bias at the mid point by 10K to GND and 10K to +5V. In this example shown here the input is a sine wave of 1kHz from the program Signal Inspector running on my iMac. The full range of the code displays a maximum up to about 4kHz.
Hint: Google "u8glib" and "fix_fft", then put them both in your Arduino "libraries" folder.
Here's a photo of the display with a 500Hz square wave input. You can see the fundamental and the harmonics at x3, x5 & x7.
Code
#include "U8glib.h"
#include "fix_fft.h"
// LCD SPI SCK-EN, MOSI-RW & SS-CS
#define EN 13
#define RW 11
#define CS 10
// display set up, bar, line position L & R
#define LINEY 50
#define LINEXL 0
#define LINEXR 128
#define SAMPLES 128
#define AUDIO A0
U8GLIB_ST7920_128X64_1X lcd(EN, RW, CS); // serial use, PSB = GND
char im[SAMPLES];
char data[SAMPLES];
int barht[SAMPLES];
void setup()
{
lcd.begin(); // inti display
lcd.setRot180(); // flip screen
}
void loop()
{
static int i, j;
int val;
// get audio data
for(i = 0; i < SAMPLES; i++)
{
val = analogRead(AUDIO); // 0-1023
data[i] = (char)(val/4 - 128); // store as char
im[i] = 0; // init all as 0
}
// run FFT
fix_fft(data, im, 7, 0);
// extract absolute value of data only, for 64 results
for(i = 0; i < SAMPLES/2; i++)
{
barht[i] = (int)sqrt(data[i] * data[i] + im[i] * im[i]);
}
for(i = 0, j = 0; i < SAMPLES/2; i++, j += 2)
{
barht[i] = barht[j] + barht[j + 1];
}
// display barchart
barchart(SAMPLES/4, barht); // plot SAMPLES / 4 = 32 as barchart gen cannot handle 128 bars
}
// plot line and bar at position and height
void barchart(int n, int bh[])
{
int i, s, w; // bars, spacing and width
s = (LINEXR - LINEXL) / n;
w = s / 2;
lcd.firstPage();
do
{
lcd.setFont(u8g_font_helvR08);
lcd.drawStr(20, 10, "FFT Audio Spectrum");
lcd.drawLine(LINEXL, LINEY, LINEXR, LINEY);
lcd.drawStr(0, LINEY + 10, "0");
lcd.drawStr(29, LINEY + 10, "1k");
lcd.drawStr(59, LINEY + 10, "2k");
lcd.drawStr(91, LINEY + 10, "3k");
lcd.drawStr(115, LINEY + 10, "Hz");
for(i = 0; i < n; i++)
{
lcd.drawBox(LINEXL + s * i, LINEY - bh[i], w, bh[i] + 1); // u8glib doesn't accept box height of 0
}
}while(lcd.nextPage());
}
Improvements can be made by directly programming the Arduino Uno ADC converter, rather than relying on the call to analogRead(). This would give a faster esponse and a wider bandwidth.
No comments:
Post a Comment