Fastled issue on Teensy 3.6

Status
Not open for further replies.

renaud

Member
Hello,
I am trying to drive an rgb led strip (dotstar) with a teensy 3.6.

I can make it run with Adafruit_DotStar.h
Adafruit_DotStar strip=Adafruit_DotStar(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG);
It's too slow for my project.

With Fastled, it does not work :(
FastLED.addLeds<DOTSTAR, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);

I am using pin 2 for data and 3 for clock.

Any idea what is wrong?
Thx,
Renaud
 
Last edited:
try using FastLED.addLeds<DOTSTAR, RGB>(leds, NUM_LEDS);
which uses pin 11 (MOSI) for data, and pin 13 for CLK. these are the SPI pins and permits FastLED speed optimizations
 
If you're using pins 2 and 3, then FastLED is being forced into software SPI. No good for fast data rates.

According to the diagram, these are the hardware SPI pins:
Data (0, 7, 11, 28)
Clock (13, 20, 32)

I'd try one of these to be sure you're getting the performance you expect, before you try mixing an matching pins.
Channel 0: MOSI = 11 CLK = 13
Channel 1: MOSI = 0 CLK = 32

Just an FYI.. it tuns out you can mix-and-match some pins if you need to. On my project, I wanted to free up pin 13 for the onboard LED, but still needed a SCK pin.
Instead of the default (Data=11, CLK=13), FastLED allowed me to specify (Data=11, CLK=14), and keep the hardware SPI working just fine. Note also, I was unable to convince the Adafruit DotStar library to use this miss-matched pins pair in Hardware.
 
pin 14 is an alternate for SCK0 so is fine. The card that comes with the 3.6 shows it and other alternates.

I have a system setup with both MOSI0 on pin 11 & SCK0 on pin 14, and MOSI1 on pin 0 & SCK1 on pin 32 running without hitch.

Defines and variables.
Code:
#define numleds 288
#define DATA_PIN1 11
#define CLOCK_PIN1 14
#define DATA_PIN2 0
#define CLOCK_PIN2 32
CRGB leds[numleds];
Initialization code. Note, 2 different 144 LED long strings.
Code:
FastLED.addLeds<APA102, DATA_PIN1, CLOCK_PIN1, RGB, DATA_RATE_MHZ(8)>(leds, 0, numleds/2);
FastLED.addLeds<APA102, DATA_PIN2, CLOCK_PIN2, RGB, DATA_RATE_MHZ(4)>(leds, numleds/2, numleds/2);
How to show them.
Code:
FastLED.show();
 
Thank you, it works fine. Except sometimes last 5 led of the strip are blinking :(
Strip length=141.
I am using now DataPin=11, ClockPin=14
 
maybe you need to add another 5v supply toward the end of the strip

Could be that or the infamous APA102 timing issue that means longer strips have to be run at slower data rates. Just slow this down DATA_RATE_MHZ(8) until it works reliably.

I have a 20 Amp medical grade DC to DC converter with 12 AWG wires with plenty of bulk capacitance supplying my strips and I only get 8 and 4 MHz.
 
I have a 20 Amp medical grade DC to DC converter with 12 AWG wires with plenty of bulk capacitance supplying my strips and I only get 8 and 4 MHz.
I guess I should mention that from my 12 AWG supply wires, I have 100uF electrolytic capacitors and connections at the density of every 10 LEDs over to the +5V and ground on the strips on one prototype. It didn't allow me to clock data into my APA102 LED strips any faster. The only way I've found so far is to limit the length of the strips of leds. Power supply noise is also not an issue. I've looked at the power rails on my strips with an oscilloscope and there isn't any objectionable noise. On a 144 LED long strip with power only being supplied at one end, I was seeing near 0.5V ripple at the end, and the LEDs were still working. A low ESR electrolytic capacitor at the end tamed things down a lot. Connecting the power supply to both ends helped even more. I'm still experimenting to see what works good enough, and isn't a broadcast antenna.

I did find literature that says APA102 LEDs have a built in decoupling capacitor, so only bulk capacitance is needed.
 
This is the first I've heard of needing to go down to only 8 MHz for such a 288 long APA102 strip. It could be the LEDs, maybe you were unlucky and got a batch of APA102 worse than the norm. Or maybe something isn't quite right with has FastLED is using the SPI hardware on Teensy 3.6?

If you can post a short program, I'll run it here on a 3.6 and take a quick look at the signals with my scope. At the very least, we can see whether Teensy 3.6 really is giving you the clock speed you specified to FastLED.

Also, please use File > Prefs to turn on verbose info while compiling. Then you should see a message telling you the full path to the copy of FastLED. If you're not using the one that comes with Teensyduino, I'll need to know which one to get to reproduce the same result.
 
Code in this https://forum.pjrc.com/threads/53008-Lockups-with-FastLED-amp-TeensyThreads thread, but tied into issues with TeensyThreads library lockups. In my current development code I moved the show call into it's own thread and have nothing done in the main loop. It seams to be stable now, but my thread time slice is longer than the time needed to write the LED strings. I explicitly use calls to threads.yield() when a thread finishes it's current work to keep from wasting cpu cycles.

I just finished reconfiguring my T3.6 with APA102 LEDs strings. The one used for the above thread. I had wired my level translator with wires directly tied to the pins on the chip and one broke off. That's replaced with one on a protobard, and it's running fine with less bulk decoupling capacitors. The whole thing is now supported on a strip of aluminum with kapton tape wrapped around where the Teensy and drive electronics are. Oh, I should mention I use a TI SN74AHCT125 as a level translator. That logic series accepts 3.3 V logic levels in and then outputs 5 V logic levels when powered by 5 VDC. Enables are active low and tied to ground. My ancient 20MHz analog oscope can't seam to get a stable lock on the SPI clock signal. I was hoping to see how much change in the time between clock and data leading edges changes from the start of the string to the end. Also my APA102 chips don't like it when I probe the contacts between them with my probes set to 1X. It must attenuate the signal to much. Probing the AHCT125 chip outputs works. Probing between the APA102 chips with the probes set at 10X works.

I was wondering if the knockoff APA102s I have are just bad with their timing. I remember running 32 MHz with some APA102 strings sourced from Adafruit, iPixel is their supplier, but that was all done on Raspberry Pi systems.

I put the scope on my setup again. It's only a >25 year old 20MHz analog scope and when I had the string MHz set to 4 or 8 I couldn't get a trigger lock on it. Set the MHz down to 1, and I'm now getting a lock. 0.225 us per clock cycle. It's in the uncalibrated part of the scope's range, but each clock cycle only takes a bit more than one 0.2us division on the screen to complete. 0.2 and 0.5 us per division ranges on the scope are uncalibrated.

Code to follow in my next post, but it was quickly hacked from the code linked to at the top. Thread code deleted. I changed my LED string to 20*numleds long, and have it outputting for half that length on the second string. All pixel values were set in setup and don't change.
 
Using library FastLED at version 3.1.8 in folder: /home/pi/software/arduino/arduino-1.8.5/hardware/teensy/avr/libraries/FastLED

Some extra variables and library calls remain, but heavily trimmed down.

Code:
#include <fastspi_nop.h>
#include <cpp_compat.h>
#include <fastled_config.h>
#include <bitswap.h>
#include <fastpin.h>
#include <power_mgt.h>
#include <pixeltypes.h>
#include <noise.h>
#include <fastspi_dma.h>
#include <FastLED.h>
#include <lib8tion.h>
#include <dmx.h>
#include <hsv2rgb.h>
#include <controller.h>
#include <colorutils.h>
#include <fastled_progmem.h>
#include <fastspi.h>
#include <color.h>
#include <platforms.h>
#include <fastled_delay.h>
#include <colorpalettes.h>
#include <chipsets.h>
#include <pixelset.h>
#include <fastspi_types.h>
#include <fastspi_ref.h>
#include <fastspi_bitbang.h>
#include <led_sysdefs.h>

#include <math.h>

// for interrupts
#include <avr/io.h>
#include <avr/interrupt.h>

#include <TimeLib.h>

#define numleds 288

#define DATA_PIN1 11
#define CLOCK_PIN1 14
#define DATA_PIN2 0
#define CLOCK_PIN2 32
#define OEPURPLEPIN 6
#define ENBLUEPIN 15
#define ENWHITEPIN 31

const int offset = -5;   // Central USA

CRGB leds[numleds * 20];
int co = 0;
static uint8_t sat = 0, val = 0;
uint32_t i = 0;
uint32_t pr = 1;
volatile int8_t Sec = 0, Min = 0, Hour = 0;

void setup()
{
  Serial.begin(9600);
  i = 0;
  while ((!Serial) && (i++ < 60)) { // Needed for Leonardo only
    delay(10);
  }
  if(!Serial) pr = 0;
  if(pr) Serial.printf("sr %x\n", RTC_SR);
 
  // LED strings
  FastLED.addLeds<APA102, DATA_PIN1, CLOCK_PIN1, RGB, DATA_RATE_MHZ(1)>(leds, 0, numleds/2);
  FastLED.addLeds<APA102, DATA_PIN2, CLOCK_PIN2, RGB, DATA_RATE_MHZ(1)>(leds, numleds/2, numleds*10);
  
  for(i = 0; i < numleds*20;   i++) {
    leds[i] = CHSV(0x7f, 0x3F, 0xaf);
  }

}

void loop()                 
{
  float nowf;
  static uint32_t lastTSR = 0;

  FastLED.show();
}
 
I'm going to chock this down to a hardware issue for SPI0. The broken pin on my driver chip was the VCC power one. That meant the incoming signal to the first APA102 wasn't very well formed. It propagated that and timing got off fast. 8MHz was the limit. Now that I have a good solid drive circuit, I'm getting DATA_RATE_MHZ(32) clear to the end of the 144 LED long string on SPI0. Note, I don't think it really is 32MHz. I'd need to calibrate my scope to tell. I do get saw teeth as the poor scope tries to keep up, but they don't change enough in length on the screen above DATA_RATE_MHZ(16) for me to feel it is really transmitting faster.

SPI1 is a different story. The saw teeth I see are packed tighter together for the first 8 bits than the next 24 bits. There are gaps between 16 bit groupings, with larger gaps between 32 bit groupings. The data rate for SPI1 is also much faster than the data rate for SPI0 when both are set to the same speed.
 
I took some oscilloscope pictures last night. Daytime shots had to many reflections, and the traces weren't visible for SCI1 images. SCI0 was on channel 1, and SCI1 on channel 2. Channel 2 doesn't get a text tag in the lower left side.

SCI1 @ DATA_RATE_MHZ(4), 4MHz. I couldn't get a stable lock on the first few bits of byte 1, but you can see the saw teeth are closer together than for the following three bytes. What looks like 0.2Ns is really 0.2 micro seconds. The fastest range my old 20MHz oscilloscope has, and it's uncalibrated and unstable too. It's also very hard to get a lock unless the signal is very regular.
IMG_20180926_005856.jpg

SCI0 at DATA_RATE_MHZ(4), 4MHZ with the same oscilloscope settings. Looks much better.
IMG_20180926_005754.jpg

I don't remember if this is at 2MHz or 4MHz, but it is from SCI0 and you can see nice 16 bit blocks of data with small gaps between them.
IMG_20180926_005623.jpg

This is SCI1 again, but at 1MHz or 2MHz.I got it to lock so you can see a full first byte at the higher data rate. Byte two starts after a short gap, and has a slower data rate.
IMG_20180926_005350.jpg
 
Wow, that's an impressive list of header files!

Code:
#include <fastspi_nop.h>
#include <cpp_compat.h>
#include <fastled_config.h>
#include <bitswap.h>
#include <fastpin.h>
#include <power_mgt.h>
#include <pixeltypes.h>
#include <noise.h>
#include <fastspi_dma.h>
#include <FastLED.h>
#include <lib8tion.h>
#include <dmx.h>
#include <hsv2rgb.h>
#include <controller.h>
#include <colorutils.h>
#include <fastled_progmem.h>
#include <fastspi.h>
#include <color.h>
#include <platforms.h>
#include <fastled_delay.h>
#include <colorpalettes.h>
#include <chipsets.h>
#include <pixelset.h>
#include <fastspi_types.h>
#include <fastspi_ref.h>
#include <fastspi_bitbang.h>
#include <led_sysdefs.h>

Do all of these come from FastLED? Or other libs too?
 
Those are the ones that were added to my file when I told the IDE I wanted to use the FastLED library. Yeah, I thought it was a bit much too.
 
I looked into possible timing issues in FastLED as I waited for crashes.

On a Teensy 3.6 does this need to be enabled for the hardware SPI, and disabled for bit banged SPI?

in fastspi.h
Code:
#if defined(FASTLED_TEENSY3) && (F_CPU > 48000000)
#define DATA_RATE_MHZ(X) (((48000000L / 1000000L) / X))
#define DATA_RATE_KHZ(X) (((48000000L / 1000L) / X))
#else
#define DATA_RATE_MHZ(X) ((F_CPU / 1000000L) / X)
#define DATA_RATE_KHZ(X) ((F_CPU / 1000L) / X)
#endif

I've updated to the latest Arduino IDE and Teensydino. I did that because I started getting mysterious lockups. No joy. I'm still getting them. also the output anomaly for the SPI1 serial is still the same. Swapped in my other T3.6, no change, still crashes after a few hours, and anomaly is the same.

What happens in the lockups is both the Serial output via USB and SPI ports stops at the same time. It usually takes many hours before it happens. Using LEDs on io pins, I have been able to tell that ALL my threads (TeensyThreads library) are all still running. I was expecting a crash on one or more. Nope. I've looked at memory usage, and that is static. No change.

Further exploration shows that I can make the crash happen much faster by changing thread stack positions in memory. One stack crosses the memory block divide between the two memory banks. Looks like I possibly got bit by an unaligned word access across that boundary. Did that thread somehow randomly change a common serial output register? I'm now 8 hours into a 48+ hour test with that stack not being used. 48 hours is over twice the longest time to serial output halt I was seeing. I was usually seeing 4 to 12 hours to serial output halt.

Thread on the perils of unaligned word access across memory bank boundary:
https://forum.pjrc.com/threads/45489-A-dangerous-Teensy-3-6-quirk

This thread I started awhile ago may be caused by the same issue:
https://forum.pjrc.com/threads/53008-Lockups-with-FastLED-amp-TeensyThreads
 
Status
Not open for further replies.
Back
Top