The MSGEQ7 is a small 8-pin device that can be used in conjunction with a microcontroller to create a simple seven-band audio spectrum analyzer.
Well, I'm happy to say that things are bouncing along with regard to my Bodacious Acoustic Diagnostic Astoundingly Superior Spectromatic (BADASS) display project. As I discussed in this blog, the plan for my first-pass incarnation of this project is to use an Arduino Mega microcontroller platform to drive the display itself. One reason for this is that I'm using Adafruit's NeoPixel strips, and the folks at Adafruit provide a really nice NeoPixel software library for use the Arduino Uno and Mega. Meanwhile, a second device -- either a microcontroller or an FPGA -- is to be used to perform the digital signal processing (DSP) on the incoming audio stream to extract the spectrum data.
As part of my first-pass realization of this project, I opted to use a chipKIT MAX32 to process the audio data stream. This little beauty boasts a 32-bit processor running at 80MHz along with 512 Kbytes of Flash and 128 Kbytes of RAM. The illustration below provides a high-level view as to how this is all going to fit together.
My original plan was to implement some DSP algorithm like a Fast Fourier Transform (FFT) on the chipKIT, but then my chum Steve Manley -- a self-described lover of anything to do with flashing lights -- told me about the MSGEQ7 7-band graphic equalizer chips you can purchase for only $4.95 each from SparkFun.
This really is a very clever little device. Inside there are seven band-pass filters tuned to 63Hz, 160Hz, 400Hz, 1,000Hz, 2,500Hz, 6,250Hz, and 16,000Hz. Each of these filters has an associated peak detector. The clever thing is that the outputs from the seven peak detectors are multiplexed together, which explains how everything fits into an 8-pin package.
Everything is controlled by two digital signals: RESET and STROBE. As shown in the waveform diagram below, a positive-going pulse on the RESET signal kicks everything off. Although the datasheet doesn’t actually say so, my impression is that this pulse takes a copy of the current peak detector outputs and stores (latches) these values. We then apply seven negative-going pulses to the STROBE input. Every time the STROBE input goes low, we can read the value of one of the bands on the DATA_OUT signal, starting with the 63Hz value and working out way up to the 16,000Hz value.
The DATA_OUT is an analog value, whose magnitude reflects the value from the corresponding peak detector. This value can be read using one of the chipKIT MAX32's analog inputs.
Actually, I recreated the timing diagram shown above from the original datasheet. If you read the comments associated with my step-by-step construction guide, you will see a question by David Ashton. David points out that, as the minimum strobe pulse width of 18µs is less than the minimum output settling time of 36µs, this implies that you can read the data even after the STROBE signal has returned to its HIGH state. Based on this, David notes that you could actually read the data during the "purple times" in the above diagram.
If this were to prove to be correct, then -- based on the timing specifications in the datasheet -- a better representation of the timing relationships and waveforms would be as illustrated below.
Since it's not possible to make a definitive decision based on the existing datasheet, I talked to John Ambrose at Mixed Signal Integration -- the company that makes the MSGEQ7 (along with many other interesting products). John confirmed that applying a positive-going pulse to the RESET signal does indeed latch the current frequency values.
John went on to explain that the DATA_OUT signal is clamped to 0V when the STROBE signal is HIGH. This has several implications, including the fact that you cannot read the data when the STROBE signal is in its HIGH state. Also, this means that the minimum strobe pulse width ("ts") really isn't 18µs; instead, it's equal to the output settling time ("to") plus however long it takes for you to actually read the sample (let's call this "tsr" for "sample read time"). Based on this, the definitive timing diagram is actually as shown below.
With all that behind us, the following illustration reflects the additional components we need to make things work. In the original datasheet, the value of C2 is shown as being 0.01µF, but I ran across an application note somewhere that said it was better to use 0.1µF, so that's what I did.
I used two MSGEQ7s -- one for each (left and right) audio channel. If you wish to use a single device for both channels, you can employ the circuit variation shown at the bottom of the above illustration.
As soon as I'd wired everything up on a breadboard, my first experiment involved feeding music from my iPad into an external amplifier and into my breadboard. I created a simple program that looped around reading the outputs from the MSGEQ7s and writing their numerical equivalents to a serial I/O window on my notepad computer (a cheap-and-cheerful machine that I picked up from my local technology recycling store just to program my Arduinos and chipKITs).
Once I was confident that my MSGEQ7s were working as expected and that I could access their spectrum data, I added 14 LEDs (seven for each channel) to my breadboard as illustrated below.
Just to make things a bit more interesting, I associated red LEDs with the two lowest frequency bands, yellow LEDs with the two highest frequency bands, and orange LEDs with the three middle frequency bands.
All I'm doing at this stage is to use the numerical value (0 to 255) associated with each audio band to feed a PWM (pulse-width modulated) output that is used to drive the corresponding LED. You can see the result in this video, which I just uploaded to YouTube.
Actually, there are some interesting "gotchas" associated with all of this, but those are outside the scope of this brief overview. Should you be interested in building something like this yourself, check out my step-by-step construction guide (which includes some example programs) and also my step-by-step test guide.