Home > AVR Projects > Audio Visualization with Nokia 3310 LCD and FFT

Audio Visualization with Nokia 3310 LCD and FFT

January 18th, 2009


The purpose of this project is to make an audio visualizer to demonstrate the use of the Nokia 3310 LCD as a graphical display. By audio visualizer, I mean the visualization like Winamp, XMMS, or Windows Media player. This project utilizes a fixed point FFT (fast fourier transform) algorithm to convert the discrete audio samples in time into frequency. This allows us to graph bars for each frequency as the music is playing.  In other words, different bars dance around for the bass, midrange, treble, and all the points in between.


For input, we use the sparkfun.com microphone module. This is fed to an ADC (analog to digital conversion) pin on an Atmel AVR atmega8 running at 8MHz. Like our other Nokia 3310 based projects, we talk to the LCD using SPI. In order to run the atmega8 in 8MHz, you must change the default value of the low byte on the fuse. Our atmega does not have a floating point unit. To be able to execute fast and without lots of extra instructions, we must use a fixed point FFT algorithm. Most FFTs use floating point for accuracy. For our purposes, this loss of accuracy is no big deal.

Please install flash and visit our site to play this video.

A popular fixed point FFT algorithm was written by Tim Robberts in 1989 (http://www.jjj.de/fft/fix_fft.tar.gz). Initially, I ported this code to the avr and avr libc to be used for this project. It definitely worked, but the performance was not great. Luckily, I stumbled on an AVR optimized fft library from http://elm-chan.org/works/akilcd/report_e.html and this code executes 4 times faster! Yes, that is 4 times faster. Go optimized assembly and go elm-chan.org :-)

The process is shown in the diagram below. First, we take samples at 16kHz. We take 64 samples. With an FFT, the more samples that you take the more granularity that you have in determining what frequencies are present. For our case, even less would do just fine but the library we are using needs a minimum of 64 samples. Next, we do an FFT on the samples to convert it to frequency. Last, we update our display. Remarkably, even running the LCD over SPI, it still is able to refresh the entire screen in less than 4ms. This allows us to refresh the screen plenty often.

Overview of the process: capture, process, display

Overview of the process: capture, process, display

As a side note, the more samples we capture and process at a time, the more precise the granularity on our frequency results.  In other words, we’ll have more accuracy.  The sampling rate is what determines the range of frequencies that we know about.  If one wants to see higher frequencies, one has to sample faster.  For our case, 16KHz seemed more than adequate.  It appears as if our microphone module does not have very good frequency response in the high end.  In the end, we decided to “zoom in” on the lower frequencies by making their bars wider because it gave a better visual result with our microphone module.


Schematic - atmega8 with 3310 LCD and IR sensor

Schematic - atmega8 with 3310 LCD and IR sensor

Nokia 3310 LCD Pinout

Nokia 3310 LCD Pinout

Source Code

avr-gcc project – avr-fft-3310.tar.gz (complete project code and firmware)

firmware – avr-fft.rom

* make sure you run the AVR at 8MHz by setting the lower fuse byte to 0xe4.  I do this with uisp with “uisp -dprog=stk200 –wr_fuse_l=0xe4″ but the command will vary depending on what programming program and hardware that you use.

FFT code from – elm-chan.org projectavrfft.zip

mike AVR Projects , , , , ,

  1. Brian
    January 19th, 2009 at 10:50 | #1

    Please share the code soon. I’m very curious.

  2. mike
    January 20th, 2009 at 11:01 | #2

    Until then, if you just want to use the fft stuff, that was borrowed from the link above (elm-chan.org). If you want to try it out verbatim, you can follow the schematic and program your avr with the avr-fft.rom above.

    I hope to have some time this weekend to clean up the code.

  3. mike
    January 20th, 2009 at 21:25 | #3


  4. whamodyne
    February 16th, 2009 at 12:36 | #4

    Great project! Can you post the schematic for this one? Are you using a MAX293 filter chip like e-chan did in his project, or is the microphone/opamp from Sparkfun going directly into the A/D pin?

    I’m wanting to try this one out on my own to see how it works, love your AVR and Nokia 3310 LCD projects.

  5. February 16th, 2009 at 13:24 | #5

    Yes, the Sparkfun microphone module output pin went directly into the ADC input pin (ADC0). Until I have time to post a schematic, it should be

    (1) basic power connections
    (2) LCD connected as shown
    (3) microphone connected to ADC0 pin

    Hopefully that will get you started until I have time to make a schematic. I wish the gain was higher on the microphone module because I did have to point the speaker directly at it. I wanted to try a filter chip and put the audio in directly with a headphone jack someday …

  6. TedTheBellhop
    February 17th, 2009 at 10:28 | #6

    Hey Mike, nice project!

    I am using the same microphone breakout board (BOB-08669) connected to an Arduino Duemilanove (analog In). Right now I can’t use it properly because the differences of the values are too low when making noise just 20-40 cm away. My target is to determine the volume in the first place.
    I started with this example http://wiring.org.co/learning/examples/microphone.html and it worked pretty good. I wanted to replace all the wiring with the breakout board (BOB-08669) but it looks like it’s not that easy…
    Maybe it’s the same problem you have (low gain) and I need to amplify more.

  7. February 17th, 2009 at 11:14 | #7

    It looks like the BOB-08669 is a basic inverting op amp circuit with some filtering. I haven’t analyzed what the frequency response should be, but assume one could just use a higher value for R5 for the gain. If it is a standard inverting amp, the gain would be:

    Gain = 1 + R5/R4

    Right now R5 is 100k and R4 is 1k. That means the gain is 101. Replacing R5 with a 200kohm resistor should double the gain. I don’t have any 200k SMT resistors but may try getting some on my next digikey order.

  8. thebard
    March 3rd, 2009 at 23:17 | #8

    Hey this project rocks… we’re looking at doing something similar for a uni project. Basically using atmega168 instead of atmega8 to capture some sounds, and then analyse them and do some data mapping. I ordered a couple of those LCDs and electret breakouts to give this a go… will let you know how it turns out.

  9. ricardo.nas
    March 4th, 2009 at 14:43 | #9

    man, I have an stupid question. I need a microphone to send audio data to a computer using line in.

    Can I use this mic (Breakout Board for Electret Microphone) / send the data to an arduino / and then to a computer via Xbee?

    Sorry if it sounds stupid, but i have no idea how to do it. any tips? What I need is to really record the audio. Thank you.

  10. March 4th, 2009 at 20:23 | #10

    I’m kind of confused.

    If you just want to record off of line in, why not just record directly with the line in on the sound card?

    Is the objective to wirelessly record? My experiences so far with this mic breakout have not been great for general audio quality. The gain doesnt appear to be high enough to get anything other that audio being spoken directly into out pretty loud. When connected directly with nothing except directly into an ADC pin, it appears to be overly noisy. I’m thinking there has to be a better way to connect it for higher quality audio.

    Last, if that is your goal (see warning above) you would take audio in the ADC pin, out serial through XBEE, ,thento XBEE on the PC side to USB using Sparkfuns serial to USB FTDI converter or the xbee explorer (http://www.sparkfun.com/commerce/product_info.php?products_id=8687).

  11. metal
    November 9th, 2010 at 15:40 | #11

    mike :

    Hi Mike,

    How can I modify the code to use 20×2 character LCD?


  1. June 13th, 2010 at 17:02 | #1
  2. August 24th, 2010 at 08:48 | #2
You must be logged in to post a comment.