Spectrum Shield with LED Output

I’m trying to get SparkFun’s ‘spectrum shield’ working, with 7 LEDs as output, as in this tutorial.

With the PWM demo (code below), my LEDs are lighting up randomly, even when no audio input is plugged in! Any suggestions as to why this might be happening and what I might do to fix it?

(And when the aux cable is plugged in to the shield and either to my computer or phone, the LED response does not seem to correspond to the music that’s playing.)

Images of my setup are attached. The code I’m using is below.

(Perhaps relatedly, there’s a quiet hum (around a B4) when I wear my headphones plugged into the output jack on the shield…)

/****************************************************************************** 
SparkFun Spectrum Shield PWM Demo
Toni Klopfenstein @ SparkFun Electronics
February 2015
https://github.com/sparkfun/Spectrum_Shield

This sketch shows the basic functionality of the Spectrum Shield, working with a basic RGB LED Matrix.

The Spectrum Shield code is based off of the original demo sketch by Ben Moyes @Bliptronics.  
This sketch is available in the Spectrum Shield repository. 

Development environment specifics:
Developed in Arduino 1.6.

This code is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
*********************************************************************************/

//Declare Spectrum Shield pin connections
#define STROBE 4
#define RESET 6
#define DC_One A0
#define DC_Two A1 


//Define LED connections on the shield
int LED[] = {7, 8, 9, 10, 11, 12, 13};

//Define spectrum variables
int freq_amp;
int Frequencies_One[7];
int Frequencies_Two[7]; 
int i;

/********************Setup Loop*************************/
void setup() {
  
  //Set LED pin configurations
  for(i=0; i<7; i++)
  {
    pinMode(LED[i], OUTPUT);
    digitalWrite(LED[i], LOW);
  }
  
  //Set Spectrum Shield pin configurations
  pinMode(STROBE, OUTPUT);
  pinMode(RESET, OUTPUT);
  pinMode(DC_One, INPUT);
  pinMode(DC_Two, INPUT);  
  digitalWrite(STROBE, HIGH);
  digitalWrite(RESET, HIGH);
  
  //Initialize Spectrum Analyzers
  digitalWrite(STROBE, LOW);
  delay(1);
  digitalWrite(RESET, HIGH);
  delay(1);
  digitalWrite(STROBE, HIGH);
  delay(1);
  digitalWrite(STROBE, LOW);
  delay(1);
  digitalWrite(RESET, LOW);
}


/**************************Main Function Loop*****************************/
void loop() {
  
  Read_Frequencies();
  Graph_Frequencies();
  delay(50);
 
}


/*******************Pull frequencies from Spectrum Shield********************/
void Read_Frequencies(){
  //Read frequencies for each band
  for (freq_amp = 0; freq_amp<7; freq_amp++)
  {
    Frequencies_One[freq_amp] = analogRead(DC_One);
    Frequencies_Two[freq_amp] = analogRead(DC_Two); 
    digitalWrite(STROBE, HIGH);
    digitalWrite(STROBE, LOW);
  }
}

/*******************Light LEDs based on frequencies*****************************/
void Graph_Frequencies(){
   for( i= 0; i<7; i++)
   {
     if(Frequencies_Two[i] > Frequencies_One[i]){
        analogWrite(LED[i], Frequencies_Two[i]/4);
     }
     else{
        analogWrite(LED[i], Frequencies_One[i]/4);
     }
   }
}

IMG_1555 (1).JPG

IMG_1556 (1).JPG

The analogWrite() works only on PWM pins, see the "~" on the pin labels. Change your LED connections and LED[] array accordingly.

You may get ground loops, injecting noise to the sound inputs. Such loops result from multiple Gnd connections, like from USB and sound connections. Try to power the Arduino from a battery or other power supply, and remove the USB cable. Or use an isolated sound source, like mp3 player, instead of PC outputs. Check with your headphone whether the hum then disappears.

Thanks DrDiettrich! I powered the Arduino from a wall wart, and I do get less ground loop noise–though still a little bit.

I’ve changed the LEDs and LED array in the code accordingly… but I still get the same LED response with the audio cable plugged in (and music playing) as I do when it’s not plugged in to anything (both using the PWM demo, the code above, and with the code below-- with this, the LEDs just blink one after the other, but not in time with the music).

It seems like somehow there is no input from the ICs on the shield-- any ideas what could be wrong?

(I’ve tried playing sine tones from here, and I still get the same seemingly random response of LEDs lighting up.)

/****************************************************************************** 
SparkFun Spectrum Shield Demo
Toni Klopfenstein @ SparkFun Electronics
December 2015
https://github.com/sparkfun/Spectrum_Shield

This sketch shows the basic functionality of the Spectrum Shield, working with a basic RGB LED Matrix.

The Spectrum Shield code is based off of the original demo sketch by Ben Moyes @Bliptronics.  
This sketch is available in the Spectrum Shield repository. 

Development environment specifics:
Developed in Arduino 1.6.

This code is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
*********************************************************************************/

//Declare Spectrum Shield pin connections
#define STROBE 4
#define RESET 5
#define DC_One A0
#define DC_Two A1 


//Define LED connections on the Arduino/Shield
int LED[] = {3, 5, 6, 9, 10, 11, 13};

//Define spectrum variables
int freq_amp;
int Frequencies_One[7];
int Frequencies_Two[7]; 
int i;

/********************Setup Loop*************************/
void setup() {
 //Set LED pin configurations
 for(i=0; i<7; i++)
 {
   pinMode(LED[i], OUTPUT);
   digitalWrite(LED[i], LOW);
 }
 
 //Set spectrum Shield pin configurations
 pinMode(STROBE, OUTPUT);
 pinMode(RESET, OUTPUT);
 pinMode(DC_One, INPUT);
 pinMode(DC_Two, INPUT);  
 digitalWrite(STROBE, HIGH);
 digitalWrite(RESET, HIGH);
 
 //Initialize Spectrum Analyzers
 digitalWrite(STROBE, LOW);
 delay(1);
 digitalWrite(RESET, HIGH);
 delay(1);
 digitalWrite(STROBE, HIGH);
 delay(1);
 digitalWrite(STROBE, LOW);
 delay(1);
 digitalWrite(RESET, LOW);
}


/**************************Main Function Loop*****************************/
void loop() {
 
 Read_Frequencies();
 Graph_Frequencies();
 delay(50);

}


/*******************Pull frquencies from Spectrum Shield********************/
void Read_Frequencies(){
 //Read frequencies for each band
 for (freq_amp = 0; freq_amp<7; freq_amp++)
 {
   Frequencies_One[freq_amp] = analogRead(DC_One);
   Frequencies_Two[freq_amp] = analogRead(DC_Two); 
   digitalWrite(STROBE, HIGH);
   digitalWrite(STROBE, LOW);
 }
}

/*******************Light LEDs based on frequencies*****************************/
void Graph_Frequencies(){
  for( i= 0; i<7; i++)
  {
    if(Frequencies_Two[i] > Frequencies_One[i]){
       digitalWrite(LED[i], HIGH);
       delay(Frequencies_Two[i]);
       digitalWrite(LED[i], LOW);
    }
    else{
       digitalWrite(LED[i], HIGH);
       delay(Frequencies_One[i]);
       digitalWrite(LED[i], LOW);
    }
  }
}

Some ideas:

Serious diagnostics require a sine wave source of variable frequency and volume, e.g. a couple of sound files of a constant frequency each. Can you record and play back such files?

Disconnect and shorten the audio inputs, to separate external from internal noise. When the display stabilizes, the problem is external noise.

What happens when you put a constant voltage on the analog input? Disconnect the shield, and use another input pin in code. Then all LEDs should react the same when you modify the analog voltage. You can test various conditions, with the shield removed/installed, with sound applied or off. This will allow to identify internal noise, introduced by the shield itself.

The filter may be too sensitive. Try to reduce the input volume, or zero the ADC readings below some threshold.

The channel settling time may be too high. Add a short delay (100µs) before reading the ADC, or analogRead twice and discard the first value.

There exists a special ADC Noise Canceler mode, removing some internal noise from the ADC readings. But that's tricky to implement, if you cannot find sample code.

And don't expect too much from such a spectrum analyzer, but at least the display should follow the input (volume), somehow.

Thanks for your reply, and for all the suggestions!

I tried playing sine tones of different frequencies at different volumes from the website indicated above... and still got the same random looking output. In using the Spectrum demo code, the LEDs just flash in sequence, as if there is no audio input, even when playing various tones at various volumes.

I tried reduced the input volume to the minimum possible value, with no visible change. I also tried adding a delay, also with no visible change.

I'm not concerned about the ground loop noise so much anymore, as it seems barely audible. But by shortening the audio inputs do you mean shortening the aux cable?

Maybe I'm not understanding the sample code correctly...

I assumed the Frequencies arrays were arrays of the amplitude (/DC output) at each frequency band (i.e. the first value in the array was the amplitude at the lowest frequency band, and the next value was the value at the next lowest frequency band etc.). I also thought each array was from a different IC. But now I'm wondering why there are two-- is one for the left channel, and the other for the right? (Why does the shield have two identical ICs in the first place?)

If the Frequency arrays are based on amplitude (DC output), it makes sense to change the brightness of the LED based on these... so the PWM sketch makes sense-- louder bands have brighter corresponding LEDs. But the Spectrum demo sketch has a delay that's as long as a value from the Frequency array: delay(Frequencies_Two*).* Is this just choice to represent amplitude of a sound in a particular band using frequency of LED blinking? (It seems weird to represent amplitude with delay...)

The 2 chips support a left and a right channel, whose data are stored in the two array. The output corresponds to the maximum of both channels, so that you may get garbage with a signal on only one channel. Modify the Graph_Frequencies() to show only the channel you use.

I missed that there exist two sketches with different output procedures. To me only the PWM version with analogWrite makes sense.

That’s helpful, thanks!

I think I’m back to the ground loop noise problem… what I thought was minimal is perhaps not as minimal as I thought.

I’ve modified the Graph_Frequencies function so I can see what’s happening. It looks like the LEDs are lighting up in response to whatever noise I’m hearing through my headphones when nothing is playing on my computer. Interestingly, I can hear the noise through headphones when the Arduino is plugged into my computer, but I can’t hear it when the USB cable is unplugged! However, I can still see the LEDs blinking with a similar pattern as when I can hear the sound! It seems quite obvious (using the modified sketch) now that the LEDs are blinking in time with the sound (moderately high pitched beeps, at two different B, an octave apart).

For reference, the modified bit of code below.

void Graph_Frequencies(){
   for( i= 0; i<7; i++)
   {
     if(Frequencies_Two[i] > Frequencies_One[i]){
        analogWrite(LED[i], 200);
     }
     else{
        analogWrite(LED[i], 0);
     }

     Serial.println("two");
     Serial.println(Frequencies_Two[i]);
     Serial.println(Frequencies_One[i]);
   }
}

(Beyond this, even when I do play actual music on to of the ground loop noise, the LEDs don’t seem to be responding to it at all… but perhaps that’s a problem to conquer after this one?)

Better use
for( i= 0; i<7; i++) analogWrite(LED, Frequencies_One*/4);*
This will give brightness proportional to the signal amplitude.

Thanks.

Any ideas what might be causing the ground loop noise now? I've powered the board using a wall wart.

And any ideas why the board doesn't seem to be responding to music input via the aux cable?

I've also tried powering the board via USB to both laptop and desktop, as well as using a phone and computer as input.

Is there some way I can tie the grounds together to eliminate this?

Do you think ground loop noise is related to the problem of not seeing any response to 'real' audio?

I’ve tried printing shield/IC output values (from A0 and A1) to serial monitor, using the code below. I’ve experimented with different frequencies, using only left channel or only right channel, different volumes, different audio inputs (computer, phone), all with no visible changes in the values printed (which are supposed to be the amplitude at particular frequency bands in each of the left and right channels! so they should be different when I change the frequency or volume or channel of the input, unless I’m doing something very wrong).

// 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(9600);
 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();
 delay(500);
 // 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();
}

Now the channel on the right band (A1) seems to be working!

But the left channel IC (A0) is outputting 1023 1022 1023 etc. for all frequency bands all the time...

When the second analogRead is okay, the delay may still be too short. If so, swapping the analoRead lines should read reasonable values for the other channel.