Combining Octows2811 shield and the audio shield

Status
Not open for further replies.

Flinch

Member
Heya =)

I'm running ~600 ws2812 pixels and wanted it to react to the music, basically have a hue range of 60ish (reds to yellows) and and have reds as deeper frequencies and yellows as higher frequencies.

Im using the fastSPI library since I already have some good animations in it and im more familiar with it, but wanted to use the octoshield for its 5v output and ease of use.....

I noticed some pin conflicts but when I breadboarded it with what I needed for the strips im using it seemed to work fine so now im putting together a shield shield :p

Is there anything I should be worried about in doing this?

Give us a shout if you want the code =)

Cheers

-Mat
 
Hi,

I've bought the parts from PJRC and hope to play with them this weekend. So far I've just read the web pages. When you say 'pin conflicts' do you mean the overlap between the SPI on the card reader and OctoWS2811's LED strip pins, so if I don't use the SD card reader I can use OctoWS2811 and the audio adapter together? Is this what you're doing?

Any code and/or video will be much appreciated.
 
Heya

Tbh I havent checked, the event Im doing it for soon and deadline approaches.....

Heres the code so far. It basically takes the raw freq and changes it to 8 bands averaged to between 0 and 50. Its got a mode for low / high freq. But going to have it working with the leds first then tune it.... Its a mash up between me and a friend so sorry for its quality..

Code:
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <FastLED.h>


#define LED_COUNT 391
#define BIN_LENGTH 7   // ****???
#define DATA_PIN 2
#define CLK_PIN 4

const int myInput = AUDIO_INPUT_LINEIN;


// Standard audio stuff

AudioInputI2S       audioInput;         // audio shield: mic or line-in
AudioAnalyzeFFT256  myFFT(20);
AudioOutputI2S      audioOutput;        // audio shield: headphones & line-out


AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFFT, 0);
AudioConnection c3(audioInput, 1, audioOutput, 1);


AudioControlSGTL5000 audioShield;



struct CRGB leds[LED_COUNT];



double MAX_SIZE = 200.0;   // Max range of averaged freq bands
int max_bright = 255;
int count = 0;
int c = 0;
int audio = 0;
int led_mode = 0;
int iterations = 10000;
const int half = 1;

int arbritaorySize_array = 50;


int hue = 35;
int hueCounter;


unsigned long time;

IntervalTimer smpltimer;


int scale_doof(double val, int f_band){

  if(f_band > 1) {            // Alter to tune frequencies?
    val = val*4;
  }
  if (val > MAX_SIZE) {
     val = MAX_SIZE;
  }
  return (val/MAX_SIZE)*arbritaorySize_array;
}


void zero_leds(void) {
  int i;
  for(i = 0; i < LED_COUNT; i++) {
    leds[i].setRGB(0,0,0);
  } 
}



void modHue(int hueMod, int mode) {
  
 

}

void set_doof(int scale, int mode, int f_band) {
 
 
 
 if (mode == 0) {
   hue = hue - scale;
    Serial.print("-------");
    Serial.println(hue);
    
    if (hue < 10) {
    hue = 10;
  }
 }
 else if (mode == 1) {
   hue = hue + scale;   
    Serial.print("-------");
    Serial.println(hue);
    
  if (hue > 54) {
    hue = 54;
  }
 }
  
  
  
  /*DEBUGGGG
   Serial.print("-------");
  Serial.print("Scale: ");
  Serial.println(scale);
  Serial.println("-------");
  

  
 Serial.print("mode: ");
  Serial.println(mode);
  Serial.println("-------");

  
 Serial.print("f_band: ");
  Serial.println(f_band);
  Serial.println("-------");
  }

  
*///


/* ------------------ Hue Fader ----------------

  if (hue > 54) 
  {hueCounter = 1;} 
  if (hue < 10)
  {hueCounter = 0;}
   
   
    
  if(hueCounter == 0)
  {hue++;}
  if(hueCounter ==1)
  {hue--;}
  
  ---------------------------------------------------*/


}



void update_audio(double fft[]) {

  int i, j, scaled;
  
  int mode = 0;
  
  for(i = 0; i < BIN_LENGTH; i++) {
    scaled = scale_doof(fft[i], i);
    if(i > 3){
      mode = 1;
    }
    set_doof(scaled, mode, i);
  }

  count++;
 


  LEDS.show();

  
  zero_leds();

}





void setup() {

  AudioMemory(12);
  audioShield.enable();
  audioShield.inputSelect(myInput);
  audioShield.volume(1.5);
  Serial.begin(115200);
  
  smpltimer.begin(smpltimerisr, 1000000); //seconds = Value/1000000

  LEDS.setBrightness(max_bright);

  LEDS.addLeds<NEOPIXEL,DATA_PIN>(leds, LED_COUNT);    //Change to multistrip style. 

 /* Populate arrays with pixel counts*/
  
 
}



void loop() {



  if (myFFT.available()) {
    // each time new FFT data is available
    // print it all to the Arduino Serial Monitor
    //Serial.println(count);
    int i, sum, avCounter, total;
    sum, avCounter, total = 0;
    double averages[BIN_LENGTH];
    int divider = 8;
    
    Serial.print("FFT: ");
    for (i=0; i<64; i++) { // take the first 64 of 128 frequency bins and average 8 bins to get the 8 different frequency values
      total+= myFFT.output[i];
      Serial.print(myFFT.output[i]);
      Serial.print(" ");
      if(i % divider == 0){
        averages[avCounter] = total/divider;
        total = 0;
        avCounter++;
      }
    }
    Serial.println();

    update_audio(averages);
   
  }
}



void smpltimerisr(void){
  Serial.print("Count: ");
  Serial.println(count);
  count = 0;
}
 
***More edit. More commented. More optimising. Much more to go...... **

So ive got some code working a tad. Now to map it and tune it and see if I can actually make this happen 0.o

Edit: Shifted pattern being called from audio update to end of main loop.

Calling it from audio update results in smoother fades, but calling from end of main loop results in faster patterns, since audio only updates when availiable. The best inbetween would probably be taking less fft samples....

Next stage is to see if it works with multiple strands and get it all mapped out.... (three rings plus three sculptures with ~40 pixels placed on each)

Code:
/*
 // Combining the PJRC audio library http://www.pjrc.com/teensy/td_libs_Audio.html and 
  fastLED libraries https://github.com/FastLED/FastLED 
  as well as some code from Owen. 
  
  
*/


#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <FastLED.h>


#define LED_COUNT 393
#define BIN_LENGTH 7   // 8 averages for frequency range
#define DATA_PIN 2
#define CLK_PIN 4


//-------------- Standard audio stuff ----------------------------------------------

const int myInput = AUDIO_INPUT_LINEIN;


AudioInputI2S       audioInput;         // audio shield: mic or line-in
AudioAnalyzeFFT256  myFFT(20);          //Number of FFT reads per analysis?
AudioOutputI2S      audioOutput;        // audio shield: headphones & line-out


AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFFT, 0);
AudioConnection c3(audioInput, 1, audioOutput, 1);


AudioControlSGTL5000 audioShield;

//--------------LED array structuring------------------------------------------------

struct CRGB leds[LED_COUNT];

int ledsX[LED_COUNT][3];     //-ARRAY FOR COPYING WHATS IN THE LED STRIP CURRENTLY (FOR CELL-AUTOMATA, MARCH, ETC)



//-------------Funkboxing attributes-------------------------------------------------

int BOTTOM_INDEX = 0;
int TOP_INDEX = int(LED_COUNT/2);
int EVENODD = LED_COUNT%2;

//---LED FX VARS
int idex = 0;                //-LED INDEX (0 to LED_COUNT-1
int ihue = 0;                //-HUE (0-255)
int ibright = 0;             //-BRIGHTNESS (0-255)
int isat = 0;                //-SATURATION (0-255)
int bouncedirection = 0;     //-SWITCH FOR COLOR BOUNCE (0-1)
float tcount = 0.0;          //-INC VAR FOR SIN LOOPS
int lcount = 0;              //-ANOTHER COUNTING VAR

int thisdelay = 20;          //-FX LOOPS DELAY VAR
int thisstep = 10;           //-FX LOOPS DELAY VAR
int thishue = 0;             //-FX LOOPS DELAY VAR
int thissat = 255;           //-FX LOOPS DELAY VAR

//--------------fcknaround attributes-------------------------------------

int hue;
int hueCounter;

int modeZero;
int modeOne;

int hueCalc;


//--------------Owens Audio attributes--------------------------------------

double MAX_SIZE = 200.0;   // Max range of averaged freq bands
int max_bright = 255;
int count = 0;             // No of fft rounds analysed yeah?

//int c = 0;         //not needed?
//int audio = 0;     //not needed?
int iterations = 10000;
const int half = 1;

int ampRounding = 64;   // Rounds the 8 freq bands to 0 - 64

unsigned long time; 

IntervalTimer smpltimer;

/* -------------------------------------------- Effects ------------------------------------------------ 

/*------------------------------------#
#----- FASTSPI2 EFFECTS EXAMPLES -----#
#-------------- v0.51 ----------------#
#------------ teldredge --------------#
#-------- www.funkboxing.com ---------#
#------ teldredge1979@gmail.com ------#
#-------------------------------------#


*/


void ems_lightsONE() {                    //Multiple Cylon's
                                          //Two points (antiPodal) getting dimmer on either side spinning around.
  
  idex++;
  
  if (idex >= LED_COUNT) {idex = 0;}
  
  int idexR = idex;
  
  int idexB = antipodal_index(idexR);
  
  int iL1 = adjacent_cw(idexR);
  int iL2 = adjacent_cw(iL1);
  int iL3 = adjacent_cw(iL2);
  int iL4 = adjacent_cw(iL3);
  int iL5 = adjacent_cw(iL4);
  
  int iR1 = adjacent_ccw(idexR);
  int iR2 = adjacent_ccw(iR1);
  int iR3 = adjacent_ccw(iR2);
  int iR4 = adjacent_ccw(iR3);
  int iR5 = adjacent_ccw(iR4);
  
  int iL1AP = adjacent_cw(idexB);
  int iL2AP = adjacent_cw(iL1AP);
  int iL3AP = adjacent_cw(iL2AP);
  int iL4AP = adjacent_cw(iL3AP);
  int iL5AP = adjacent_cw(iL4AP);
  
  int iR1AP = adjacent_ccw(idexB);
  int iR2AP = adjacent_ccw(iR1AP);
  int iR3AP = adjacent_ccw(iR2AP);
  int iR4AP = adjacent_ccw(iR3AP);
  int iR5AP = adjacent_ccw(iR4AP);

  for(int i = 0; i < LED_COUNT; i++ ) {
    if (i == idexR) {leds[i] = CHSV(hue, thissat, 255);}
    else if (i == idexB) {leds[i] = CHSV(hue, thissat, 255);}
    else if (i == iL1) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iL2) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iL3) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iL4) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iL5) {leds[i] = CHSV(hue, thissat, 20);}     
 
 
 
 
    
    else if (i == iR1) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iR2) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iR3) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iR4) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iR5) {leds[i] = CHSV(hue, thissat, 20);}  
    
    
    
    else if (i == iL1AP) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iL2AP) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iL3AP) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iL4AP) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iL5AP) {leds[i] = CHSV(hue, thissat, 20);}     
 
 
 
 
    
    else if (i == iR1AP) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iR2AP) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iR3AP) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iR4AP) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iR5AP) {leds[i] = CHSV(hue, thissat, 20);}  
    else {leds[i] = CHSV(0, 0, 0);}
  }
  
  
  LEDS.show();  

}

//----------------------------------------------------------------------------------

void color_bounceFADE() {  //Single Cylon Bounce



  if (bouncedirection == 0) {
    idex = idex + 1;
    if (idex == LED_COUNT) {
      bouncedirection = 1;
      idex = idex - 1;
    }
  }
  if (bouncedirection == 1) {
    idex = idex - 1;
    if (idex == 0) {
      bouncedirection = 0;
    }
  }
  int iL1 = adjacent_cw(idex);
  int iL2 = adjacent_cw(iL1);
  int iL3 = adjacent_cw(iL2);
  int iL4 = adjacent_cw(iL3);
  int iL5 = adjacent_cw(iL4);
  
  // Arrays be easier yeah?
  
  int iR1 = adjacent_ccw(idex);
  int iR2 = adjacent_ccw(iR1);
  int iR3 = adjacent_ccw(iR2);
  int iR4 = adjacent_ccw(iR3);
  int iR5 = adjacent_ccw(iR4);
  
  
  
  
  for(int i = 0; i < LED_COUNT; i++ ) {
    if (i == idex) {leds[i] = CHSV(hue, thissat, 255);}
    
    
    else if (i == iL1) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iL2) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iL3) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iL4) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iL5) {leds[i] = CHSV(hue, thissat, 20);}     
 
 
 
 
    
    else if (i == iR1) {leds[i] = CHSV(hue, thissat, 150);}
    else if (i == iR2) {leds[i] = CHSV(hue, thissat, 110);}
    else if (i == iR3) {leds[i] = CHSV(hue, thissat, 80);}
    else if (i == iR4) {leds[i] = CHSV(hue, thissat, 50);}
    else if (i == iR5) {leds[i] = CHSV(hue, thissat, 20);}    
    else {leds[i] = CHSV(0, 0, 0);}
  }
  LEDS.show();
//  delay(thisdelay);
}


//-----------------Funkboxing--- UTILITY FXNS --------------------------------------
//
//
//---SET THE COLOR OF A SINGLE RGB LED
void set_color_led(int adex, int cred, int cgrn, int cblu) {  
  leds[adex].setRGB( cred, cgrn, cblu);
} 

//---FIND INDEX OF HORIZONAL OPPOSITE LED
int horizontal_index(int i) {
  //-ONLY WORKS WITH INDEX < TOPINDEX
  if (i == BOTTOM_INDEX) {return BOTTOM_INDEX;}
  if (i == TOP_INDEX && EVENODD == 1) {return TOP_INDEX + 1;}
  if (i == TOP_INDEX && EVENODD == 0) {return TOP_INDEX;}
  return LED_COUNT - i;  
}

//---FIND INDEX OF ANTIPODAL OPPOSITE LED
int antipodal_index(int i) {
  int iN = i + TOP_INDEX;
  if (i >= TOP_INDEX) {iN = ( i + TOP_INDEX ) % LED_COUNT; }
  return iN;
}

//---FIND ADJACENT INDEX CLOCKWISE
int adjacent_cw(int i) {
  int r;
  if (i < LED_COUNT - 1) {r = i + 1;}
  else {r = 0;}
  return r;
}

//---FIND ADJACENT INDEX COUNTER-CLOCKWISE
int adjacent_ccw(int i) {
  int r;
  if (i > 0) {r = i - 1;}
  else {r = LED_COUNT - 1;}
  return r;
}

//copys led array...
void copy_led_array(){
  for(int i = 0; i < LED_COUNT; i++ ) {
    ledsX[i][0] = leds[i].r;
    ledsX[i][1] = leds[i].g;
    ledsX[i][2] = leds[i].b;
  }  
}



//--------------------Owens Utility Functions------------------------------
//


//Creates an upper bound for the amplitute and scales bands differently
// multiplies rest by four.
int scale_doof(double val, int f_band){

  if(f_band > 1) {                               //keeps bands 0, 1 as they are (Bass dominates)
    val = val*4;
  }
  if (val > MAX_SIZE) {                         //Scales value to a maximum
     val = MAX_SIZE;
  }
  return (val/MAX_SIZE)*ampRounding;            //Rounds values to 64
}


//Turns em all off
void zero_leds(void) {
  int i;
  for(i = 0; i < LED_COUNT; i++) {
    leds[i].setRGB(0,0,0);
  } 
}




//----Work in progress. converts scaled freq bands to hue modifiers
//
int set_doof(int scale, int mode, int f_band) {

 if (mode == 0) {

 Serial.print("modeZero:    ");
 Serial.println(modeZero);
   
 modeZero+= scale;
 

 }
 
else if (mode == 1) {
  modeOne+= scale;
  
//  Serial.print("modeOne:    ");
// Serial.println(modeOne);
   
  
}
  
  /*DEBUGGGG
   Serial.print("-------");
  Serial.print("Scale: ");
  Serial.println(scale);
  Serial.println("-------");
  

  
 Serial.print("mode: ");
  Serial.println(mode);
  Serial.println("-------");

  
 Serial.print("f_band: ");
  Serial.println(f_band);
  Serial.println("-------");
  }

  
*///


/* ------------------ Hue Fader ----------------

  if (hue > 54) 
  {hueCounter = 1;} 
  if (hue < 10)
  {hueCounter = 0;}
   
   
    
  if(hueCounter == 0)
  {hue++;}
  if(hueCounter ==1)
  {hue--;}
  
  ---------------------------------------------------*/


}

//--------------------------
//Main function. Uses above to convert to hue modifiers and then displays pretty lights
//--------------------------

void update_audio(double fft[]) {

  int i, j, scaled;
  
  int mode = 0;                        
  
  for(i = 0; i < BIN_LENGTH; i++) {
    scaled = scale_doof(fft[i], i);
    if(i > 3){
      mode = 1;
    }
    set_doof(scaled, mode, i);
  }

   count++;
 
   hue = hueCalc;

//  LEDS.show();

  
//  zero_leds();

}





void setup() {

  
  //--Audio Setup -----
  AudioMemory(12);
  audioShield.enable();
  audioShield.inputSelect(myInput);
  audioShield.volume(1.5);
  Serial.begin(115200);
  
  
  //--Timer Setup ------
  smpltimer.begin(smpltimerisr, 1000000); //seconds = Value/1000000


  //--LED Setup ----------
  LEDS.setBrightness(max_bright);
  LEDS.addLeds<NEOPIXEL,DATA_PIN>(leds, LED_COUNT);    //Change to multistrip style. 

  
}



void loop() {
  

  

  if (myFFT.available()) {
    // each time new FFT data is available
    // print it all to the Arduino Serial Monitor
    
    Serial.println(count);
    
    int i, sum, avCounter, total;
    sum, avCounter, total = 0;
    double averages[BIN_LENGTH]; // array of 8 freq bands
    int divider = 8;
    
    Serial.print("FFT: ");
    for (i=0; i<64; i++) { // take the first 64 of 128 frequency bins and average 8 bins to get the 8 different frequency values
      total+= myFFT.output[i];
      Serial.print(myFFT.output[i]);
      Serial.print(" ");
      if(i % divider == 0){
        averages[avCounter] = total/divider;
        total = 0;
        avCounter++;
      }
    }
    update_audio(averages);
    
    // Serial.print("Zero:Final    ");
    // Serial.println(modeZero);
     
     hueCalc = modeZero - modeOne;
     
//     Serial.print("hueCalc:  ");
//     Serial.println(hueCalc);

  }
  

  ems_lightsONE();

  
  //Resets 
  modeZero = 0;
  modeOne = 0;
}



void smpltimerisr(void){
  Serial.print("Count: ");
  Serial.println(count);
  count = 0;
}
 
Last edited:
Thanks for the code. My LED layout is weird so I couldn't use your code directly but I was able to use most of it.

Like you and some others I have problems with OctoWS2811 and the audio adapter together. I got the libraries to work but I there's occasionally random flickers of random colors, I'll try to post a video later.

My particular project requires OctoWS2811 so I'm going to keep working with that library instead of switching to FastLED, but I look forward to seeing more about your implementation.
 
Hi Flinch,

Thanks for posting this. Question - are you processing the FFT on the stereo input or just mono? I'm looking to take the stereo line input and process each individually, but I noticed this on the Audio Library page:
"The beta test Audio Library has a known bug limiting AudioAnalyzeFFT256 to only a single instance. Future versions will correct this issue, allowing you to have multiple AudioAnalyzeFFT256 objects, each analyzing a different audio source. "

Any help is much appreciated. Thanks!
 
Hi

Not fully on top of the Octows2811 but having just checked the pins used I think you can use that board plus the audio board at the same time with caveats. What you can't do is use is both boards plus the relevant high speed 8 channel library, since it is using the Audio volume control input 15 for a clock function (which also means you can't use pin 16 since it's shorted to 15 by the OctoBoard) There are also conflicts with a Octo channels 2 and 3 on pins 7 and 14 being used for the SD card/flash memory and channel 8 on pin 5 is also the SD card chip select.

So the original posters SPI implementation will work, just be aware of the conflicting pins and the fact that octo channel 2 and 3 are connected by a bi directional level converter, so connections made out on the Cat 6 cable for those channels will impact the SD card function, and not fitting the optional volume control pot would seem wise given the pin 15/16 short loop.

For PotatoTron who is using the Octo library some interesting potential fixes are possible but not necessarily 'fun', involving moving the clashing pins apart in hardware and changing the relevant library to suit.

I would defer to someone who has a better grasp on the DMA magic used for the 8 channel driver but I think the simple/ugly method is:
Not fit the volume control (and if possible comment out relevant code polling it as an input)
Only use the Mic in rather than WAV from memory, and if possible comment out calls for SD card (and the currently unused W25Q128 EEPROM)

If these options are not possible then it's time to break out the soldering iron and move tracks around, which will be a complex balance of easy of access to the physical board track vs ease of code change (single DEFN change in the header vs search and replace through a library).

I hope this partial answer helps.
 
Cheers for the details GremlinWrangler =)

The project worked fine, I used only a single channel in through the line in pins. All 393 pixels were wired as a single strand in the end, my other fixtures were located further than though so were run off a seperate controller. Due to weather had to send signal AND power over a ~20m length of wire..... (for ~400 pixels) AND had a motor running from sample power supply. The motor caused glitching that I solved by using resistors to slow it and some caps, and sending the power over the length was fine since the colour theme was red/orange.

Currently working on some unrelated projects but look forward to developing this further at another point, especially getting my head around the DMA stuff....
 
Status
Not open for further replies.
Back
Top