Teensy 3.2 crashes when playing audio from Prop Shield flash and running FastLED

Status
Not open for further replies.

jseg

Member
Hello everyone,

I'm hoping you all can help me with a problem I've been struggling with for the past couple of days. I'm trying to play a series of RAW files from the flash memory of the Prop Shield while driving a string of DOTSTAR LEDs. The code runs long enough for the first audio clip to play (.3s) and then hangs. While the audio is playing, the LEDs animate fine; then as it switches to the next file teensy hangs and windows makes a sound like Teensy has been unplugged. I read this thread on github, FastLED Issues 339 , and saw that the fix suggested there was being distributed with Teensyduino 1.30, so I took the opportunity to upgrade. It didn't affect the behavior. In the code below, if I comment out all of the lines associated with FastLED, the audio works correctly--and vice versa. I'm not sure what I'm missing--it seems like a problem with the SPI transaction, but I've gone as far as I can go. Any ideas? Thanks.

Here is my set up:

Arduino 1.6.11 and Teensyduino 1.30
FastLED v. 3.001.001

Teensy 3.2
Propshield LC w/ a speaker and
144 Dotstar Leds

Code:
// Converted from the WavFilePlay from the Teensy release:
// hardware/teensy/avr/libraries/Audio/examples/WavFilePlayer/WavFilePlayer.ino
//
// Simple RAW file player example for the prop shield to use the Analog DAC
// and prop shield amplifier to play mono sounds.
// http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog
//
// On the prop shield, pin 6 selects the serial flash memory controller,
// and pin 5 enables the amplifier.
//
//Added code to test usage with FASTLED
//
// This example code is in the public domain.
//
//#define FASTLED_ALLOW_INTERRUPTS 0
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <FastLED.h>

//// GUItool: begin automatically generated code
AudioPlaySerialflashRaw playFlashRaw1; //xy=149,388
AudioMixer4 mixer1; //xy=445,386
AudioOutputAnalog dac1; //xy=591,379
AudioConnection patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection patchCord2(mixer1, dac1);
//// GUItool: end automatically generated code

//Audio Definitions
#define PROP_AMP_ENABLE  5
#define FLASH_CHIP_SELECT 6
#define VOLUME_POT  A1

//LED Definitions
#define NUM_LEDS 144
#define DATA_PIN 11
#define CLOCK_PIN 13
#define FRAMERATE 300


//LED OBJECT and supporting variables
CRGB leds[NUM_LEDS];
const int ledDelay = (1000/FRAMERATE);
elapsedMillis frame = 0;
uint8_t gHue = 0; // rotating "base color" used by many of the patterns (from DemoReel100 example)

void setup() {
Serial.begin(9600);

// wait up to 3 seconds for the Serial device to become available
long unsigned debug_start = millis ();
while (!Serial && ((millis () - debug_start) <= 3000))
;

//Setup of LEDS
 pinMode(7,OUTPUT); //LED ENABLE
 digitalWrite(7,LOW);
 FastLED.addLeds<DOTSTAR, DATA_PIN, CLOCK_PIN, RGB,DATA_RATE_MHZ(12)>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
 LEDS.setBrightness(200);
 delay(10); 

Serial.println ("Start prop shield RAW player");

// Enable the amplifier on the prop shield
dac1.analogReference(EXTERNAL); // much louder!
pinMode(PROP_AMP_ENABLE, OUTPUT);
digitalWrite(PROP_AMP_ENABLE, HIGH);

// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(60);

// Set initial volume
 mixer1.gain(0, 1.0f);

// uncomment these lines if you have a potentiometer or trimpot
// on the pin A1 to control the volume, and comment out the
// above line
//float vol = analogRead(VOLUME_POT);
//mixer1.gain(0, vol / 1024.0f);

// Start SerialFlash
if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
  while (1)
  {
  Serial.println ("Cannot access SPI Flash chip");
  delay (1000);
  } 
  }

}

int filenumber = 0;  // while file to play

const char * filelist[7] = {
  "s1.raw", "s2.raw", "s3.raw", "c1.raw", "m1.raw", "s4.raw", "b1.raw"
};

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

// Start playing the file. This sketch continues to
// run while the file plays.
playFlashRaw1.play(filename);

// A brief delay for the library read RAW info
delay(5);

// Simply wait for the file to finish playing.
while (playFlashRaw1.isPlaying()) {
// uncomment these lines if you have a potentiometer or trimpot
// on the pin A1 to control the volume
//float vol = analogRead(VOLUME_POT);
//mixer1.gain(0, vol / 1024.0f);
}
}

void playFromArray() {
  if (!playFlashRaw1.isPlaying()) {
    const char *filename = filelist[filenumber];
    filenumber = filenumber + 1;
    if (filenumber >= 7) filenumber = 0;
    Serial.print("Start playing ");
    Serial.println(filename);
    playFlashRaw1.play(filename);
    delay(30); // wait for library to parse WAV info
  }
}

void ledUpdate(){
    // beginTransaction prevents SPI bus conflicts
    SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
    digitalWrite(7, HIGH);  // enable access to LEDs
    FastLED.show();
    digitalWrite(7, LOW);
    //delayMicroseconds(5);
    SPI.endTransaction();   // allow other libs to use SPI again
}

void sinelon()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(50,0,NUM_LEDS);
  leds[pos] += CHSV( 96, 255, 192);
  ledUpdate();
 }


void loop() {
  playFromArray();
  if ( frame > ledDelay){
    frame = 0;
    sinelon();
  }
}
 
There is another thread on this topic here. It suggests the following solutions:

  • Reduce the SPI frequency (tried 24, 12, and 10Mhz)
  • Toggle a #define related to interrupts (tried FASTLED_ALLOW_INTERRUPTS 0)
  • Post #4 suggests stopping the audio and replaying after updating LEDS (this didn't work and I think play() restarts the file anyway.
  • Increase audio memory (tried values ranging from 8 to 60).
  • Revert to FastLED 3.0.3 (haven't tried because the solution referenced WS2812s

Despite trying these suggestions, I haven't had any luck yet. I did try one other thing which was to remove the SPI transaction altogether and toggle the CS pins manually like so:

Code:
void ledUpdate(){
    // beginTransaction prevents SPI bus conflicts
    //SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);  // enable access to LEDs
    FastLED.show();
    digitalWrite(7, LOW);
    digitalWrite(6, HIGH);
    //delayMicroseconds(5);
    //SPI.endTransaction();   // allow other libs to use SPI again
}

In that case, the LEDs went nuts, but the audio played a bit longer before freezing. That makes me wonder if the issue isn't related to APA102, FastLED, Teensyduino 1.29, Teensy 3.2 - Hanging after random number of shows. However, I'm using Teensyduino 1.30 which includes the accepted fix.

Lastly, I'm wondering if anybody has a working example utilizing all three features of the Prop Shield LC (memory, spi leds, and audio). I haven't been able find a complete example or even a completed project that proves a working configuration. Without an example, I'm not sure if there really is a bug, or if I'm just doing it wrong. I've been know to do it wrong. :)

Thanks everyone.
 
Did you scan the prop beta thread for samples, can't say for sure, but seeems that there may be one

<edit> I just did and audio with fastled wasn't a combo I came across.
 
Last edited:
Thanks for the reply. I did do a cursory look through that thread, and didn't see anything. This morning I read the entire thread carefully and it looks like SerialFlash and FastLED were tested individually, but not as a pair. I suspect that this is an SPI issue with either SerialFlash or FastLED, because there are examples of Audio itself playing nice with multiple SPI devices (the TFT example in Audio's tutorials, for instance). I would like to test FastLED and SerialFlash against other SPI devices but the APA102s and the flash chip are all I have handy.

After reading https://github.com/FastLED/FastLED/pull/343, I tried running the code above, with FastLED 3.1.0 as suggested. No dice.
 
I tried using Adafruit's DotStar library instead. It works fine. Still no idea whats wrong with FastLED. Here is a working example that plays RAW files stored on the Prop Shield flash memory and updates DotStars/APA102s:

Code:
// Mashup example of Adafruit's DotStar library running along side SerialFlash
// and the Audio Libray--all three features of the Prop Shield LC working together.

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


////// GUItool: begin automatically generated code
AudioPlaySerialflashRaw playFlashRaw1; //xy=149,388
AudioMixer4 mixer1; //xy=445,386
AudioOutputAnalog dac1; //xy=591,379
AudioConnection patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection patchCord2(mixer1, dac1);
////// GUItool: end automatically generated code

//Audio Definitions
#define PROP_AMP_ENABLE  5
#define FLASH_CHIP_SELECT 6

//LED Definitions
#define NUMPIXELS 144 // Number of LEDs in strip
#define LED_ENABLE 7
Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DOTSTAR_BRG);

//Timing
elapsedMillis frame = 0;
elapsedMillis sound = 0;

void setup() {
Serial.begin(9600);
// wait up to 3 seconds for the Serial device to become available
long unsigned debug_start = millis ();
while (!Serial && ((millis () - debug_start) <= 3000));
pinMode(LED_ENABLE,OUTPUT); //Set up access to LEDS
digitalWrite(LED_ENABLE,LOW); //Turn off LEDs
strip.begin(); // Initialize pins for output
strip.show();  // Turn all LEDs off ASAP

//Initialize audio stuff
dac1.analogReference(EXTERNAL); // much louder!
pinMode(PROP_AMP_ENABLE, OUTPUT); //Turn on Prop Shield Amp
digitalWrite(PROP_AMP_ENABLE, HIGH);
AudioMemory(12);
mixer1.gain(0, 1.0f);
  if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
    while (1)
    {
      Serial.println ("Cannot access SPI Flash chip");
      delay (1000);
    } 
  }
}

// Runs 10 LEDs at a time along strip, cycling through red, green and blue.
// This requires about 200 mA for all the 'on' pixels + 1 mA per 'off' pixel.

int      head  = 0, tail = -10; // Index of first 'on' and 'off' pixels
uint32_t color = 0xFF0000;      // 'On' color (starts red)

//Upload your own files with TeensyTransfer: https://github.com/FrankBoesing/TeensyTransfer
const char * filelist[7] = {  
  "b1.raw", "s2.raw", "s3.raw", "c1.raw", "m1.raw", "s4.raw", "s1.raw"
};

void playFromArray() {
  if (playFlashRaw1.isPlaying() == false) {
    static int filenumber = 0;
    static const char *filename = filelist[filenumber];
    filename = filelist[filenumber];
    filenumber = filenumber + 1;
    if (filenumber >= 7) {filenumber = 0;}
    Serial.print("Start playing ");
    Serial.println(filename);
    playFlashRaw1.play(filename);
    delay(5); // wait for library to parse WAV info
   }
}

void loop() {
if (sound > 2000){ 
  sound = sound - 2000; 
  playFromArray();
}
if (frame > 10){// Pause 10 milliseconds (~100 FPS)
    frame = frame - 10;
    
    //This code comes from the strand test example in the DotStar lib
    strip.setPixelColor(head, color); // 'On' pixel at head
    strip.setPixelColor(tail, 0);     // 'Off' pixel at tail
    
    if(++head >= NUMPIXELS) {         // Increment head index.  Off end of strip?
      head = 0;                       //  Yes, reset head index to start
      if((color >>= 8) == 0)          //  Next color (R->G->B) ... past blue now?
        color = 0xFF0000;             //   Yes, reset to red
    }
    if(++tail >= NUMPIXELS) tail = 0; // Increment, reset tail index
    
    //SPI Transaction
    SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
    digitalWrite(LED_ENABLE, HIGH);  // enable access to LEDs
    strip.show();                     // Refresh strip
    digitalWrite(LED_ENABLE, LOW);
    SPI.endTransaction();   // allow other libs to use SPI again
  }
}

I'd still like to use FastLED, but I think I'm going to use Adafruit's lib for the time being.
 
Good follow-up jseg. I never worked with that - though my work with FastLed on another thread is finding oddness - but that is when trying to run SPI faster than the 10 MHz used here: SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));

I wonder what you see if you bump the 10000000 to 24000000? It may be that FastLed on your system is running at a bad speed?
 
I'm bummed about FastLED. I already invested time reading the documentation and making my animations before I tried adding sound on the Prop Shield. So, I'm not thrilled about switching to Adafruit's library. However, I'm at a loss with FastLED. I looked under the hood of both libraries SPI handling, and Adafruit's is much simpler by comparison--its mostly using SPI.h to handle the configuration. On the other hand FastLED is directly manipulating the ports. The details of how all that works are above my pay grade, but I suspect FastLED would work better if it took adafruits approach to interfacing with the hardware. Just a guess--I don't really know anything about the details of the hardware.

As for adjusting the clock rate, with Adafruits lib it works at 24, with FastLED it does not, nor at 12. I haven't tried anything less than 10.

Regards,

John
 
Last edited:
I am too. I just ran into this issue with several projects. I dont think I will be using FastLED library anymore. It's nice, but doesnt work worth a crap. Adafruits library works no problem. I've tried WS2812 and APA102 strips and FastLED has issue after issue. Using APA102 and no sound comes out.


I'm bummed about FastLED. I already invested time reading the documentation and making my animations before I tried adding sound on the Prop Shield. So, I'm not thrilled about switching to Adafruit's library. However, I'm at a loss with FastLED. I looked under the hood of both libraries SPI handling, and Adafruit's is much simpler by comparison--its mostly using SPI.h to handle the configuration. On the other hand FastLED is directly manipulating the ports. The details of how all that works are above my pay grade, but I suspect FastLED would work better if it took adafruits approach to interfacing with the hardware. Just a guess--I don't really know anything about the details of the hardware.

As for adjusting the clock rate, with Adafruits lib it works at 24, with FastLED it does not, nor at 12. I haven't tried anything less than 10.

Regards,

John
 
Does it work if you surround your usage of Fast LED with SPI.beginTransaction() and SPI.endTransaction() ?

No, FastLED doesnt work period (w/ sound). I have two separate projects that have light and sound going off. And FastLED doesnt work right with WS2812 or APA102 strips.

Adafruit's library, on the other hand, works fine. Even with the APA102 strips using the SPI commands.

I've jettison using FastLED with the prop shield, too much trouble really.
 
Any further word on this? I've just hit this issue. Have done heaps of stuff with FastLED before, and really like a lot of the features. First time working with the prop shield and sound / lights and recreating all my patterns in the Adafruit library isn't super exciting :/
Prop shield is awesome btw! I've added an ESP01 + LiPo and running patterns via QLab -> OSC.
 
I think the reason FastLED does not work with SerialFlash is that FastLED uses its own SPI implementation, whereas SerialFlash and Adafruit’s led library both depend on the standard Arduino SPI library. For some reason FastLED does not handle transactions in a way that is compatible with the Arduino library running at the same time. At least that’s what I remember from when I looked at that last a year and half ago.
 
This really is a drag. I've built lots of LED projects with FastLED on arduinos and only looked into the Teensy to over come the memory limitations for the ardunios. I know Adafruit produces great products so I just I'll have to re-code all of the animations that I've built with FastLED. But honestly I don't get how the arduinos and can stuff that teensy's can't.
 
This really is a drag. I've built lots of LED projects with FastLED on arduinos and only looked into the Teensy to over come the memory limitations for the ardunios. I know Adafruit produces great products so I just I'll have to re-code all of the animations that I've built with FastLED. But honestly I don't get how the arduinos and can stuff that teensy's can't.

Is this related to a specific unique problem that could be addressed? Example with details? >> Forum Rule: Always post complete source code & details to reproduce any issue!

This is an older thread and based on other post - pjrc.com/threads/57579-Ghost-in-the-Machine - that used an Audio card - this thread relates to Prop Shield?
 
Is this related to a specific unique problem that could be addressed? Example with details? >> Forum Rule: Always post complete source code & details to reproduce any issue!

This is an older thread and based on other post - pjrc.com/threads/57579-Ghost-in-the-Machine - that used an Audio card - this thread relates to Prop Shield?


Here's the code I was working on last night.

Code:
#include "FastLED.h"

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN        23
#define LED_TYPE        WS2812B
#define COLOR_ORDER     RGB
#define NUM_LEDS        32
int BRIGHTNESS =        255;

int touchRead_Pin1 =    15;
int TouchData_1;
int TouchData_mapped;

CRGB leds[NUM_LEDS];


void setup() {
  Serial.begin(115200);

  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    //.setCorrection(TypicalLEDStrip) // cpt-city palettes have different color balance
    .setDither(BRIGHTNESS < 255);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  fill_solid( leds, NUM_LEDS, CRGB(250,0,0));

  
  

}

void loop() {
  TouchData_1 = touchRead(touchRead_Pin1);
  TouchData_mapped = map(touchRead(touchRead_Pin1), 3300, 7000, 0, 250);
  
  

   // Serial.print("Touch 1 = "); Serial.print(TouchData_1); Serial.print("    Touch Map = "); Serial.println(TouchData_mapped);

    if (TouchData_mapped < 120) {
        Serial.println("Not Touched"); 
    }      
    else if (TouchData_mapped > 180){
        Serial.println("    Touched"); 
    }
       

  BRIGHTNESS = TouchData_mapped; 
  FastLED.setBrightness(BRIGHTNESS);
  

  FastLED.show();
  FastLED.delay(20);
    

    //delay(100); 

}

What I was hoping this would do was to adjust the brightness to 250ish when touched but after a like a second the LEDs would just freak out, flicker out... I can upload video to youtube if needed. The Audio board for the last project is the PJRC audio board... https://www.pjrc.com/store/teensy3_audio.html

And forgive me for the inline code in the post. I don't use forums. I think this is the 3rd post I've even made. I did just download the latest FastLED library and will try that tonight. Not jumping here, but you will see I'm using touchRead and even printing to the monitor I could see the output freezing if I touched the input for more than a moment. I was thinking I would code around this will millis and only look at the pin like every 100 or 200 millis. But really, I don't need to do that with inputs on a Uno or Mega.

Thank you for replying. I'm so hoping that the teensy can free me from memory limits of the Mega.

Just added a video to youtube, https://youtu.be/vPu3U7cgiiY At about 15 seconds in you will see what's happening. When touched the brightness value goes up to around 250 so the LEDs should be on fairly bright and not blinking out. Thanks again.
 
Last edited:
Status
Not open for further replies.
Back
Top