RSS

Color Organ / Spectrum Analyzer, Arduino project with FFT algorithm.

10 Feb


The basic idea was to create color organ / spectrum analyzer on arduino board, trying to minimize quantity of external components, like analog filters, LED display drivers, etc.
Spend a lot of time in search on internet I was able to find only two ! project ,  which implemented FFT in order to solve a problem. One of them is:

http://elm-chan.org/works/akilcd/report_e.html

in a few days it will celebrate 6-th anniversary.  The obstacle, at least for me, was to compile / adapt his software for Arduino IDE platform, as it written in assembly and C.  So, I’ve moved on, and was lucky to discover an excellent chunk of code dated back to 1989! They didn’t have floating point co-processor or “blue deep” around at that time, so mathematical skills were in high demand.

FFT algorithm could find application in wide variety of projects, for example, musical note recognition, voice recognition, sound localization etc. It could be done in Arduino, or in combination with PC. In this project all functionality implemented in Arduino.  Sampling, FFT processing and visualization of music, everything done by single arduino Uno board alone!.  The same time, after each stage data could be extracted via serial link to PC. To use the the data provided by Arduino in different application on PC (like interactivity / processing),  you can just pull data over serial link, as it was done for debugging purposes with “f” command.  After FFT-processing input data array x, generated output array fx with  32 elements, “bins”, each representing a range of frequencies. The width of a bin equals: D = 1 / T, where T is input array sampling timing, in our case T = 14.6 millisecond.

D = 1 / (14.6 * 10^-3) = ~ 70 Hz.
So, the value of fx[0] is amplitude DC offset up to 35 Hz;
fx[1] is amplitude in a range   35 <—> 105 Hz;
fx[2] is amplitude in a range 105 <—> 175 Hz;
fx[3] is amplitude in a range 175 <—> 245 Hz;
fx[4] is amplitude in a range 245 <—> 315 Hz;
………………………………………………………..
fx[31] is amplitude in a range 2135 <—> 2170 Hz;
Upper limits could be extended up to 76 kHz.(*)

Sum up first 10 fx bins, I’m getting 35 <—> 735 Hz frequency range for red LED’s, from 11-th to 20-th consequently provides me 735 <—> 1435 Hz  for green LED’s, and from 21-st to 31-st 1435 <—> 2170 Hz range for blue LED’s.

 Now hardware part.

I was considering two way to build display, using PWM or BarGraph. In my opinion, PWM is not quite suited with LED, due nonlinearity in their current-brightness response. Probably, PWM approach would be O’K with incandescent lights.
BarGraph design gives better impression, when higher sound volume   highlighted bigger area. Just imagine, how beautiful Fireworks are!
I’ve used Christmas LEDs, that left over since last holiday  :) This is why I put 3 of them in each string, and have to use ULN2003 with 12V power source. Basically, all you need is 12 Leds ( 4 – red, 4 – green and 4 blue ) and 12 resistors, connect led+resistor between output of arduino board  and ground.

For sound input I used a kit MK136 ( 2 mic’s + amplifier IC NE5532 ), powered up from arduino board +5V. Why kit? It provides a board and components. Next, you can easily reconfigure input circuitry for different sound sources as:

        1. signal from 3.5 mm jack connector
2. pick up sound using microphone.
3. configure one channel with mic and another with 3.5 jack, that is what I did.
Plus it has a pot, to adjust sensitivity on the fly. Don’t install DC blocking capacitors  at the outputs.

Sparkfun’s breakout board for electret microphone will works too:

 (with some limits, from 3 options listed above only number 2 would be avaiable.)

Here how to create DC offset with just couple resistors + cap. Circuit requires line level of the input signal (~1 V). You can use headphones output.

Link to download sketch:                         Music_color
 *Please, be advised, code written for AtMega328p and should be corrected to work with other microprocessors. 

Sine Tables:                                         Sine_Tables

( for someone who ‘d like to experiment, but don’t know how to create them)

Thats it for now, will come back to answer your questions if you have any.

About these ads
 

Tags: , , , , , , , , , ,

11 Responses to Color Organ / Spectrum Analyzer, Arduino project with FFT algorithm.

  1. Mike

    March 24, 2011 at 7:53 pm

    I'm very new to Arduino. Your color organ looks awesome, I am just a little confused by the code. I don't know how/what to include as a library/sketch, etc. My email is mikehill100@gmail.com. I'm really interested and any help would be great.

     
  2. Magician

    March 24, 2011 at 8:43 pm

    Code intentionally was done as "all in one". You don't have to configure additional library or headers files.There is only one scetch, copy paste from first to last line in your IDE and it would compile without any error.

     
  3. Eno

    September 29, 2011 at 3:13 am

    It took me a few minutes to figure out how to connect the headphone jack but it's working. This gets me started on the stuff I want to do. Thanks.

     
  4. xray

    January 10, 2012 at 8:09 pm

    Hello Magician, I couldn't seem to download your sketch. Without seeing your code, I assume you are using fix_fft as your library? Can you tell me how I can make it to for 0 to ~ 200kHz? I think the sample code I found has the operating range from 0 to 500Hz and I have been puzzling to figure out how to get to work at a wider spectrum… Thanks!xray

     
  5. Magician

    January 10, 2012 at 11:57 pm

    I'm using fix_fft as a function/subroutine, there is only one sketch "all-in-one". Arduino ADC can't sample faster than ~150 kHz, so maximum freq. analysis up to 75 kHz. If your microprocessor is different (mbed, Maple, PIC, cortex- whatever) and capable take samples 400 kS/s (to get 200 kHz), you will have to write other code and call fix_fft function when array of samples ready.

     
  6. xray

    January 11, 2012 at 1:44 am

    Thanks Magician, sorry I am very new with Arduino, let alone using FFT. Now comparing with the fix_fft I found at other source, I noticed you have increased the length of the sinetable considerably. And would you mind telling me the difference between fix_fft() vs. fixfftr()? Say if I want to analyze spectrum bandwidth of 20kHz, where should I modify your code to do so?Thanks,xray

     
  7. Magician

    January 11, 2012 at 2:48 am

    Don't know where you get other fix_fft, I download a code from this link: http://www.jjj.de/fft/fftpage.html Sinetable size should be no less than FFT_SIZE, 64 in my code would be sufficient,I just left look-up table unmodified, as it was in original source code, in case someone increase number of bins more than 64. fix_fftr doesn’t do much in my code as it “intermediate” stage to change direction – make reverse FFT in the original version.

     
  8. Magician

    January 11, 2012 at 4:11 pm

    I posted sine tables file above, size 32, 64, 128 and 256.

     
  9. xray

    January 11, 2012 at 5:24 pm

    So, by adjusting the since of the since table will change the maximum range of FFT? If not too much to ask, would u share the math behind it?

     
  10. Magician

    January 11, 2012 at 10:56 pm

    Adjusting size of the sinetable, you make your sketch smaller, easier to navigate and edit. It has only “cosmetic” effect. I was not going to explain how FFT works, but looks like I have to. Just be aware, I’m a Magician, not really Mathematician -); Based on freq. range you need, you define sampling period according to Nyquist theorem: Fsaml. >= 2 x Fmax. For example, for 0 – 20 kHz freq., samples must be taken with 40 kHz freq. No less, but could be more, to relax antialising filter requirements. There are two way: using ADC control register of Arduino, or using a Timer (what people usually do to schedule periodic action). First way easier, and you could look into my other blog how to set ADC for faster readings. Disadvantage is sampling freq. has to be multiple of the Fosc. You can’t set it to 40 kHz sharp, but ~36 kHz, ~72 kHz, or default ~9 kHz.When you wrap around periodic sampling function in the code, next question: how many samples do I need? It all depends on what freq resolution do you need,( and what memory size of your chip !). In this example, 20 kHz with array of 64 samples would provide : 20.000 / 32 = 625 Hz/bin. Pay attention, I reduce 64 in half, to 32 as output of the FFT always “mirrored” in other half. Hope , this helps.

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: