Before putting together the final circuit I put (mostly) everything together on a protoboard. Halfway through the project I found a great resource in Imgur user [omenSP]'s http://imgur.com/a/jYhRk. Before I invested in the NeoPixel strip I tested the circuit with a pixel ring I had onhand.
Once I got the complete strip in I realized I had to cut and resolder for the hat. Every time I work with these pixels I burn out or otherwise damage a pixel. Because of the design I had to cut and resolder the strip. One final test before soldering the complete board:
The code I used is below. Credit for large portions of the code goes to [omenSP].
/*
Test #3 adds neopixel ring for visual representation and responsiveness
MSGEQ7 bands = 63Hz, 160Hz, 400Hz, 1,000Hz, 2,500Hz, 6,250Hz, 16,000Hz
Most of this was inspired by
http://pastebin.com/4hHQfq49# & http://imgur.com/a/jYhRk
http://www.eetimes.com/author.asp?section_id=216&doc_id=1323030
I'm sure there is a better way to split L&R channels (omenSP's code averages them for 1 EQ). For right
now I did it fairly manually by doubling up on nearly every variable
At the moment I am sharing strobe and reset pins across both MSGEQ7 chips
*/
//------------------------------------LIBRARIES---------------------------------
#include <Adafruit_NeoPixel.h> // NeoPixel Library
#include <Event.h> // Comes with Timer.h library?
#include <Timer.h> // Timer library
#include <math.h> // Math library
//------------------------------------PIN DECLARATIONS---------------------------------
//int ctrlReset = 2; // Digital pin 2 = signal to reset MSGEQ7s
//int ctrlStrobe = 3; // Digital pin 3 = signal to strobe (read data from) MSGEQ7s
//int Led4 = 4; //LED to light up and test 1 band
const byte dataPinL = 8; // Data pin for Neopixels
const byte dataPinR = 9; // Data pin for Neopixels
//int channelLeft = A0; // Analog pin 0 = spectrum data from left channel
//int channelRight = A1; // Analog pin 1 = spectrum data from right channel
const byte analogPinL = A0; // left channel analog data from shield
const byte analogPinR = A1; // right channel analog data from shield
const byte strobePin = 4; // data strobe for shield
const byte resetPin = 5; // reset strobe for shield
//------------------------------------VARIABLES/CONSTANTS DECLARATIONS---------------------------------
//int spectrumLeft[7]; // Array to store 7 bands of spectrum data from left channel
//int spectrumRight[7]; // Array to store 7 bands of spectrum data from right channel
const byte numBand = 16; // Number of LEDS per band. **change for strip
const byte numTop = 0; // The number of LEDs to have top color
int peakArrayL[7]; // Holds peak values for each of the 7 bands
int peakArrayR[7]; // Holds peak values for each of the 7 bands
Timer t; // Timing variable
String colorPick = "GreenYellowRed"; //Select color palette for EQ. See uint32_t Wheel
int spectrumReadR; //R magnitude from shield
int spectrumReadL; //L magnitude from shield
//int audio = MONO; //set audio mode to mono, combine R&L channels **dunno what this does
int magL = 0; //the magnitude of a freq band
int magR = 0; //the magnitude of a freq band
int numONL = 0; //the number of LEDs on in a freq band
int numONR = 0; //the number of LEDs on in a freq band
float fl_magL = 0.0; //floating point mag after noise removal and scaling
float fl_magR = 0.0; //floating point mag after noise removal and scaling
const int noise[] = {1, 1, 1, 1, 1, 1, 1}; // set this to magnitude of noise from shield
const float gain[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; // - gain for each band
const unsigned long loop_dlay = 35; // loop delay to slow down display update rate
byte //**not the faintest idea what this does, and i feel like it will throw an error
peak = 0,
dotCount = 0;
Adafruit_NeoPixel stripL = Adafruit_NeoPixel(numBand, dataPinL, NEO_GRB + NEO_KHZ800); //**mult #pins for strip?
Adafruit_NeoPixel stripR = Adafruit_NeoPixel(numBand, dataPinR, NEO_GRB + NEO_KHZ800); //**mult #pins for strip?
void setup()
{
Serial.begin(9600);
/*-------------FROM OLD PROGRAM--------------
pinMode(ctrlReset,OUTPUT); // Define reset as output
pinMode(ctrlStrobe,OUTPUT); // Define strobe as output
pinMode(Led4,OUTPUT);
digitalWrite(ctrlReset,LOW); // Pull the reset signal low
digitalWrite(ctrlStrobe,HIGH); // Drive the strobe signal high
digitalWrite(Led4,LOW);
*/
pinMode(resetPin, OUTPUT);
pinMode(strobePin, OUTPUT);
pinMode(dataPinL, OUTPUT);
pinMode(dataPinR, OUTPUT);
// Start strip communication and start them at 1/4 brightness and blank
stripL.begin();
stripR.begin();
stripL.setBrightness(64); // Control strip brightness **see how well it works in a lit room
stripR.setBrightness(64); // Control strip brightness **see how well it works in a lit room
stripL.show(); // Initialize all pixels to 'off'
stripR.show(); // Initialize all pixels to 'off'
digitalWrite(resetPin,HIGH);
delayMicroseconds(5);
digitalWrite(strobePin,HIGH);
delayMicroseconds(50); // strobe PW > 18 usec min
digitalWrite(strobePin,LOW);
delayMicroseconds(50); //reset PW > 100 usec min
digitalWrite(resetPin,LOW);
delayMicroseconds(5);
digitalWrite(strobePin,HIGH);
delayMicroseconds(100); // allow reset to strobe falling > 72 usec min
t.every(100,peakLower); // calls peakLower function every 100 ms **(why?) (or 10ms?)
}
/*void loop() //---------VOID LOOP FROM OLD PROGRAM---------------
{
readMSGEQ7();
//-----------debug lines from the old program. update this, b/c it could be helpful--------------
// Display values from the left channel on the serial monitor
for (int i = 0; i < 7; i++)
{
if (spectrumLeft[i] < 100) Serial.print(" ");
if (spectrumLeft[i] < 10) Serial.print(" ");
Serial.print(spectrumLeft[i]);
Serial.print(" ");
}
Serial.print(" ");
// Display values from the right channel on the serial monitor
for (int i = 0; i < 7; i++)
{
if (spectrumRight[i] < 100) Serial.print(" ");
if (spectrumRight[i] < 10) Serial.print(" ");
Serial.print(spectrumRight[i]);
Serial.print(" ");
}
Serial.println();
//-------LED DEBUG FROM OLD PROGRAM. PROBABLY DELETE THIS---------
if (spectrumLeft[4] > 100)
digitalWrite(Led4,HIGH);
else
digitalWrite(Led4,LOW);
}
*/
/*-------------THE READ FUNCTION FROM EETIMES PROGRAM. USING omenSP's FOR NOW---------------
void readMSGEQ7() { // Read the seven spectrum bands from the MSGEQ7 chips
digitalWrite(ctrlReset, HIGH); // Pulse the reset signal, which causes
digitalWrite(ctrlReset, LOW); // the MSGEQ7s to latch the spectrum values
delayMicroseconds(75); // Delay to meet minimum reset-to-strobe time
for(int i=0; i <7; i++) // Cycle through the 7 spectrum bands
{
digitalWrite(ctrlStrobe,LOW); // Read current band (then increment to next band)
delayMicroseconds(40); // Wait for outputs to settle
spectrumLeft[i] = analogRead(channelLeft) / 4; // Store current values from left & right channels
// spectrumRight[i] = analogRead(channelRight) / 4; // Divide 0-1023 by 4 to give 0-255
//Dividing by 4 is really for PWM output and I can probably eliminate that later
digitalWrite(ctrlStrobe,HIGH);
delayMicroseconds(40); // Delay to meet minimum strobe-to-strobe time
}
}
*/
void loop() {
for(byte band = 1; band <= 7; band++) {
digitalWrite(strobePin, LOW); //set analyzer to low to read
delayMicroseconds(40);
spectrumReadR = analogRead(analogPinR); //read right audio
spectrumReadL = analogRead(analogPinL); //read left audio
digitalWrite(strobePin, HIGH); //set analyzer back to high
//---------NOT SURE WHY THIS SECTION IS IN BOTH LOOP() AND READBAND()---------
// mag = (spectrumReadR + spectrumReadL) / 2;
magL = max(0, (magL - noise[band-1])); //creates magnitude of frequency
magR = max(0, (magR - noise[band-1])); //creates magnitude of frequency
fl_magL = gain[band-1] * float(magL); //adjusts magnitude for gain
fl_magR = gain[band-1] * float(magR); //adjusts magnitude for gain
numONL = map(fl_magL, 0, 1024, 0, numBand+1); //maps magnitude to number of active pixels
numONR = map(fl_magR, 0, 1024, 0, numBand+1); //maps magnitude to number of active pixels
anyBand(band);
//Serial.print(band);
//Serial.println(peakArray[band-1]);
if(peakArrayL[band-1]==0) stripL.setPixelColor(peakArrayL[band-1] + numBand*(band-1), stripL.Color(0,0,0));
else stripL.setPixelColor(peakArrayL[band-1] + numBand*(band-1), stripL.Color(255,0,0));
if(peakArrayR[band-1]==0) stripR.setPixelColor(peakArrayR[band-1] + numBand*(band-1), stripR.Color(0,0,0));
else stripR.setPixelColor(peakArrayR[band-1] + numBand*(band-1), stripR.Color(255,0,0));
t.update();
}
// strip.setBrightness(40); //I already did this up top. why do it again?
stripL.show();
stripR.show();
delay(loop_dlay);
}
void readBand(byte band) {
for(byte band = 1; band <= 7; band++) {
digitalWrite(strobePin, LOW); //set analyzer to low to read
delayMicroseconds(40); //minimum delay for MSGEQ7
spectrumReadR = analogRead(analogPinR); //read right audio
spectrumReadL = analogRead(analogPinL); //read left audio
digitalWrite(strobePin, HIGH); //set analyzer back to high
//mag = (spectrumReadR + spectrumReadL) / 2; //average L and R spectrums to make mono
magL = max(0, (magL - noise[band-1])); //creates magnitude of frequency
magR = max(0, (magR - noise[band-1])); //creates magnitude of frequency
fl_magL = gain[band-1] * float(magL); //adjusts magnitude for gain
fl_magR = gain[band-1] * float(magR); //adjusts magnitude for gain
numONL = map(fl_magL, 0, 1024, 0, numBand+1); //maps magnitude to number of active pixels
numONR = map(fl_magR, 0, 1024, 0, numBand+1); //maps magnitude to number of active pixels
anyBand(band);
}
}
void anyBand(byte band) { // For each LED on a single freq band, turn on or off
for(byte i = 0; i < numBand; i++){ // depending on if that freq was seen. Also provides
if(i < (numONL - numTop - 1)){ // for a falling peak **that i may want to comment out
stripL.setPixelColor(i + numBand*(band-1), Wheel(map(i,0,numBand-1,20,83))); //main wheel colors
}
else if(i >= numONL){
stripL.setPixelColor(i + numBand*(band-1), stripL.Color(0,0,0)); //unused colors on wheel
}
else{
if(i > peakArrayL[band-1]) peakArrayL[band-1] = i; //used for falling peak dot
}
}
for(byte i = 0; i < numBand; i++){
if(i < (numONR - numTop - 1)){
stripR.setPixelColor(i + numBand*(band-1), Wheel(map(i,0,numBand-1,20,83))); //main wheel colors
}
else if(i >= numONR){
stripR.setPixelColor(i + numBand*(band-1), stripR.Color(0,0,0)); //unused colors on wheel
}
else{
if(i > peakArrayR[band-1]) peakArrayR[band-1] = i; //used for falling peak dot
}
}
}
void peakLower() { // **Not quite sure what this does yet
for(byte i = 0; i < 7; i++) {
if(peakArrayL[i] > 0) peakArrayL[i]--;
if(peakArrayL[i] > 0) peakArrayL[i]--; //**Not sure if I implemented these 2 channels right
else continue;
}
}
uint32_t Wheel(byte WheelPos) { // Allows to select color palette
if(colorPick == "GreenYellowRed") {
return stripL.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
return stripR.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
else if(colorPick == "PinkPurpleBlue") {
return stripL.Color(255 - WheelPos * 3, 0, WheelPos * 3);
return stripR.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
else if(colorPick == "GreenTealBlue") {
return stripL.Color(0, 255 - WheelPos * 3, WheelPos * 3);
return stripR.Color(0, 255 - WheelPos * 3, WheelPos * 3);
}
}
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.