Hello All,

I am trying to implement a Synthesia project with Neopixel LEDs, where certain LEDs must glow when a partilcuar frequency or its octave is mapped to the LED. I plan to inplement this with the Arduino Uno board. To start with, I came across multiple forums, and as many suggested, used the FFT library by by musical lab. I did use their fft_adc_serial.pde as a template and modified it after I understood what the code was implementing. (Added more comments and changed a few logic to make it easier for me/someoneelse to understand).

For the audio input to the Uno board, I am using a Parralax sound sensor that takes the input from a Stero playing music and outputs the amplified signal to the Arduino board. I am using the Analog input 0 and using the ADC in this pin to sample the signal presented by the sound sensor to the Uno board. I am using a prescaler of 32, which gives me a sampling frequency of (16000000/32/13) = 38.461kHz. From the Nyquist Theorem the effective bandwidth is half the Sampling freqeuncy = 38.461kHz/2 ~ 19kHz. Since The Audio band is 20Hz to 20kHz, we have chosen the correct sampling frequency. I am using a FFT bin size of 256 samples.

With the circuit in place, I am using the Serial console to output the values stored in decibel values stored in fft_log, after calling the command fft_run() and fft_mag_log(). Here the frequency buckets start from 0hz and eac freqeuncy bin is (19kHz/256) = 74.21Hz. So the first bin starts from 0Hz to 74.21kHz, the second bin starts from 74.21Hz to 148.43Hz and so on.

When I run an audio input signal and print out the values in the serial port, I see the following values as attached in serial_with_600Hz_signal.txt. If I do not have any audio signal, I see the following values as attached in serial_wity_silence text file. Basically both have the almost the same value in th 0Hz-75Hz value. For the bucket with 600-700hz, I see the following values:

Frequency: 600Hz 79 dB

Frequency: 675Hz 68 dB

I had expected a large value in this range. But I do not see it. Was wondering if someone can point out where I am goig wrong?

My Code is placed below:

#define LOG_OUT 1 // use the log output function

#include “FastLED.h”

#include “FFT.h” // include the library

#define FFT_N 256 // set to 256 point fft

#define NUM_LEDS 1

#define DATA_PIN 6

#define CLOCK_PIN 13

#define ANALOG_PIN 0

#define ADC_INTERRUPT_ENABLE 0x10

#define BIT_15_HEX 0x8000

#define SAMPLING_FREQ (16000000/(13*32))

int val = 0; // variable to store the value read

CRGB leds[NUM_LEDS]; // Define the array of leds

void setup() {

Serial.begin(9600); // setup serial

FastLED.addLeds<NEOPIXEL, DATA_PIN> (leds, NUM_LEDS);

DIDR0 = 0x01; // turn off the digital input for adc0

ADMUX = 0x40; // use adc0

/*

- To get 10bit precision, from 50kHz to 200kHz clock must be supplied to the ADC. The
- chip runs at 16MHHz. If we were set the prescaler value to 128 → 0b011 as part of the
- ADPS register value, then we get (16MHz/128) = 125kHz as the ADC Input Clock frequency.
- Since it takes 13 input clock cycles to get one Audio sample, the effective sampling
- frequency is 125Khz/13 = 9.6kHz. This is not sufficient as the audio frequency range
- is from 20Hz to 20KHz.
- If we choose a prescaler of 32, then the sampling frequency becomes 16000/(32*13) ~ 38KhZ
- From Nyquist’s Theorem, the effective bandwidth is half the sample rate,= 19KhZ

*/

ADCSRA = 0xe5;

}

void loop() {

//Serial.println(“Start of for loop”);

cli();

while(1){

for (int i = 0 ; i < 512 ; i+=2) { // we need 256 samples that represent the real into 256 bins of the FFT

while(!(ADC_INTERRUPT_ENABLE & ADCSRA)); // wait till the interrupt flag is 0. Which means conversion is in process

ADCSRA = 0xf5; // Set ADIF to 1 and ADSC to 1, as the first conversion was made and we need to be ready for the next conversion

byte low = ADCL; // fetch adc data

byte high = ADCH;

int value = (high << 8) | low; // form into an int

/*

- The value we have over here is the value from bit to bit 10. We need to shift high 8 times, so that the first two bits (0 and 1)
- in ADCH now occupy bit 8 and bit 9. We now need to make this value left shifted as to provide scaled values. By left shifting
- the value by 6, the MSB in ADCH is now at bit 15 and the LSB of ADCL is at bit 6.

*/

int adc_val = value << 6;

adc_val = (adc_val - BIT_15_HEX); // form into a 16b signed int

fft_input *= adc_val; // put real data into even bins*

- fft_input[i+1] = 0; // set odd bins to 0*
- }*
- fft_window(); // window the data for better frequency response*
- fft_reorder(); // reorder the data before doing the fft*
- fft_run(); // process the data in the fft*
- fft_mag_log(); // take the output of the fft*
- sei();*

_ /*_

_ * the 20kHz signal bandwidth,is divided into 256 equal-sized sections, each covering 78.125kHz band_

_ * we will be printing the decibel level of the input signal at each of these bands._

_ */_ - Serial.println(“start”);*
- for (byte i = 0 ; i < FFT_N/2 ; i++) {*

*Serial.print("Frequency: “); Serial.print(i* ((SAMPLING_FREQ/2)/FFT_N)); Serial.print(” ");*

*Serial.println(fft_log_out*); // send out the data to the serial port so I can see what it’s doing**

** }**

** }**

*}*

*serial_with_silence.txt (5.65 KB)*

*serial_with 600 Hz sine wave sound.txt (5.99 KB)*