Wednesday, January 30, 2013

Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer

This is 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

readMSGEQ7()

in the following example sketch (download):

// Example 48.1 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013  // MSGEQ7 spectrum analyser shield - basic demonstration
int strobe = 4; // strobe pins on digital 4 int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays int right[7];
int band;
void setup() { Serial.begin(115200); pinMode(res, OUTPUT); // reset pinMode(strobe, OUTPUT); // strobe digitalWrite(res,LOW); // reset low digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield }
void readMSGEQ7() // Function to read 7 band equalizers { digitalWrite(res, HIGH); digitalWrite(res, LOW); for(band=0; band <7; band++) { digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band  delayMicroseconds(30); //  left[band] = analogRead(0); // store left band reading right[band] = analogRead(1); // ... and the right digitalWrite(strobe,HIGH);  } }
void loop() { readMSGEQ7(); // display values of left channel on serial monitor for (band = 0; band < 7; band++) { Serial.print(left[band]); Serial.print(" "); } Serial.println();
// display values of right channel on serial monitor for (band = 0; band < 7; band++) { Serial.print(right[band]); Serial.print(" "); } Serial.println(); }

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 (download):

// Example 48.2 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013  // MSGEQ7 spectrum analyser shield and I2C LCD from akafugu
// for akafugu I2C LCD #include <Wire.h> #include "TWILiquidCrystal.h" LiquidCrystal lcd(50);
// create custom characters for LCD byte level0[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111}; byte level1[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111}; byte level2[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111}; byte level3[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111}; byte level4[8] = { 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}; byte level5[8] = { 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}; byte level6[8] = { 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}; byte level7[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
int strobe = 4; // strobe pins on digital 4 int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays int right[7];
int band;
void setup() { Serial.begin(9600); // setup LCD and custom characters lcd.begin(16, 2); lcd.setContrast(24); lcd.clear();
lcd.createChar(0,level0); lcd.createChar(1,level1); lcd.createChar(2,level2); lcd.createChar(3,level3); lcd.createChar(4,level4); lcd.createChar(5,level5); lcd.createChar(6,level6); lcd.createChar(7,level7);
lcd.setCursor(0,1); lcd.print("Left"); lcd.setCursor(11,1); lcd.print("Right");
pinMode(res, OUTPUT); // reset pinMode(strobe, OUTPUT); // strobe digitalWrite(res,LOW); // reset low digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield }
void readMSGEQ7() // Function to read 7 band equalizers { digitalWrite(res, HIGH); digitalWrite(res, LOW); for( band = 0; band < 7; band++ ) { digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band  delayMicroseconds(30); //  left[band] = analogRead(0); // store left band reading right[band] = analogRead(1); // ... and the right digitalWrite(strobe,HIGH);  } }
void loop() { readMSGEQ7();
// display values of left channel on LCD for( band = 0; band < 7; band++ ) { lcd.setCursor(band,0); if (left[band]>=895) { lcd.write(7); } else if (left[band]>=767) { lcd.write(6); } else if (left[band]>=639) { lcd.write(5); } else if (left[band]>=511) { lcd.write(4); } else if (left[band]>=383) { lcd.write(3); } else if (left[band]>=255) { lcd.write(2); } else if (left[band]>=127) { lcd.write(1); } else if (left[band]>=0) { lcd.write(0); } } // display values of right channel on LCD for( band = 0; band < 7; band++ ) { lcd.setCursor(band+9,0); if (right[band]>=895) { lcd.write(7); } else if (right[band]>=767) { lcd.write(6); } else if (right[band]>=639) { lcd.write(5); } else if (right[band]>=511) { lcd.write(4); } else if (right[band]>=383) { lcd.write(3); } else if (right[band]>=255) { lcd.write(2); } else if (right[band]>=127) { lcd.write(1); } else if (right[band]>=0) { lcd.write(0); } } }

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 (download):

// Example 48.3 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013  // MSGEQ7 spectrum analyser shield with a Freetronics DMD
// for DMD #include <DMD.h> // for DMD #include <SPI.h> // SPI.h must be included as DMD is written by SPI (the IDE complains otherwise) #include <TimerOne.h>  #include "SystemFont5x7.h" // keep next two lines if you want to add some text #include "Arial_black_16.h" DMD dmd(1, 1); // creates instance of DMD to refer to in sketch
void ScanDMD() // necessary interrupt handler for refresh scanning of DMD {  dmd.scanDisplayBySPI(); }
int strobe = 4; // strobe pins on digital 4 int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays int right[7];
int band;
void setup() { // for DMD //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display Timer1.initialize( 5000 ); //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker. Timer1.attachInterrupt( ScanDMD ); //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()  dmd.clearScreen( true ); //true is normal (all pixels off), false is negative (all pixels on)  // for MSGEQ7 pinMode(res, OUTPUT); // reset pinMode(strobe, OUTPUT); // strobe digitalWrite(res,LOW); // reset low digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield }
void readMSGEQ7() // Function to read 7 band equalizers { digitalWrite(res, HIGH); digitalWrite(res, LOW); for( band = 0; band < 7; band++ ) { digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band  delayMicroseconds(30); //  left[band] = analogRead(0); // store left band reading right[band] = analogRead(1); // ... and the right digitalWrite(strobe,HIGH);  } }
void loop() { int xpos; readMSGEQ7(); dmd.clearScreen( true );  // display values of left channel on DMD for( band = 0; band < 7; band++ ) { xpos = (band*2)+1; if (left[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else if (left[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else if (left[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else if (left[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else if (left[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else if (left[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else if (left[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else if (left[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); } }  // display values of right channel on DMD for( band = 0; band < 7; band++ ) { xpos = (band*2)+18; if (right[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else if (right[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else if (right[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else if (right[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else if (right[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else if (right[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else if (right[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else if (right[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); } } }

… and here it is in action:

 

Conclusion

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.

Wednesday, January 16, 2013

Kit Review – SC/Jaycar USB Power Monitor

Introduction

Every month Australian electronics magazine Silicon Chip publshes a varierty of projects, and in December 2012 they published the USB Power Monitor by Nicholas Vinen. Jaycar picked it up and now offers a kit, the subject of our review. This small device plugs inline between a USB port and another device, and can display the current drawn, power and voltage at the USB port with a large LCD module. This is useful when you’re experimenting with USB-powered devices such as Arduino projects or curious how external USB devices can affect your notebook computer’s battery drain.

Assembly

The kit arrives in typical Jaycar fashion:

… everything necessary is included with the kit:

The instructions arrive as an updated reprint of the original magazine article, plus the usual notes from Jaycar about warranty and their component ID sheet which is useful for beginners. The PCB is quite small, and designed to be around the same size as the LCD module:

As you can see below, most of the work is already done due to the almost exclusive use of SMD components:

That’s a good thing if you’re in a hurry (or not the best with surface-mount work). Therefore the small amount of work requires is simply to solder in the USB sockets, the button and the LCD:

It took less than ten minutes to solder together. However – take careful, careful note of the LCD. There isn’t a pin 1 indicator on the module – so instead hold the LCD up to the light and determine which side of the screen has the decimal points – and line it up matching the silk-screening on the PCB. Once finished you can add the clear heatshrink to protect the meter, but remember to cut a small window at the back if you want access to the ICSP pins for the PIC microcontroller:

How it works

The USB current is passed through a 50 mΩ shunt resistor, with the voltage drop being measured by an INA282 current shunt monitor IC. The signal from there is amplified by an op amp and then fed to the ADC of a PIC18F45K80 microcontroller, which does the calculations and drives the LCD. For complete details purchase the kit or a copy of the December 2012 edition of Silicon Chip.

Operation

First you need to calibrate the unit – when first used the meter defaults to calibration mode. You simply insert it into a USB port. then measure the USB DC voltage brought out to two pads on the meter. By pressing the button you can match the measured voltage against the display as shown below – then you’re done.

Then you simply plug it in between your USB device and the socket. Press the button to change the measurement. The meter can measure the following ranges:

For an operational example. consider the next three images are from charging my phone – with the power, current and voltage being shown:

If you want to use the USB ports on the right-hand side of your computer, just press the button while inserting the meter – and it flips around:

Finally – here’s a quick video of the meter at work, whilst copying a file to an external USB hard drive:

 

Conclusion

I really like this – it’s simple and it works. Kudos to Nicholas for his project. You can purchase it from Jaycar and their resellers, or read more about it in the December 2012 edition of Silicon Chip. Full-sized images available on flickr. This kit was purchased without notifying the supplier.

In the meanwhile 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? And join our friendly 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.

Wednesday, January 9, 2013

Review: GorillaBuilderz LeoShield

Introduction

Some of you may be using an Arduino Leonardo board, taking advantage of the newer ATmega32U4 microcontroller for various reasons. And rightly so – there’s the extra analogue I/O, virtual USB and the microUSB socket so you can use your phone charger cable. However with the new microcontroller comes a few changes to the board pinouts – I2C and SPI have moved. So if you have a nice Ethernet shield or something using I2C – you’re basically out of luck… until now. The problem has been solved nicely by the team at GorillaBuilderz have created their LeoShield:

Use

You simply place it on the Leonardo, and then the older legacy shield on top. The LeoShield redirects the I2C pins back to A4 and A5, and also sends the SPI lines back to D11~D13. For example, our Ethernet shield:

The ICSP pins are also extended from the Leonardo to the LeoShield, for example:

however when inserting the LeoShield into your Leonardo, take care lining up all the pins before pushing the shield down. There is also the large prototyping area which has 5V , 3.3V and GND rails across the full width for convenience. The sticker on the rear of the shield is to insulate against any large items that may come in contact from the host board, however you can peel it off to realise the complete prototyping space.

Conclusion

It’s simple and it works – so if you need to use an older Arduino shield with a Leonardo the choice is simple – get yourself a Leoshield.

Disclaimer - The Leoshield was a review product received from GorillaBuilderz.

Thanks for reading tronixstuff.com. I’ve got some new tutorials coming up very soon, and a lot of existing posts are curently being updated – so follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column. And join our friendly 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