Connecting to external board for additional memory

Status
Not open for further replies.

dfeoktis

Member
I'm doing a project driving a large amount (144) LEDs using Adafruit's NeoPixel library with FFT data and the wanted to use an external ATMega 2560-based board to drive them (there's enough memory on the 2560 to drive the project where the Teensy seems to have some trouble and it has 5V power). It seems to miscommunicate with the LED strip in the same configuration once I use the FFT function--it displays "copies" of the strip object another across the LED strip (for example, if I set the strip to be 3 pixels, the LED strip will display around 10 copies the same three-pixel pattern with synced time-dependent behavior right next to one another and three white pixels at the end). In projects without the FFT (i.e. Adafruit's strandtest), it handles a reasonable number of pixels just fine without the copying issue.

The strange thing is that when I use a different LED strip with fewer LEDs per inch, the same code works just like it's supposed to and doesn't do that odd repetition of the data on the strip. That strip is powered completely by the Teensy, though, and this one has external 5V power (and is also grounded to the 3.3V Teensy).

I feel that using an external board with 5V logic and more memory to drive the LEDs would solve the issue, but I may be wrong.

Is it possible to use a 3.3V Teensy and a 5V Arduino in a slave/master configuration, where I'd send the important numbers from Teensy's FFT to the Arduino Mega and send data to the strip from the latter? Any advice on how I could connect them?

Source code below:

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Adafruit_NeoPixel.h>

#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
#define LEDPin 8

AudioPlaySdWav wavPlayer;
AudioAnalyzeFFT1024 myFFT;
AudioAnalyzePeak peak;
AudioMixer4 mixer;
AudioOutputI2S audioOutput;
AudioConnection patchCord1(wavPlayer, 0, mixer, 0);
AudioConnection patchCord2(wavPlayer, 0, audioOutput, 0);
AudioConnection patchCord3(wavPlayer, 1, mixer, 1);
AudioConnection patchCord4(wavPlayer, 1, audioOutput, 1);
AudioConnection patchCord5(mixer, peak);
AudioConnection patchCord6(mixer, myFFT);
AudioControlSGTL5000 sgtl5000_1;

boolean isPlaying = false;
float currentPeak = 0.0;
float frequencyBands[3];
int numPeaks = 2;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPeaks, LEDPin, NEO_GRB + NEO_KHZ800);

void setup() {
AudioMemory(12);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);

SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}

strip.begin();
strip.show();
}

void playFile(char *filename){
Serial.print("Playing file: ");
Serial.println(filename);
wavPlayer.play(filename);
}

elapsedMillis rms;
elapsedMillis fps;

void checkAudio(){
if(rms > 30){
if(peak.available()){
rms=0;
currentPeak = peak.read();
}
}
if(myFFT.available()){
frequencyBands[0] = myFFT.read(0, 10)*255;
frequencyBands[1] = myFFT.read(6, 32)*180;
frequencyBands[2] = myFFT.read(16, 360)*20;
}
int rOut = (int) frequencyBands[0];
rOut = min(rOut, 255);
int gOut = (int) frequencyBands[1];
gOut = min(gOut, 255);
int bOut = (int) frequencyBands[2];
bOut = min(bOut, 255);
pushToLEDs(currentPeak, strip.Color(rOut,gOut,bOut));
}

void pushToLEDs(float currentPeak, uint32_t color){
int numberOfLEDs = (int) (currentPeak*(strip.numPixels()+.1));
for(int i=0; i<strip.numPixels(); i++){
strip.setPixelColor(i, color);
if(i>=numberOfLEDs){
strip.setPixelColor(i, strip.Color(0,0,0));
}
strip.show();
}
}

void loop() {
if(!isPlaying){
delay(1000);
playFile("MOON.wav");
isPlaying = true;
}
checkAudio();
}
 
All the Teensy's should be happy driving 144 LEDs and the audio library FFT given the octoWS2811 spectrum analyser example code uses nearly 2000, the problem is almost certainly the interaction of the audio library and it's need to interrupt to keep running and the critical timing of the self clocking LED strip waveform as produced by the basic adafruit library. Blocking interrupts while updating LEDs works to get the LEDs running, but that will start introducing audio glitches with each update if the number of pixels is high (previous posts seemed to be about 30, but haven't relocated them though).

If you want both functions to work you need to find some way to stop the audio and LED functions from interupting each other. The simple solution if blocking interrupts has side effects would be two separate devices sharing the time critical stuff as you discuss but in terms of raw processing power a Teensy has enough CPU cycles and supporting hardware to do the job with enough clever code, see the above mentioned OctoWS example code driving 2k LEDs. What I haven't seen is anything you can just pick up and use for your planned design with a single LED strand so would probably involve an adventure into low level code and hardware. If design is still flexible the current normal route for LEDs+audio is to follow the prop shield in using SPI LEDs since they are more forgiving about minor deviations in time due to the separate clock line
 
All the Teensy's should be happy driving 144 LEDs and the audio library FFT given the octoWS2811 spectrum analyser example code uses nearly 2000, the problem is almost certainly the interaction of the audio library and it's need to interrupt to keep running and the critical timing of the self clocking LED strip waveform as produced by the basic adafruit library. Blocking interrupts while updating LEDs works to get the LEDs running, but that will start introducing audio glitches with each update if the number of pixels is high (previous posts seemed to be about 30, but haven't relocated them though).

If you want both functions to work you need to find some way to stop the audio and LED functions from interupting each other. The simple solution if blocking interrupts has side effects would be two separate devices sharing the time critical stuff as you discuss but in terms of raw processing power a Teensy has enough CPU cycles and supporting hardware to do the job with enough clever code, see the above mentioned OctoWS example code driving 2k LEDs. What I haven't seen is anything you can just pick up and use for your planned design with a single LED strand so would probably involve an adventure into low level code and hardware. If design is still flexible the current normal route for LEDs+audio is to follow the prop shield in using SPI LEDs since they are more forgiving about minor deviations in time due to the separate clock line

Thanks for the advice! I'll definitely look into getting an OctoWS adapter. Is it possible to stack it with a teensy audio adapter, and in either case how would you recommend setting up two devices to communicate (if not over I2S)?
 
It is possible to use the Octo library and the audio shield, but it requires shuffling pins around conflicts so they don't stack straight up and you have to change the default code in the libraries to reflect. So it's not a magic bullet for your problem. In terms of communication the easy option is probably to stream between the hardware serial ports if you are just using the audio board to dump pixel data or fft info into another board. A more robust and possible faster approach might be SPI but you aren't really moving enough data to chase down that rabbit whole unless they happen to be the pins you have free. I2S will require level conversion due to the way pullups work on the shared bus. In terms of moving data easy enough to just dump bytes across with a timeout to catch misses, or you can get more sophisticated with start and stop blocks, or go looking at libraries http://www.billporter.info/2011/05/30/easytransfer-arduino-library/
 
Ok, it seems hardware serial would be a good solution here--would I need a 74HCT245 (or similar level shifter IC) for that serial communication (I've only got one Teensy at the moment so it'd have to be with an Arduino Mega) or would I be fine just wiring up the RX/TX pins?
 
The mega can probably read 3.3V as high, but will be marginal and may hit issues at high data rates as the slew rate becomes more of an influence. Going the other way the Teensy3.2 can handle 5V but the belt and braces answer puts a voltage divider in there.
 
Status
Not open for further replies.
Back
Top