3 Simple Ways to
Share What You Make

With Instructables you can share what you make with the world — and tap into an ever-growing community of creative experts.

PhotosPhotos

Share one or more photos of a project, recipe, or whatever you've made, quickly and easily.

Step by StepStep-By-Step

Share your step-by-step photos with text instructions of what you made so others can do it too!

VideoVideo

Share your how-to video. You'll need your embed code from a video site such as YouTube.

The LED Matrix Panel, or LMP, for the Arduino microcomputer, continued.

The LED Matrix Panel, or LMP, for the Arduino microcomputer, continued.
Last time, in part 1 we introduced you to the LMP, a simple, lost-cost part that connects directly to the Arduino. This time, we will continue with a simple program I call the Musicator.

It is a simple Spectrum Analyser, completely done in software, which reads the output from an earphone plug (on A01), and generates a 5-channel pattern on the LMP, based on the loudness and frequency of the signal.

Here is a sample video:


All you need, beside the LMP and, of course, the Arduino, is a cable with a jack that fits into an earphone socket. It doesn;t matter whether you use the Left or Right channel.
 
Remove these adsRemove these ads by Signing Up
 

Step 1The Sketch (LMP_Musicator01)

The Sketch (LMP_Musicator01)
/*
  • VUmeter / Light organ (Full db presentation)
  • Horizontal presentation - center-out linear display
  • (c) Copyright 2009 QS@quantsuff.com
  • All Rights Reserved
*
  • LED Matrix row:1-5; col:1-6
  • Map PORTB == D8:D12 - pin[row+7] : +v
  • PORTD == D2:D7 - pin[8-col] ; Gnd
  • Our output: col::D2:D7 -ve (LOW) while row::D8:D13 +ve
*/

char msg[] = {
0x11, 0x0a, 0x0e, 0x0e, 0x0a, 0x11, // Starburst
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
0x11, 0x19, 0x1e, 0x00, 0x1f, 0x10, // Q U
0x1f, 0x00, 0x1e, 0x05, 0x1e, 0x00, // A
0x1f, 0x06, 0x0c, 0x1f, 0x00, 0x03, // N T
0x1f, 0x03, 0x00, 0x12, 0x15, 0x09, // S
0x00, 0x1f, 0x10, 0x1f, 0x00, 0x1f, // U F
0x05, 0x05, 0x00, 0x1f, 0x05, 0x05, // F
0,0,0,0,0,0 }; //Plus an overrun buffer

// bit pattern, 1 byte per column. Top = lsb

char display[6], hdisp[6] ;

int w10kbuf[2], w1kbuf[20], w100buf[100]; // Assume all zeroed (:P)
int w10kidx, w1kidx, w100idx;
// int w10kmax, w5kmax, w1kmax, w500max, w100max;
long w, w10ksum=0, w1ksum=0, w100sum=0;
int www, w10k, w1k, w100, meter[5] ;

int scale=3; // log scale (start at 23)
int recal=0; //AGC rate
int inPin=1 ; // analogRead on A01

void setup() // run once, when the sketch starts
{
for (int ledPin=2; ledPin<=12; ledPin++) {
pinMode(ledPin, OUTPUT); // sets the digital pin as output
digitalWrite(ledPin,(ledPin<=7)) ; //Disable all cols
}
lmpWrite(msg,0,15); //Cycle delay is 1/10 secs
// (it's really to initialize the counters)
analogReference(INTERNAL) ; // Do not use DEFAULT or EXTERNAL!
int i= digitalRead(inPin); // remove old data
}

void loop() // run over and over again
{
w100 = (w100sum / 23) >> scale; // A cheap filter @ app 100Hz
w1k = abs((w1ksum / 3)-w100) >> scale; // 1kHz
w10k = (www+w10ksum) >> scale; // 10kHz
w= (w100 + w1k + w10k) ; // Total power (VU function)

if (w<13) {
recal++;
if (recal>=15) { //350mS counts before recalibration of meter
recal=0;
scale-= (scale>3);
} }// increase res only if less than 1/2 scale

// if ((w100>33) || (w1k>30) || (w10k>33)) { // log2
if ((w100+w1k+w10k)>83) { // Peaked: make it less sensitive
recal=0;
scale++;
w100= w100>>1;
w1k = w1k >>1;
w10k = w10k >>1;
}
meter[0]= min(w100>>1,31);
meter[1]= min(abs(w100+w1k-w10k)>>2,31);
meter[2]= min(w1k>>2,31);
meter[3]= min(abs(w1k+w10k-w100)>>2,31);
meter[4]= min((w10k*5)>>3,31);

for (int col=0;col<6;col++) {
int c=0;
for (int mm=0; mm<=4; mm++) {
c= c<<1;
c+= (meter[mm] > col);
}
hdisp[col]= c;
}
display[0]= hdisp[4];
display[1]= hdisp[2];
display[2]= hdisp[0];
display[3]= hdisp[0];
display[4]= hdisp[2];
display[5]= hdisp[4];

lmpWrite(display,0,1);

display[0]= hdisp[5];
display[1]= hdisp[3];
display[2]= hdisp[1];
display[3]= hdisp[1];
display[4]= hdisp[3];
display[5]= hdisp[5];

/* Vertical display routine
*
fillVBar(display,0,w100);
fillVBar(display,1,abs(w100+w1k-w10k));
fillVBar(display,2,w1k);
fillVBar(display,3,abs(w1k+w10k-w100));
fillVBar(display,4,w10k);
//fillVBar(display,5,w10k>>1);
//fillVBar (display,5,scale+1);
int i=0;
int s=scale-1;
for (int ii=0; ii<5; ii++) {
i= i | (s & 1);
i= i<<1;
s= s>>1;
}
display[5]= i;
*
*/

lmpWrite(display,0,1);
}

void fillVBar(char disp[],int o, int val) {
int j= B100000; // digit pattern
val= constrain(val,2,127) ;
while (val>2) {
j|= (j>>1) ;
val= val>>1 ;
}
disp[o]=j;
}

void lmpWrite(char disp[],int stchar,int steps)
/* Usage: Loads bit pattern in disp[], starting at stchar,
  • 1 byte per column, left-to-right, top-to-bottom
  • Map PORTB == D8:D12 - pin[row+7] : +v
  • PORTD == D2:D7 - pin[8-col] ; Gnd
*/
{
int col, row, cval, lit=0, ww=0;
long delayStart=millis() + 90*(constrain(steps,1,100)) ;
// Display / loop time
www= 0 ;
do {
for (col=0; col<6; col++) {
cval = disp[col+stchar];
for (row=1; row<=5; row++) { //only 5 lower bits
if (cval & 1) { // light this LED
if (lit==0)
digitalWrite(7-col,LOW); //col needs activating
digitalWrite(row+7,HIGH);
lit++ ; // in case we need to know how many LEDs are lit
}
// Cycle stealing here, to read VU input
ww=max(ww,analogRead(inPin)) ; //Raw volume data (rectified)
www=max(ww,www) ; //Peak retect
delayMicroseconds(80); //This makes sure the panel is
// lit the same period of time.
digitalWrite(row+7,LOW); //Turn LED off
cval = cval>>1 ; // check the next bit
}
digitalWrite(7-col,HIGH); // turn col OFF
w10ksum+= www-w10kbuf[w10kidx]; // This is our 'capacitor'
w10kbuf[w10kidx]=www;
w10kidx++;
w10kidx= ((w10kidx<1)); // 0 or 1
//if (w10kidx>3) w10kidx=0;
//w10ksum=ww ; // Increase the high-end response

w1ksum+= ww-w1kbuf[w1kidx];
w1kbuf[w1kidx]=ww;
w1kidx++;
if (w1kidx>19) w1kidx=0;
//w1kidx= ((w1kidx<19) && (w1kidx++)); // 0 - 19

w100sum+= ww-w100buf[w100idx];
w100buf[w100idx]=ww;
w100idx++;
if (w100idx>99) w100idx=0;
//w100idx= ((w100idx<1) && (w100idx++)); // 0 - 199

lit = 0;
}
}
while (delayStart > millis()) ;
}
« Previous StepDownload PDFView All StepsNext Step »
25 comments
May 29, 2011. 2:18 PMjaragon says:
i have build the lmp and constructed as in the instruc, but now all the musicator does is keep the leds high when i input an audio signal :(
Nov 29, 2010. 12:17 PMbenoit-1842 says:
what is the a01 ???? The place you put the earphone ???
Nov 29, 2010. 4:51 PMbenoit-1842 says:
thanx a lot for your quick response...It's my first project so i'm a little bit...nervous. Can we have more details about building the board on the project 1.... (solder etc....)


Thanx Ben
Nov 29, 2010. 11:40 AMbenoit-1842 says:
i want to start the project but I don't understand where you put your earphone socket !!!!?????
Sep 15, 2009. 3:37 PMMdob says:
Is it possible to expand the amount of leds and would you have to change the code to make the different patterns? If it is how would you?
May 12, 2010. 3:57 PMfruitkid101 says:
Ha! I built one for the arduino mega (tons of pins) It's way bigger and can do simple animations, Great!
Sep 16, 2009. 3:37 PMMdob says:
Ok, thanks for the info; i was just wondering if it could be done.
Jan 13, 2010. 4:22 PMredrosid23 says:
 I have zero experience with arduinos so please excuse my ignorance,

is it possible to operate this without it being connect to the computer, or does the arduino receive the code from the computer during operation?
May 12, 2010. 3:55 PMfruitkid101 says:
Yes, you can use it without the computer. When you upload the code, the arduino stores it and will use it whenever powered up. If you want to use the arduino without a computer, you just have to supply 5v and Gnd to it either by making a cable that can do that, or otherwise
Dec 8, 2009. 8:24 PMCrink says:
Love the project.  I am actually thinking of trying to do the same thing using a FFT transform.  If it is not too much trouble, could you provide a more commented version of your code.  I do not just want to use it but understand it and adapt it.  Thanks.
Dec 30, 2009. 4:51 AMsteveastrouk says:
He's implemented it very cleverly as a series of discrete digital filters, rather than an FFT. Would an FFT work better ? 
Jan 6, 2010. 3:51 PMCrink says:
Not quite sure if an FFT would be easier but the problem with the FFT is the memory involved in the computations.  It would be cool to implement it thought.  Yeah I see the digital filters now.  Thanks.
Sep 17, 2009. 6:53 AMajam123 says:
Oh my god... it actually works!
Apr 20, 2009. 10:51 PMnigel_g says:
If I paid you to build me one of these, what would it cost?
Apr 15, 2009. 1:42 AMfrollard says:
Phenomenal project! Software is so important in a project like this - very well executed!
Apr 15, 2009. 9:39 PMfrollard says:
I'm looking to build an uuber-pov project - and with experimenting with 'more efficient' shifting, want to use generic shift registers to have a 48-bit arduino register :D it will be excellent.
Apr 15, 2009. 11:57 PMfrollard says:
essentially, I need to something-plex the output to get enough pixels. One word description- "Minivan-pov" :D To someone driving next to you it would look like a glowing bar. Stationary objects would see a picture/message

Use 6 registers @ 8 bits each, latched in parallel, so thats 48 bits in 8 shifts - common clock, latch - and parallel data = 6 + 1+1...easy data output. Just need to tweak the shiftout library to output a matrix instead of an array. There was a lot of buzz on the forum using more advanced techniques for the backend code for shiftout to not use digitalwrite, but rather some fancy assembly that saves a few clock cycles per shift.

The registers I'm using have an active (I forget) low or high latch for data input mode (output off) and data output mode (output on)...basically you can achieve good thruput with this parallel buffer in that you draw frame n+1 while you display frame n.

GHASP! I've spilled my secrets!
Apr 16, 2009. 3:00 PMfrollard says:
yeah, like a wheelpov, but horizontal motion and vertical bar. For the subway Idea if it were powered, and had a little radar to tell the speed of the train, it would work to make a moving image for the riders, just not animated.

Pro

Get More Out of Instructables

Already have an Account?

close

All Steps Viewing
View all steps of an Instructable on the same page when you're a Pro Member.

Upgrade to Pro today!
177
Followers
22
Author:qs