teensy3.1 + tlc59711 16 bit led driver timing issue and flicker?

Status
Not open for further replies.

cdorety

Member
Hey all,

I'm running adafruit's tlc59711 library on a teensy 3.1: https://github.com/adafruit/Adafruit_TLC59711

teensyduino 1.22
arduino 1.06
(same problem occurs in teensyduino 1.18-rc1 with arduino 1.05)

This is a breadboard situation, but I have the tlc59711 powered separately and co-grounded with the teensy. I understand that breadboards are not ideal environments for high-speed data testing. That being said, the flicker is consistent as to being in the lower brightness levels whether ramping up or down. Signals look clean wherever I scope them. Experience and intuition tell me it is code timing.


I run a simple brightness loop (code below) that ramps from 0 to 3000 (of 65535) increments of 20 (i+=20)

I notice some random flickering in the lower brightness registers (probably in the hundreds) as it ramps up. If I run the loop all the way to 65535, the flickering is not apparent in the higher brightness values.

When I scope the clk signal I notice that the clock stays high for two cycles occasionally (see image). Is this normal? could it cause such a flicker? It seems to happen every 8 clock cycles.



Code:
/*************************************************** 
  This is an example for our Adafruit 12-channel PWM/LED driver

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/

  These drivers uses SPI to communicate, 2 pins are required to  
  interface: Data and Clock. The boards are chainable

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/


#include "Adafruit_TLC59711.h"
#include <SPI.h>


// How many boards do you have chained?
#define NUM_TLC59711 2

#define data  8
#define clock  7





Adafruit_TLC59711 tlc = Adafruit_TLC59711(NUM_TLC59711, clock, data);
//Adafruit_TLC59711 tlc = Adafruit_TLC59711(NUM_TLC59711);

void setup() {

  pinMode(10, OUTPUT);
  tlc.begin();
  tlc.write();
  
 
 
  
}

void loop() {
  
 
  colorRamp();
  

}

void colorRamp() {
  
  for (long j = 0; j < 3000; j+=20){
    for(uint16_t i=0; i<4*NUM_TLC59711; i++) {
        tlc.setLED(i, j, j, j);
        
        
    }
    tlc.write();
    delay(20);
  }
}

scope_clk_data.png

Here's a video (might not be super clear)

https://youtu.be/f8u6sNHwDro


I'm working on a PCB design that will have a tlc59711 and 4 bright RGB leds. It will be swrt, but I gotta fix this flicker.

PS the same flicker is apparent if I read color information off an SD card. I create a brightness ramp in photoshop, save it as raw, read it from the card and write the data to the LEDs...same lower brightness flicker.


Any insight would be AMAZING. go teensy!
 

Attachments

  • tlc59711_test_post.ino
    3.3 KB · Views: 538
I am thinking it might have something to do with the Software SPI bit banging timing?

I am using pins 7 and 8

I would use the hardware SPI pins, but those are reserved for the SD card.
 
Just for fun I moved clock and data to the Hardware SPI pins (11 and 13).

I am having the same flicker but now much faster!
 
Have either of you tried the TLC5940 as there seems to be a specific lib for that for the teensy. I am just trying to work out what chip to use for a POV.
 
Interestingly, I am unable to affect a change in the SPI speed by changing SPI.setClockDivider(SPI_CLOCK_DIV128);

Also unable to change mode: SPI.setDataMode(SPI_MODE3);
 
flicker potentially solved.

the adafruit breakout board has 5 input and output pins:

GND
VCC
V+
CI
DI

I mistakenly thought I could have the VCC in not connected. The data sheet for the tlc59711 states that, when run from 3.3 to 5 volts, the Vref (v+)pin should also be connected to VCC.

The data sheet also implies that it can be connected to ground with a 1uF cap.

anyhow, Thanks for the opportunity to publicly go through my own troubleshooting process.
 
Have either of you tried the TLC5940 as there seems to be a specific lib for that for the teensy. I am just trying to work out what chip to use for a POV.

No. It's only 12-bit and I really want to have 16-bit control because I'm trying to get very smooth low level fades.
 
So did this solve the issue ?

I finally fixed this for me. Wow did this take longer to figure out than I expected. It boiled down to a clock problem. Teensy was sending serial data too fast, and the Adafruit library has the lines below which are supposed to set the clock speed and other serial options but weren't actually doing anything.

Code:
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE0);

The library for the TLC59711 references old SPI code. I think the clock settings, the MSB settings, and the phase settings were basically being ignored. I updated my TLC library to take into account the new transactional SPI code as show on this page: https://www.pjrc.com/teensy/td_libs_SPI.html.

And set my settings to: SPISettings SPI_SETTINGS(1000000, MSBFIRST, SPI_MODE0);

I also had to put "SPI.beginTransaction(SPI_SETTINGS)" at the beginning of the Adafruit_TLC59711::write() method, and put a matching "SPI.endTransaction()" at the end of the method. See below.

No more flickering or glitchy fades.

Best -- Andrew

Code:
SPISettings SPI_SETTINGS(1000000, MSBFIRST, SPI_MODE0); 

void Adafruit_TLC59711::write(void) {
	
  SPI.beginTransaction(SPI_SETTINGS);
	
  uint32_t command;

  // Magic word for write
  command = 0x25;
  command <<= 5;

  //OUTTMG = 1, EXTGCK = 1, TMGRST = 1, DSPRPT = 0, BLANK = 0 -> 0x16
  command |= 0x16;

  command <<= 7;
  command |= BCr;

  command <<= 7;
  command |= BCg;

  command <<= 7;
  command |= BCb;

  cli();
  for (uint8_t n=0; n<numdrivers; n++) {
    spiwriteMSB(command >> 24);
    spiwriteMSB(command >> 16);
    spiwriteMSB(command >> 8);
    spiwriteMSB(command);

    // 12 channels per TLC59711
    for (int8_t c=11; c >= 0 ; c--) {
      // 16 bits per channel, send MSB first
      spiwriteMSB(pwmbuffer[n*12+c]>>8);
      spiwriteMSB(pwmbuffer[n*12+c]);
    }
  }

  if (_clk >= 0)
    delayMicroseconds(200);
  else
    delayMicroseconds(2);

	SPI.endTransaction();

  sei();

}
 
I've got my new PCB's in with the tlc59711 and 4 high-power LEDs. They work great! I've moved over to the teensy LC as a controller due to the double SPI capability.

All that being said...I found a NEW flicker.

As per andrew's (catgetnosleep) post above, I modified my adafruit_tlc59711.cpp with the following lines:

Code:
SPISettings SPI_SETTINGS(1000000, MSBFIRST, SPI_MODE0); 

void Adafruit_TLC59711::write(void) {
	
  SPI.beginTransaction(SPI_SETTINGS);
	
  uint32_t command;

  // Magic word for write
  command = 0x25;
  command <<= 5;

  //OUTTMG = 1, EXTGCK = 1, TMGRST = 1, DSPRPT = 0, BLANK = 0 -> 0x16
  command |= 0x16;

  command <<= 7;
  command |= BCr;

  command <<= 7;
  command |= BCg;

  command <<= 7;
  command |= BCb;

  cli();
  for (uint8_t n=0; n<numdrivers; n++) {
    spiwriteMSB(command >> 24);
    spiwriteMSB(command >> 16);
    spiwriteMSB(command >> 8);
    spiwriteMSB(command);

    // 12 channels per TLC59711
    for (int8_t c=11; c >= 0 ; c--) {
      // 16 bits per channel, send MSB first
      spiwriteMSB(pwmbuffer[n*12+c]>>8);
      spiwriteMSB(pwmbuffer[n*12+c]);
    }
  }

  if (_clk >= 0)
    delayMicroseconds(200);
  else
    delayMicroseconds(2);

	SPI.endTransaction();

  sei();

}

I am able to run the tlc59711 atg 2MHz, but if I go above that, I get a flicker as the teensy LC writes data to the registers. It is very regular in nature.

Anyone here running the tlc59711 faster than 2MHz?
 
I recently built a TLC59711-based LED controller and used Adafruit's library. But while I have been contemplating switching to the Teensy (mainly to get lower USB latency), my controller is currently Arduino Uno based, so I might get kicked off here. ;)

I had changed Adafruit_TLC59711.cpp to increase the SPI clock to 8 MHz for my LED controller by replacing SPI_CLOCK_DIV8 with SPI_CLOCK_DIV2, just tried cdorety's colorRamp() code, and could not see any flickering for my setup.

Note that Adafruit's library either uses the SPI library or transfers "manually" by controlling data and clock directly. If the library is instantiated with just the number of chips (e.g., Adafruit_TLC59711 tlc = Adafruit_TLC59711(NUM_TLC59711);), it is in SPI mode. Internally, it uses if (_clk >= 0) to check whether it is in manual mode. Andrew (cantgetnosleep)'s changes to the library do not take this into account, and while, e.g., the SPI.setClockDivider used in Adafruit's library is deprecated, it still worked for me on the Arduino.

In theory, with 8 MHz SPI clock, I should have been able to set two TLC59711s in 56 μs (224 bits * 2 / 8 Mbits/s). But I measured only 420 μs for 8 MHz. My hunch is part of the culprit is that the Adafruit library calls SPI.transfer() once for every 32 bits instead of using a buffer. Still, the 420 μs is better than what I got for the library's original 2 MHz SPI clock (589 μs) and "manual" mode (1044 μs).

Judging from the datasheet of the TLC59711, there is a case for using TMGRST = 0 to reduce flickering, but I found this to not make a difference; I could not see flickering for either 0 or 1. (For details, see my comments on this post.) Nonetheless, it may make a difference for someone else, so here how to change this in the Adafruit library:

Code:
void Adafruit_TLC59711::write(void) {
  uint32_t command;

  // Magic word for write
  command = 0x25;

  command <<= 5;
  //OUTTMG = 1, EXTGCK = 0, TMGRST = 1, DSPRPT = 1, BLANK = 0 -> 0x16
  //command |= 0x16;
  command |= 0x12;

  command <<= 7;
  command |= BCr;
...
 
Last edited:
"SPI.setClockDivider[/URL] used in Adafruit's library is deprecated, it still worked for me on the Arduino." -- Good to know. May be a difference in the Teensy and Arduino SPI implementations. When I checked it with a scope, I saw that using setClockDivider() had no effect, which was causing the SPI to run too fast for the TLC, and updating the write() method to use the newer SPI code fixed the SPI write rate.

"Andrew (catgetnosleep)'s changes to the library do not take this into account.." Specifically what do you mean by this?

Thanks and have a great day.

Andrew
 
"Andrew (catgetnosleep)'s changes to the library do not take this into account.." Specifically what do you mean by this?

Your changes make SPI calls even if the Adafruit library is in manual mode (i.e., when instantiated with Adafruit_TLC59711::Adafruit_TLC59711(uint8_t n, uint8_t c, uint8_t d)). In SPI mode (i.e., when instantiated with Adafruit_TLC59711::Adafruit_TLC59711(uint8_t n)), _clk is set to -1. SPI calls should be made only if _clk < 0. I am not sure how much "harm" is done due to this, though.
 
New TLC59711 library

All,

I wrote a new library for the TLC59711 and put it on GitHub. My main goals were to make it fast, reliable, and Teensy compatible. The library's Wiki has a comparison with the Adafruit library and various other info. (Some of the timing info I posted on this thread previously was off; reason and corrected info is on the Wiki.)

@cdorety, the TLC's VCC is not connected to the Adafruit board's VCC! In addition, the wiring in their "learn" article for the board has two issues. See the Wiki's Electronics notes section for details.

Cheers,

Uli
 
Status
Not open for further replies.
Back
Top