Teensy 3.5 and APA102's

Status
Not open for further replies.

JBDynamics

New member
Hi,

I've been an avid user of Teensy's for 4 years, and I'm having some issues with the 3.5 and APA102's. I just registered a forum account, as I haven't had any questions until now about using the Teensy's. My project is 5x socketed Teensy's on a set of replacement automotive gauges for Ford Super Duty's (two for LED control, one for odometer, one for motor control and one as a signal processor/commanding SPI master). Its for a dash swap, allowing 7.3L power strokes to use the newer 2008-2014 dashboards and gauge styles.

Basically, I am using the Teensy 3.5 because I need two dedicated sets of SPI lanes versus using the Teensy 3.2, which is fully supported with FastLED. I need one set of SPI lanes for communication with the master/signal processor, which is a Teensy 3.6 and another set of lanes for handling the data/clock signals for the APA102 LEDs. I have a teensy 3.5 for backlighting and one for indicator lights. In my board schematic and with my prototype strip I use the following decoupling capacitors: 33uF X7R MLCC for each 5 APA102's, and a 1uF for every APA102. I have not yet tried a buffer, level translator or op amp to increase the data and clock outputs to 5V. I have a 5V30A CC/CV LED specific power supply, which powers the LEDs and also powers the teensy over VIN/GND. I've been prototyping with strip lights, as I don't want to order my PCBs until I it can work with a prototype. Here's my Teensyduino code, I have also tried the Pololu APA102 library with no success. Basically I cannot get color control or all the LEDs to power on. It works flawlessly on the Teensy 3.2. I have tried numerous values less than 10 for the data rate. I have tried both hardware SPI and bit banging for LED control with no success at all using the Teensy 3.5. Do I need to translate the 3.3V signal to 5V? Should I just go with the Teensy 3.2 and bit bang so I can use the hardware SPI for communication control interface? I excluded the hardware SPI code as it is not necessary for this discussion.

Sorry if I forgot anything, I will post pictures of the prototype later today, as I am traveling on business right now.

Code:
/*
 * This is a Arduino solution that reads an encoder input and controls brightness
 * and LED color using the commands from the encoder.
 */
//#define FASTLED_FORCE_SOFTWARE_SPI
#define DEBUG true
#include <FastLED.h>

#define PIN_A       9
#define PIN_B       10
#define DATA_PIN    11
#define CLK_PIN     13
#define SWITCH_PIN  23
#define NUM_LEDS    72
#define LED_TYPE   APA102
#define COLOR_ORDER RGB
#define MAX_BRIGHTNESS 192       Thats full on, watch out
#define MIN_BRIGHTNESS 0        set to a minimum of 25%n

unsigned long currentTime;
unsigned long loopTime;
uint8_t ledBrightness = 126;
int encoder_A;
int encoder_B;
int encoder_A_prev=0;
uint8_t counter=63;
unsigned int paletteCounter=0;
CRGB colorPalette[] = {CRGB::White, CRGB::Red, CRGB::Orange, CRGB::Green, CRGB::LightBlue, CRGB::Blue, CRGB::Purple, CRGB::Magenta, CRGB::Black};
CRGB leds[NUM_LEDS];

void changeHue() {
  Serial.println("Color Palette changed");
  paletteCounter = (paletteCounter+1) % 9;
  fill_solid(leds, 72, colorPalette[paletteCounter]);
  FastLED.setBrightness(constrain(ledBrightness, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
  FastLED.show();
}

void setup()  {
  delay(250);  power-up safety delay
  pinMode(PIN_A, INPUT);
  pinMode(PIN_B, INPUT);
  FastLED.addLeds<LED_TYPE, DATA_PIN, CLK_PIN, COLOR_ORDER, DATA_RATE_MHZ(10)>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  fill_solid(leds, 72, colorPalette[paletteCounter]);
  FastLED.setBrightness(constrain(ledBrightness, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
  FastLED.show();
  currentTime = millis();
  loopTime = currentTime;
  interrupts();
  attachInterrupt(digitalPinToInterrupt(SWITCH_PIN), changeHue, FALLING);
  Serial.begin(9600);
  Serial.println("Teensy initialized");
}

void loop()  {
   get the current elapsed time
  currentTime = millis();
  if(currentTime >= (loopTime + 5)) {
     5ms since last check of encoder = 200Hz  
    encoder_A = digitalRead(PIN_A);     Read encoder pins
    encoder_B = digitalRead(PIN_B);   
    if((!encoder_A) && (encoder_A_prev)) {
      if(encoder_B) {
         B is high so clockwise
        counter++;
        char stringBuffer[20];
        if(DEBUG) {
          sprintf(stringBuffer, "CW - %d", counter);
          Serial.println(stringBuffer);
        }
        if(counter < 64) {
          ledBrightness = counter *2;
          fill_solid(leds, 72, colorPalette[paletteCounter]);
          FastLED.setBrightness(constrain(ledBrightness, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
          FastLED.show();
        }
      }
      else {
         B is low so counter-clockwise
        if (counter >= 1) {
          counter--;
        }
        char stringBuffer[20];
        if(DEBUG) {
          sprintf(stringBuffer, "CCW - %d", counter);
          Serial.println(stringBuffer);
        }
        if(counter < 64) {
          ledBrightness = counter *2;
          fill_solid(leds, 72, colorPalette[paletteCounter]);
          FastLED.setBrightness(constrain(ledBrightness, MIN_BRIGHTNESS, MAX_BRIGHTNESS));
          FastLED.show();
        }
      }
    } 
    encoder_A_prev = encoder_A;      Store value of A for next time    
    loopTime = currentTime;   Updates loopTime
  }
}
 
To drive the APA102s, yes, you need a level shifter to get from the 3.3V Teensy to the 5V APA102 LEDs. It's tempting to try to do without because it almost works, it's usually not a good use of time or money. Might not matter whether you're using hardware SPI or bit banging unless you need high update rates for hundreds of LEDs.
 
I have not had any issues with APA102's being driven from 3.3V on T3.2 and T3.6. Have you tried running any examples from the library?
 
I have not had any issues with APA102's being driven from 3.3V on T3.2 and T3.6. Have you tried running any examples from the library?

Lucky you? I have had issues driving APA102s from 3.3V on T3.2. Adding a level shifter fixed it. Maybe your power supply was better. Who knows?

Considering that this is an automotive applications, going outside the datasheet to avoid adding a cheap part seems like a bad bet to me.
 
As another data point have had very mixed success with APA102s on 3.3V. Depending on your hardware a basic test can be to run the whole strip on 3.3V (may need to shorten the in use LEDs to avoid drawing too much current) and confirm stable patterns. The blue LEDs will not work/be dim but the pattern should be stable since the controller ICs normally still work OK. Ugly hack if you want a level converter in a hurry is to cut off a single LED from the strip and power from 5V via a diode, with another diode on the -ve for ~4V operation and is it as your first pixel (and offset all your patterns by one to leave it dark). Lots of reasons why it is not a good idea but a 4V driven pixel can normally read 3.3V logic and drive 5V powered pixels.
 
Using Teensy 3.6, FastLED, and a strip of APA102, I had to decrease the CPU speed to 120 Mhz before I had any reasonable control (running both signals through a SN74HCT245N). Drove me nuts trying to figure this out. WS2812b appear to run fine through the same level shifter at 180 Mhz.
 
Status
Not open for further replies.
Back
Top