Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer

This is a tutorial on using the MSGEQ7 Spectrum Analyser with Arduino, and chapter forty-eight of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Updated 30/01/2013

In this article we’re going to explain how to make simple spectrum analysers with an Arduino-style board. (Analyser? Analyzer? Take your pick).

First of all, what is a spectrum analyser? Good question. Do you remember what  this is?

It’s a mixed graphic equaliser/spectrum analyser deck for a hi-fi system. The display in the middle is the spectrum analyser, and roughly-speaking it shows the strength of  different frequencies in the music being listened to – and looked pretty awesome doing it. We can recreate displays similar to this for entertainment and also as a base for creative lighting effects. By working through this tutorial you’ll have the base knowledge to recreate these yourself.

We’ll be using the MSGEQ7 “seven band graphic equaliser IC” from Mixed Signal Integration. Here’s the MSGEQ7 data sheet (.pdf).  This little IC can accept a single audio source, analyse seven frequency bands of the audio, and output a DC representation of each frequency band. This isn’t super-accurate or calibrated in any way, but it works. You can get the IC separately, for example:

and then build your own circuit around it… or like most things in the Arduino world – get a shield. In this case, a derivative of the original Bliptronics shield by Sparkfun. It’s designed to pass through stereo audio via 3.5mm audio sockets and contains two MSGEQ7s, so we can do a stereo analyser:

As usual Sparkfun have saved a few cents by not including the stackable header sockets, so you’ll need to buy and solder those in yourself. There is also space for three header pins for direct audio input (left, right and common), which are useful – so if you can add those as well.

So now you have a shield that’s ready for use. Before moving forward let’s examine how the MSGEQ7 works for us. As mentioned earlier, it analyses seven frequency bands. These are illustrated in the following graph from the data sheet:


It will return the strengths of the audio at seven points – 63 Hz, 160 Hz, 400 Hz, 1 kHz, 2.5 kHz, 6.25 kHz and 16 kHz – and as you can see there is some overlap between the bands. The strength is returned as a DC voltage – which we can then simply measure with the Arduino’s analogue input and create a display of some sort. At this point audio purists, Sheldonites and RF people might get a little cranky, so once again – this is more for visual indication than any sort of calibration device.

However as an 8-pin IC a different approach is required to get the different levels. The IC will sequentially give out the levels for each band on pin 3- e.g. 63 Hz then 160 Hz then 400 Hz then 1 kHz then 2.5 kHz then 6.25 kHz  then 16 kHz then back to 63 Hz and so on. To start this sequence we first reset the IC by pulsing the RESET pin HIGH then low. This tells the IC to start at the first band. Next, we set the STROBE pin to LOW, take the DC reading from pin 3 with analogue input, store the value in a variable (an array), then set the STROBE pin HIGH. We repeat the strobe-measure sequence six more times to get the rest of the data, then RESET the IC and start all over again. For the visual learners consider the diagram below from the data sheet:


To demonstrate this process, consider the function

in the following example sketch:

If you follow through the sketch, you can see that it reads both left- and right-channel values from the two MSGEQ7s on the shield, then stores each value in the arrays left[] and right[]. These values are then sent to the serial monitor for display – for example:

If you have a function generator, connect the output to one of the channels and GND – then adjust the frequency and amplitude to see how the values change. The following video clip is a short demonstration of this – we set the generator to 1 kHz and adjust the amplitude of the signal. To make things easier to read we only measure and display the left channel:

Keep an eye on the fourth column of data – this is the analogRead() value returned by the Arduino when reading the 1khz frequency band. You can also see the affect on the other bands around 1 kHz as we increase and decrease the frequency. However that wasn’t really visually appealing – so now we’ll create a small and large graphical version.

First we’ll use an inexpensive LCD, the I2C model from akafugu reviewed previously. To save repeating myself, also review how to create custom LCD characters from here.

With the LCD with have two rows of sixteen characters. The plan is to use the top row for the levels, the left-channel’s on … the left, and the right on the right. Each character will be a little bar graph for the level. The bottom row can be for a label. We don’t have too many pixels to work with, but it’s a compact example:


We have eight rows for each character, and the results from an analogueRead() fall between 0 and 1023. So that’s 1024 possible values spread over eight sections. Thus each row of pixels in each character will represent 128 “units of analogue read” or around 0.63 V if the Arduino is running from true 5 V (remember your AREF notes?). The sketch will again read the values from the MSGEQ7, feed them into two arrays – then display the required character in each band space  on the LCD.

Here’s the resulting sketch:

If you’ve been reading through my tutorials there isn’t anything new to worry about. And now for the demo, with sound –

That would look great on the side of a Walkman, however it’s a bit small. Let’s scale it up by using a Freetronics Dot Matrix Display – you may recall these from Clock One. For some background knowledge check the review here.  Don’t forget to use a suitable power supply for the DMD – 5 V at 4 A will do nicely. The DMD contains 16 rows of 32 LEDs. This gives us twice the “resolution” to display each band level if desired. The display style is subjective, so for this example we’ll use a single column of LEDs for each frequency band, with a blank column between each one.

We use a lot of line-drawing statements to display the levels, and clear the DMD after each display. With this and the previous sketches, there could be room for efficiency – however I write these with the beginner in mind. Here’s the sketch:

… and here it is in action:


At this point you have the knowledge to use the MSGEQ7 ICs to create some interesting spectrum analysers for entertainment and visual appeal – now you just choose the type of display enjoy the results.


Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The following two tabs change content below.

John Boxall

Founder, owner and managing editor of tronixstuff.com.

34 Responses to “Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer”

  1. Mel Alton says:

    Say, if you used a 2004 LCD (20 char x 4 lines) and didn’t print “left” and “right” (since it’s clear which is which) you’d have 4x the vertical height on the display, which should look nice. I’m going to build one of these and see how a 2004 display works out.

  2. JoseM says:

    Really cool!!! Thanks for sharing your work. Great job.

  3. MM_Wombat aka Dennis says:

    Excellent work John, Wonder if I could get that to work on a Maximite..

  4. zndK says:

    is there somewhere an example code to use MSGEQ7 to drive virtual vu meter bars on PROCESSING ?
    i am having dificulties to understand how to use arrays thru the serial port from ARDUINO to PROCESSING

  5. Jamil Merali says:

    Does anybody know of an IC like this that has more than 7 bands? Thanks!

  6. cod says:

    I’m wondering if two of these can be combined to create a 14 band device. I’ve read that the clock speed is controllable by altering the value combo of the external RC components. If the clock speed affects the filter peaks then you might theoretically be able to tune the second IC to a different set of valUes ?

  7. Zeph says:

    cod – you probably could actally get the 14 bands by offseting your frequencies. The frequencies in one chip differ by a factor of 2.5, so you could set the two chips to be about 1.6:1 (square root of 2.5). But notice the overlaps above – there’s going to be a lot more overlap in this case. Not sure you would be getting enough additional information to be worth it.

    • cod says:

      thanks, Zeph. Yeah, I’ve come to similar conclusion. In fact, I am currently not using the chip at all. I was hoping the msgeq7 would be a viable A/D converter when compared to a software solution, but I think my testing has led me to find that today’s modern multicore CPU’s, a firewire interface, and software EQ modeling is just gonna be a better, more versatile performer overall than even a ‘hardware’ chip that is probably 20-30 yrs old and not really intended to do much more than a rudimentary info display. Fun, but not really a modern perfomer, comparatively. I can make a 30 band software EQ in Max4Live and plug it right into Ableton, etc., with more versatility and probably better performance.

  8. tomdf says:

    Thanks for the tutorial, before reading it I could figure out exactly what the shield did!
    I’m learning Processing at the moment and used it to create a visualizer that can be viewed on a computer without any additional hardware.

  9. Jason says:

    Thanks for the tutorial! I was just wondering how hard would it be to implement this on an ATMega instead of an Adruino. The only pins that you use for the spectrum shield are pins 4,5,and 7 correct? I don’t quite understand how to wire up the spectrum shield. Can you please guide me?

    Thank you for the tutorial once again.

  10. arlo says:

    I consistently get results that seem biased towards the mid-frequencies. Feeding in a 400 Hz sine wave (synthesized via DDS but looks good on a scope) and normalizing to the 400 Hz output, the 1 KHz output is 55%. At reduced input amplitudes, the problem is worse. When I ground the input, instead of seeing all zeros, I get non-zero results with a roughly bell shaped curve peaking at 1 KHz. Have you seen similar results? Have you recorded your values when the audio input is grounded?

  11. arlo says:

    I think my problem is the MSGEQ7 performance is inconsistent. I tried four devices with grounded input and got the following results:
    1 0 0 0 0 7 0 63
    2 0 31 32 29 27 31 77
    3 0 27 27 80 6 0 0
    4 0 0 0 0 0 0 0
    I was pretty encouraged by the last device until I tried to give it inputs of several different frequencies and got outputs of all 0’s regardless of input. You can see from the data that my first post was written when I was using device #3.

    I’m going to buy some more devices (not from eBay this time) and see what happens.

  12. mbraun says:

    Nice tutorial.
    I think you might be able to clean up the code a little by using the map function. Whereas I have to admit that with your 8 if-handlers it’s easier to understand for beginners.

    • John Boxall says:

      Good point but as you mention it’s better for the readers to keep it simple. Then again a map tutorial is a good idea. Thanks :)

  13. Marco says:

    Im confused on how to convert the code for the TWILiquidcrystal.h to just being able to use the LiquidCrystal.h library. I do not have the TWILCD backpack. Im a beginner so any help is appreciated!

    • John Boxall says:

      #include “Wire.h”
      #include “TWILiquidCrystal.h”
      and replace
      LiquidCrystal lcd(50);
      the normal LiquidCrystal() function you would use to set up your own display.
      Please leave comments once only.

  14. Kyle Seeberger says:

    hey, would it be possible that, instead of having an equalizer display, could you have a 7 different lights, each responsible for a frequency.

  15. Dan says:

    Great article! Is their anywhere that I could find a little more help on the Hardware side of this? I would love to do this with one of those Dot matrixes

  16. Martythed says:


    I think that I’ve figured out how to fill the space between columns and thus have two columns for each band without any spaces between them. I’ll put it on the board if anyone is interested; it’s a very simple change.


  17. wjginn says:

    @Martythed; if you can put the code I would greatly appreciate it.

    Also, I’m getting this error don’t know how to get to fix this:

    sketch_mar04a:9: error: ‘DMD’ does not name a type
    sketch_mar04a.ino: In function ‘void ScanDMD()':
    sketch_mar04a:12: error: ‘dmd’ was not declared in this scope
    sketch_mar04a.ino: In function ‘void setup()':
    sketch_mar04a:23: error: ‘Timer1′ was not declared in this scope
    sketch_mar04a:25: error: ‘dmd’ was not declared in this scope
    sketch_mar04a.ino: In function ‘void loop()':
    sketch_mar04a:51: error: ‘dmd’ was not declared in this scope
    sketch_mar04a:56: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:57: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:58: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:59: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:60: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:61: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:62: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:63: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:70: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:71: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:72: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:73: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:74: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:75: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:76: error: ‘GRAPHICS_NORMAL’ was not declared in this scope
    sketch_mar04a:77: error: ‘GRAPHICS_NORMAL’ was not declared in this scope

    can anybody help me with this?

    sorry, I just started learning C programming and also this is my first time with arduio. Since I love listening to music and have been interested in arduio projects, I thought this would be a nice first project for me.

    cheers guys

  18. will says:


    I was just wondering for the connection from the spectrum shield to the LED matrix, what’s CS, WR, DATA, CLK. I looked tried what’s in the DMD.h but I couldn’t get it to work. I’m using a different LED matrix. It’s a Bi-colour LED Matrix.

    • John Boxall says:

      See if your matrix supplier has some demo Arduino code, the interfaces on these things are usually wildly different.

  19. Robert says:

    First of all thanks for the great tutorial.
    I am new and want to make this, could you please list all components that you used for the one with LED matrix? Arduino, spectrum shield, led matrix, what else do I need to buy?

  20. Nocturne says:

    Hey, when testing my shield from Sparkfun using the first sketch on this tutorial (for which thank you a lot). I get some numbers as readings at first, but strange symbols start flooding immediately after, like that:

    297 264 133
    73 79 168 26‰Ê”L-„R¡”0P¶,E0P”$ (P“ 0°²$q ²
    ¢4–.$a¢2P”2(¢fŠ ¢@”Iq 2J$„p°¢,‚ñ¢Ò !«0²2!‚µ&–
    #FŠ5#0(´)%t²¨‡‰X  0ð²Z
    ñ²Ø ºp”(“!20¢¢)‚20¢3a*²H+
    pÐ3)¢²³š$‚@L-‚&&¢q ¢
    ‚‚’’%¢²²@-¢0¢I+€²(²³$€¢(г’$p3R“!²p2¢š9‚ ¢

    and so on… any idea why is that? :/

    • Nocturne says:

      Oh, I finally got it, after over an hour spent on this trying to figure out what was wrong, silly me, lol.
      In case anyone else face the same problem:
      changed baud rate (on serial monitor) from 9600 to maximum value 115200, works flawlessly. :)
      I’m new to Arduino, so yeah…


Leave a Reply

Receive notifications of new posts by email.

The Arduino Book

Arduino Workshop

Für unsere deutschen Freunde

Dla naszych polskich przyjaciół ...

Australian Electronics!

Buy and support Silicon Chip - Australia's only Electronics Magazine.

Use of our content…

%d bloggers like this: