Teensy 3.6 is very slow for some reason...

Status
Not open for further replies.

nicnut

Well-known member
Hi,

First of all, I want to thank everyone here for their guidance. I've had a few issues with the project I'm working on and all have been resolved, EXCEPT for the new one I am encountering now.

This is sort of related to another thread, but it's a different issue so I am creating this new post.

Here is my last post, which seems resolved:

https://forum.pjrc.com/threads/5955...kering-from-PWM-breakout-board-and-Teensy-3-6

I have a Teensy 3.6. I now have 2 PWM LED driver boards with 5 RGB LEDs connected to them (for testing, going to eventually have 17), and 3 LED displays connected to the Teensy using the SCL0 and SDA0 pins.

When I send the LED boards messages to control the LEDs they are slow if I send a bunch of messages in fast succession, like if I send 10 messages in 30 milliseconds it might take a few seconds to display all of them. I originally guessed it was the PWM LED boards just being slow.

But then I connected some LED displays to the SCL0 and SDA0 and sent a bunch of messages really fast and they took a few seconds to display them.

In my previous tests, before I connected the PWM LED boards, the LED displays showed their animations pretty much instantly, no lag whatsoever. But now there is a lag.

Maybe there is something in my code or settings that is needs to me changed? The new thing I added to the code was what was needed to communicate with the PWM LED boards.


I added this to my void setup because it was in the example code for the PWM LED boards

Code:
  Serial.begin(9600);

 Serial.println("TLC5947 test");
  tlc.begin();
  if (oe >= 0) {
    pinMode(oe, OUTPUT);
    digitalWrite(oe, LOW);
  }

I ended up commenting some of it out, so like this

Code:
  //Serial.begin(9600);

 // Serial.println("TLC5947 test");
  tlc.begin();
  if (oe >= 0) {
    pinMode(oe, OUTPUT);
    digitalWrite(oe, LOW);
  }

And it didn't seem to make a difference. I don't know if this has anything to do with it. But it might since that is what was added.

Right now, when uploading my code to Teensy in "Tools" I select MIDI.

Because of Serial.begin(9600)

Should I select Serial + MIDI, or something else? I also wonder if I should change the speed in Seiral.begin to something else. But when I comment it out it doesn't seem to matter anyway.

Is there too much PWM happening with SCL0, SDA0 and the LED boards getting sent messages on 3 digital pins, that something is getting slowed down? Any other ideas or things I can try?

How can I get it back to being instantaneous display of messages?

Thank you and let me know if you have any suggestions.
 
Serial.begin() is extraneous and the value always ignored on Teensy with native USB hardware.

If Serial USB is part of the build - then it will come online as soon as the computer connects without need for the .begin().

And entry into setup() will happen before USB can connect so to see the first messages before 50 to 500 milliseconds elapse after entry (depending on computer connection) a wait like this is required:: { while( !Serial ); } or { while( !Serial && millis()<2000 ); }

So that should not relate to the issue. But with a wait like above the prints will show on the SerMon so you can better debug and see what is happening.

No complete sketch showing the trouble is provided and guessing with the description isn't clear where to start, except changing the LED's every 3 ms seems fast - but not sure of the device and it's ability to respond or buffer at that rate.
 
Last edited:
Please follow the "Forum Rule" which appears at the top of every page on this forum. Show a *complete* program. If using libraries other than the set Teensyduino installs, please clearly state which libs you use.

Also, please try to clearly explain what you are actually observing. When you write "now there is a lag", consider that we can not see your screen or your hardware, unless you show pictures or video. Unless you clearly describe, we do not know what action you are actually doing and then what you are actually observing which constitutes "lag". Please be specific. Avoid the common problem of saying *only* what you believe. Clearly state the things you actually do and actually observe. Ideally, your info should allow anyone with the same hardware to reproduce the same problem.

We want to help you. Please give clearer & complete info. Helping solve problems over the internet is always challenging, but lack of complete code and clear info (and pictures or video) makes helping you much harder.
 
Hi,

Yes my post was pretty vague. Sorry about that. I am having a hard time articulating what's going on.

I made a video that will help a little bit. Here is a link:

https://www.youtube.com/watch?v=ApEMP2Us8Q8&feature=youtu.be

I will try again to explain what is going on, because it might be hard to tell from the video.

I am creating a MIDI controller. I have a Teensy 3.6. In the end it will have Analog sensors, Digital sensors, 4 LED displays, like the ones in the video and hopefully 17 RGB LEDs that are inside some button switches, that you can see in the video.

The RGB LEDs are connected to a PWM LED driver. It is this product:

https://www.adafruit.com/product/1429

Right now I have 5 RGB LEDs connected to 2 of these PWM LED boards that are chained together. Eventually I want to have 17 of them connected to 3 PWM LED boards.

I have been selecting USB type: MIDI when uploading my code. In the beginning of the video you can see that I am sending MIDI messages that are creating random musical pitches and they are triggering animations in the LED displays. This is working perfectly, the timing is perfectly in sync as far as I can see. While I am doing this the code that controls the RGB LEDs is not uploaded to the Teensy

These LED displays are connected to the SCL0 and the SDA0 pins on the Teensy.

When I upload the code that sends messages to the PWM LED driver it slows down the messages going to the LED displays that worked great before. And the messages going to the RGB LEDs are really slow, you can see in the 2nd half of the video that it takes a few seconds for them to respond to all their MIDI messages they have received to change colors. The PWM LED drivers are connected to:

#define data 28 //
#define clock 30
#define latch 29
#define oe -1 // not being used.

I don't want to upload all the code because it is so much, including all the different colors and all the LED animations. Also I don't have any analog or digital sensors connected right now. I'm just trying to get these LEDs and LED displays working, then I'll check the sensors after that.

If you want to see other parts of the code that I didn't upload let me know

Here are the libraries I'm using and the info for the LED driver

Code:
#include <Bounce.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h> // wire library for LED matrix

#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

#include "Adafruit_TLC5947.h"  // for LED breakout board

// How many boards do you have chained?
#define NUM_TLC5947 2       // how many breakout boards?

#define data   28     // digital pins on the Teensy
#define clock   30
#define latch   29
#define oe  -1  // set to -1 to not use the enable pin (its optional)  // for LED boards

Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5947, clock, data, latch);

Here's my setup()

Code:
void setup() {

  //Serial.begin(9600);

 // Serial.println("TLC5947 test");     // commenting this out. Doesn't seem to matter if it's in or not. 
  tlc.begin();
//  if (oe >= 0) {
 //   pinMode(oe, OUTPUT);
  //  digitalWrite(oe, LOW);
  // }

  // wire 3.3V to AREF for 3.3V reference
  analogReference(DEFAULT);

  pinMode(0, INPUT_PULLUP);   // for button swithces
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(24, INPUT_PULLUP);
  pinMode(25, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);
  pinMode(27, INPUT_PULLUP);

  // pinMode(ledPin28, OUTPUT);   // LED on digital pin 28
  // pinMode(ledPin29, OUTPUT);   // LED on digital pin 29
  // pinMode(ledPin30, OUTPUT);   // LED on digital pin 30
  // pinMode(ledPin31, OUTPUT);   // LED on digital pin 31
  // pinMode(ledPin32, OUTPUT);   // LED on digital pin 32
  // pinMode(ledPin33, OUTPUT);   // LED on digital pin 33

  usbMIDI.setHandleControlChange(myControlChange);
  setupLedDisplays();



}



Here's my loop(). I noticed i have some variables in between setup() and Loop(), I included those.

Code:
// store previously sent values, to detect changes
int previousA0 = -1;
int previousA1 = -1;
int previousA2 = -1;
int previousA3 = -1;
int previousA4 = -1;
int previousA5 = -1;
int previousA6 = -1;
int previousA7 = -1;
int previousA8 = -1;
int previousA9 = -1;
int previousA10 = -1;
int previousA11 = -1;
int previousA12 = -1;


elapsedMillis msec = 0;



void loop() {

  {

    button0.update();    //  this button code works, goes from 0 to 127 when pressed
    button1.update();
    button2.update();
    button3.update();
    button4.update();
    button5.update();
    button6.update();
    button7.update();
    button8.update();
    button9.update();
    button10.update();
    button11.update();
    button12.update();
    button24.update();
    button25.update();
    button26.update();
    button27.update();



    if (button0.fallingEdge()) {                               // this deals with reading the button swithces
      usbMIDI.sendControlChange(controllerD14, 127, channel);
    }

    if (button0.risingEdge()) {
      usbMIDI.sendControlChange(controllerD14, 0, channel);
    }

    if (button1.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD15, 127, channel);
    }

    if (button1.risingEdge()) {
      usbMIDI.sendControlChange(controllerD15, 0, channel);
    }

    if (button2.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD16, 127, channel);
    }

    if (button2.risingEdge()) {
      usbMIDI.sendControlChange(controllerD16, 0, channel);
    }

    if (button3.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD17, 127, channel);
    }

    if (button3.risingEdge()) {
      usbMIDI.sendControlChange(controllerD17, 0, channel);
    }

    if (button4.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD18, 127, channel);
    }

    if (button4.risingEdge()) {
      usbMIDI.sendControlChange(controllerD18, 0, channel);
    }

    if (button5.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD19, 127, channel);
    }

    if (button5.risingEdge()) {
      usbMIDI.sendControlChange(controllerD19, 0, channel);
    }

    if (button6.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD20, 127, channel);
    }

    if (button6.risingEdge()) {
      usbMIDI.sendControlChange(controllerD20, 0, channel);
    }

    if (button7.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD21, 127, channel);
    }

    if (button7.risingEdge()) {
      usbMIDI.sendControlChange(controllerD21, 0, channel);
    }

    if (button8.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD22, 127, channel);
    }

    if (button8.risingEdge()) {
      usbMIDI.sendControlChange(controllerD22, 0, channel);
    }

    if (button9.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD23, 127, channel);
    }

    if (button9.risingEdge()) {
      usbMIDI.sendControlChange(controllerD23, 0, channel);
    }

    if (button10.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD24, 127, channel);
    }

    if (button10.risingEdge()) {
      usbMIDI.sendControlChange(controllerD24, 0, channel);
    }

    if (button11.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD25, 127, channel);
    }

    if (button11.risingEdge()) {
      usbMIDI.sendControlChange(controllerD25, 0, channel);
    }

    if (button12.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD26, 127, channel);
    }

    if (button12.risingEdge()) {
      usbMIDI.sendControlChange(controllerD26, 0, channel);
    }

    if (button24.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD27, 127, channel);
    }

    if (button24.risingEdge()) {
      usbMIDI.sendControlChange(controllerD27, 0, channel);
    }

    /*

      if (button25.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD28, 127, channel);
      }

      if (button25.risingEdge()) {
      usbMIDI.sendControlChange(controllerD28, 0, channel);
      }

      if (button26.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD29, 127, channel);
      }

      if (button26.risingEdge()) {
      usbMIDI.sendControlChange(controllerD29, 0, channel);
      }

      if (button27.fallingEdge()) {
      usbMIDI.sendControlChange(controllerD30, 127, channel);
      }

      if (button27.risingEdge()) {
      usbMIDI.sendControlChange(controllerD30, 0, channel);
      }

    */

  }


  // only check the analog inputs 50 times per second,
  // to prevent a flood of MIDI messages
  if (msec >= 3) {               //  i changed this value to 10 from 20 for faster updates
    msec = 0;

    int n0 = map(analogRead(A0), 0, 1023, 0, 127);
    int n1 = map(analogRead(A1), 0, 1023, 0, 127);
    int n2 = map(analogRead(A2), 0, 1023, 0, 127);
    int n3 = map(analogRead(A3), 0, 1023, 0, 127);
    int n4 = map(analogRead(A4), 0, 1023, 0, 127);
    int n5 = map(analogRead(A5), 0, 1023, 0, 127);
    int n6 = map(analogRead(A6), 0, 1023, 0, 127);
    int n7 = map(analogRead(A7), 0, 1023, 0, 127);
    int n8 = map(analogRead(A8), 0, 1023, 0, 127);
    int n9 = map(analogRead(A9), 0, 1023, 0, 127);
    int n10 = map(analogRead(A14), 0, 1023, 0, 127);
    int n11 = map(analogRead(A15), 0, 1023, 0, 127);
    int n12 = map(analogRead(A16), 0, 1023, 0, 127);


    // only transmit MIDI messages if analog input changed
    if (n0 != previousA0) {
      previousA0 = n0;
      if (n0 < 2) n0 = 0;
      usbMIDI.sendControlChange(controllerA0, n0, channel);
    }

    if (n1 != previousA1) {
      previousA1 = n1;
      if (n1 < 2) n1 = 0;
      usbMIDI.sendControlChange(controllerA1, n1, channel);
    }

    if (n2 != previousA2) {
      previousA2 = n2;
      if (n2 < 2) n2 = 0;
      usbMIDI.sendControlChange(controllerA2, n2, channel);

    }
    if (n3 != previousA3) {
      previousA3 = n3;
      if (n3 < 2) n3 = 0;
      usbMIDI.sendControlChange(controllerA3, n3, channel);
    }

    if (n4 != previousA4) {
      previousA4 = n4;
      if (n4 < 2) n4 = 0;
      usbMIDI.sendControlChange(controllerA4, n4, channel);

    }

    if (n5 != previousA5) {
      previousA5 = n5;
      if (n5 < 2) n5 = 0;
      usbMIDI.sendControlChange(controllerA5, n5, channel);

    }

    if (n6 != previousA6) {
      previousA6 = n6;
      if (n6 < 2) n6 = 0;
      usbMIDI.sendControlChange(controllerA6, n6, channel);

    }

    if (n7 != previousA7) {
      previousA7 = n7;
      if (n7 < 2) n7 = 0;
      usbMIDI.sendControlChange(controllerA7, n7, channel);

    }

    if (n8 != previousA8) {
      previousA8 = n8;
      if (n8 < 2) n8 = 0;
      usbMIDI.sendControlChange(controllerA8, n8, channel);
    }

    if (n9 != previousA9) {
      previousA9 = n9;
      if (n9 < 3) n9 = 0;
      usbMIDI.sendControlChange(controllerA9, n9, channel);
    }

    if (n10 != previousA10) {
      previousA10 = n10;
      if (n10 < 3) n10 = 0;
      usbMIDI.sendControlChange(controllerA10, n10, channel);
    }

    if (n11 != previousA11) {
      previousA11 = n11;
      if (n11 < 3) n11 = 0;
      usbMIDI.sendControlChange(controllerA11, n11, channel);
    }

    if (n12 != previousA12) {
      previousA12 = n12;
      if (n12 < 3) n12 = 0;
      usbMIDI.sendControlChange(controllerA12, n12, channel);
    }



  }

  // MIDI Controllers should discard incoming MIDI messages.
  // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

Here's part of the code that controls or sends messages to change the RGB LED colors. I'm not going to include all of it, but you should get the idea.

Code:
void myControlChange(byte channel, byte control, byte value) // for LEDs, MIDI output

{

  if (channel == MIDIchannel                 // going to try eliminating 2nd write
      && control == ledcontroller15
      && value == 0)


    tlc.setLED(0, 0, 0, 0);    //off
  tlc.write();
//  tlc.write();


  if (channel == MIDIchannel
      && control == ledcontroller15
      && value == 10)


    tlc.setLED(0, 246, 84, 106);  //light pink
  tlc.write();
 // tlc.write();


  if (channel == MIDIchannel
      && control == ledcontroller15
      && value == 20)


    tlc.setLED(0, 0, 0, 255);        //blue
  tlc.write();
 // tlc.write();

  if (channel == MIDIchannel
      && control == ledcontroller15
      && value == 30)


    tlc.setLED(0, 90, 0, 255);        //lavender
  tlc.write();
 // tlc.write();


If you want to see other parts of the code let me know.
 
I'm still trying to figure out what's going on with this code issue (hopefully that's what it is)

Because I am using SCL0 and SDA0 for the LED displays, and that happens on the same pins that are A5 and A4, I commented out the code pertaining to A4 and A5 in my loop()

So my loop() now has

Code:
   int n0 = map(analogRead(A0), 0, 1023, 0, 127);
    int n1 = map(analogRead(A1), 0, 1023, 0, 127);
    int n2 = map(analogRead(A2), 0, 1023, 0, 127);
    int n3 = map(analogRead(A3), 0, 1023, 0, 127);
  //  int n4 = map(analogRead(A4), 0, 1023, 0, 127);   //commented this out for SCL0 and SDA0
  //  int n5 = map(analogRead(A5), 0, 1023, 0, 127);
    int n6 = map(analogRead(A6), 0, 1023, 0, 127);
    int n7 = map(analogRead(A7), 0, 1023, 0, 127);
    int n8 = map(analogRead(A8), 0, 1023, 0, 127);
    int n9 = map(analogRead(A9), 0, 1023, 0, 127);
    int n10 = map(analogRead(A14), 0, 1023, 0, 127);
    int n11 = map(analogRead(A15), 0, 1023, 0, 127);
    int n12 = map(analogRead(A16), 0, 1023, 0, 127);

It didn't seem to change anything relating to my timing issue. But I think I needed to fix that anyway.

If anyone has any suggestions or things I should try please let me know. I think I am pretty much out of ideas.

Thanks, Nick.
 
Hi all,

I am just updating you all to something else that I tried. It didn't work, but I am adding it here to document it and in case it inspires someone to think of something else I should try.

The LED displays I have connected (that you can see in the video) are connected to SCL0 and SDA0 on the Teensy, which is digital pins 19 and 18 respectively.

I figured I should have the LED drivers connected to the same Data and Clock pins. It made sense to me.

So I changed my code to be like this:

Code:
#define data   18     // digital pins on the Teensy, SDA0 and SCL0
#define clock   19
#define latch   29
#define oe  -1  // set to -1 to not use the enable pin (its optional)  // for LED boards

I tried that and it didn't work :(

Actually, now when I send the LED displays a message I see the RGB LEDs changing colors so it is not at all a good idea.

If anyone else has an idea I should try to resolve this let me know. I hope I can somehow work this out.
 
I watched the video and read the posts... I think I understand what he's asking. The problem has nothing to do with the teensy, it's related to the driver code: https://github.com/adafruit/Adafruit_TLC5947/blob/master/Adafruit_TLC5947.cpp

The driver code uses software SPI (to make it compatible with as many different microcontrollers as possible) rather than hardware SPI. Software SPI is slow enough that it just takes a while to clock all the data out. If you are really set on using the TLC5947 chips, you'll need to either find a driver library that uses hardware SPI, or write it yourself. Alternatively, if you could switch to using WS2812 RGB LEDs, you could use Paul's driver library: https://www.pjrc.com/non-blocking-ws2812-led-library/ Which should be much higher performance, and it's non-blocking as well so it will stay responsive to incoming MIDI messages.

Anyway... hope that helps.
 
Nice answer....

I suspect the midi code is a problem too.

Have you checked how much midi noise it's generating?

I suspect there will be a lot of alternating and adjacent CC messages.

This won't slow your Teensy down much but it might make it feel less responsive as the master stuggles to process the midi queue.

And turning down the time limit between messages, which code comments imply you have, could make it worse not better.

Potentiometer noise is a rich subject for DIY midi but theResponsiveAnalogRead library is the easy answer for taming voltage readings for MIDI on Teensy.
 
Hi wcalvert

Thank you for the reply. Yes, the problem is not with the Teensy, as when i delete the code related to the Adafruit LED driver everything works fine. I should change the name of this thread.

OK I am so happy that there is a Teensy library to deal with this problem! amazing.

So if I can't use the TLC5947 chips do you have a suggestion of how to connect my RGB LEDs? This project is based around a Teensy 3.6, but there's not enough pins to do everything with one of those. Can I connect another Teensy to the 3.6? I'm planning on 17 RGB LEDs so that's 51 LED pins I will need.

Thank you for your input, I had a feeling it had something to do with that Adafruit board.

EDIT:

Ok, I read through this page:

https://github.com/PaulStoffregen/WS2812Serial/blob/master/examples/BasicTest/BasicTest.ino

I think if I understand this correctly I don't need any extra hardware, I just connect my LEDs to one pin. then connect them together in a chain.

But I am not using Neopixels, or any kind of LED with a chip in it. I have a button switch that has RGB LEDs in it. Each one of these has 2 pins for the button switch part (which I am guessing I won't use for this) and 3 pins for R G and B and one pin for power, connected to Vin.

Will this still work? or do I need to try and find a different button switch with a Neopixel type LED in it?

thanks again.
 
Last edited:
Hi Oddson.

Thanks for the input. Right now the midi code and sensors work fine. You are probably right in that it can be optimized to work better/faster. But in my previous version of this code the midi input and output is fine. For what I'm doing I only read MIDI data at one control change controller number at a time so the noise is ignored or filtered out in the music software I use (Max).

I'm going to focus on this LED issue for now. Then revisit the MIDI messages. I'll look at the ResponsiveAnalogRead library again.

Thank you for taking a look at this.
 
Arrays make multi channel things much easier.

Your code does check-for-change after rounding 3 bits so it's likely stable unless the voltage is very near a rounding threshold at 7 bits.

It should improve with more permanent wiring ;)
 
Hey wcalvert,

Wow this library you found is nice. And in the example he's using the same chip in the LED driver I have, TLC5947.

I will give this a try and let you know how it works out.

I was worried that I would have to re-envision this thing i'm making because I can't find a button switch that has RGB LEDs AND a Neopixel type LED in it after googleing around for an hour.

Anyway I really appreciate the input from everyone chiming in.

Thank you and I'll report back once I integrate this library into my code.
 
Hey everyone,

I am running into an issue that I can't really figure out. It seems simple though.

I downloaded this TLC5947 Library from here:

https://github.com/ramonaoptics/TLC5947

I tried to verify the example code in Arduino software v. 1.8.8 and I got error messages. Having something to do with the line describing how many chips are being used:

Code:
const uint8_t TLC5947::_tlc_count = 1;          // Change to reflect number of TLC chips

I integrated this example code into my project code and was getting the same errors. I can't quite figure this out

Here is the example code:

Code:
/*
   TLC5947 Control Library
   Used to control the TI TLC5947 LED driver chip
   Zack Phillips - zkphil@berkeley.edu
   Product Page: http://www.ti.com/product/tlc5947
   Copyright (c) 2018, Zachary F. Phillips
   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
   Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL Z. PHILLIPS BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "TLC5947.h"
#include "SPI.h"

// Pin set-up
#define GSCLK 6
#define LAT 2
#define SPI_MOSI 11
#define SPI_CLK 13

const uint8_t TLC5947::_tlc_count = 1;          // Change to reflect number of TLC chips
float TLC5947::max_current_amps = 10;      // Maximum current output, amps
bool TLC5947::enforce_max_current = false;   // Whether to enforce max current limit

// Define dot correction, pin rgb order, and grayscale data arrays in program memory
uint8_t TLC5947::_dc_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
uint8_t TLC5947::_rgb_order[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
uint16_t TLC5947::_grayscale_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];

// Create TLC5947 object
TLC5947 tlc;

void setup() {
  // Set pins (non-serial) to output mode
  pinMode(GSCLK, OUTPUT);
  pinMode(LAT, OUTPUT);

  // Adjust PWM timer for maximum GSCLK frequency
  analogWrite(GSCLK, 127);

  // The library does not ininiate SPI for you, so as to prevent issues with other SPI libraries
  SPI.begin();

  tlc.init(LAT, SPI_MOSI, SPI_CLK);

  // We must set dot correction values, so set them all to the brightest adjustment
  tlc.setAllDcData(127);

  // Set Max Current Values (see TLC5947 datasheet)
  tlc.setMaxCurrent(3, 3, 3); // Go up to 7

  // Set Function Control Data Latch values. See the TLC5947 Datasheet for the purpose of this latch.
  // Order: DSPRPT, TMGRST, RFRESH, ESPWM, LSDVLT
  tlc.setFunctionData(true, true, true, true, true);

  // set all brightness levels to max (127)
  int currentR = 127;
  int currentB = 127;
  int currentG = 127;
  tlc.setBrightnessCurrent(currentR, currentB, currentG);

  // Update Control Register
  tlc.updateControl();

  // Provide LED pin order (R,G,B)
  tlc.setRgbPinOrder(0, 1, 2);
}

void loop() {

}

Also, I might as well ask this since I am making this post. From the Adafruit board you have these pins:

LAT
OE
CLK
DIN

In this library it is asking for

GSCLK
LAT
SPI_MOSI
SPI_CLK

I am thinking LAT = LAT, SPI_CLK = CLK, SPI_MOSI = DIN and GSCLK = OE

Does that seem right? Also does it matter what pins I use on the Teensy 3.6? On the diagram of pins I see a couple labeled as MOSI.

Thanks again.

Nick
 
These two pin values match standard Teensy SPI so start with them:
#define SPI_MOSI 11
#define SPI_CLK 13

Assuming it is write only there is likely no need for MISO pin.

But for SPI bus there should be a CS pin to chip select that device to respond - given this:: tlc.init(LAT, SPI_MOSI, SPI_CLK);
> That would appear to be LAT for CS and that shouldn't require a special pin in this case - but aiming for a CS0 pin can't hurt.

Prior posts IIRC mention OE as perhaps output enable to enable/disable output power to LEDs?

With one board this should be easy. If you have more than 1 for _tlc_count = 1; - start with one - then figure out how that applies tp connections needed.
 
Hi thebigg

Ok I changed the line you specified to

Code:
 const int TLC5947::_tlc_count = 1;          // Change to reflect number of TLC chips

But now I'm getting errors further down in the code. I tried, int, const int, etc.

What do you think I should declare these other variables as? The float and the bool are fine. I'm just getting errors after that, with what I declared as const int, which isn't working.

Code:
 const int TLC5947::_tlc_count = 1;          // Change to reflect number of TLC chips
float TLC5947::max_current_amps = 10;      // Maximum current output, amps
bool TLC5947::enforce_max_current = false;   // Whether to enforce max current limit

// Define dot correction, pin rgb order, and grayscale data arrays in program memory
const int TLC5947::_dc_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
 const int TLC5947::_rgb_order[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
 const int TLC5947::_grayscale_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];

thanks, Nick
 
@nicnut - posting the error text presented can help a great deal - not seeing that in post #14 above didn't explain the problem or show there was one.

With error text in #17 it might be possible to provide help without having the library at hand.
 
Open TLC5947.h in your favourite editor and have a look...

Code:
static uint8_t _rgb_order[][LEDS_PER_CHIP][COLOR_CHANNEL_COUNT];
static uint16_t _grayscale_data[][LEDS_PER_CHIP][COLOR_CHANNEL_COUNT];

There is no _dc_data though. Seems the example is out of step with the library
 
Hi defragster,

Ok I'm going to post the original example code and the error test as well.

example:

Code:
/*
   TLC5947 Control Library
   Used to control the TI TLC5947 LED driver chip
   Zack Phillips - zkphil@berkeley.edu
   Product Page: http://www.ti.com/product/tlc5947
   Copyright (c) 2018, Zachary F. Phillips
   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
   Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL Z. PHILLIPS BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "TLC5947.h"
#include "SPI.h"

// Pin set-up
#define GSCLK 6
#define LAT 2
#define SPI_MOSI 11
#define SPI_CLK 13

const uint8_t TLC5947::_tlc_count = 1;          // Change to reflect number of TLC chips
float TLC5947::max_current_amps = 10;      // Maximum current output, amps
bool TLC5947::enforce_max_current = false;   // Whether to enforce max current limit

// Define dot correction, pin rgb order, and grayscale data arrays in program memory
uint8_t TLC5947::_dc_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
uint8_t TLC5947::_rgb_order[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
uint16_t TLC5947::_grayscale_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];

// Create TLC5947 object
TLC5947 tlc;

void setup() {
  // Set pins (non-serial) to output mode
  pinMode(GSCLK, OUTPUT);
  pinMode(LAT, OUTPUT);

  // Adjust PWM timer for maximum GSCLK frequency
  analogWrite(GSCLK, 127);

  // The library does not ininiate SPI for you, so as to prevent issues with other SPI libraries
  SPI.begin();

  tlc.init(LAT, SPI_MOSI, SPI_CLK);

  // We must set dot correction values, so set them all to the brightest adjustment
  tlc.setAllDcData(127);

  // Set Max Current Values (see TLC5947 datasheet)
  tlc.setMaxCurrent(3, 3, 3); // Go up to 7

  // Set Function Control Data Latch values. See the TLC5947 Datasheet for the purpose of this latch.
  // Order: DSPRPT, TMGRST, RFRESH, ESPWM, LSDVLT
  tlc.setFunctionData(true, true, true, true, true);

  // set all brightness levels to max (127)
  int currentR = 127;
  int currentB = 127;
  int currentG = 127;
  tlc.setBrightnessCurrent(currentR, currentB, currentG);

  // Update Control Register
  tlc.updateControl();

  // Provide LED pin order (R,G,B)
  tlc.setRgbPinOrder(0, 1, 2);
}

void loop() {

}

Error Messages:

Arduino: 1.8.8 (Mac OS X), TD: 1.45, Board: "Teensy 3.2 / 3.1, Serial, 96 MHz (overclock), Faster, US English"

TLC5947:39: error: conflicting declaration 'const uint8_t TLC5947::_tlc_count'
const uint8_t TLC5947::_tlc_count = 1; // Change to reflect number of TLC chips
^
In file included from /sequences/Arduino/libraries/TLC5947-master/examples/TLC5947/TLC5947.ino:30:0:
/sequences/Arduino/libraries/TLC5947-master/TLC5947.h:94:18: note: previous declaration as 'const int TLC5947::_tlc_count'
static const int _tlc_count; //
^
TLC5947:39: error: declaration of 'const int TLC5947::_tlc_count' outside of class is not definition [-fpermissive]
const uint8_t TLC5947::_tlc_count = 1; // Change to reflect number of TLC chips
^
TLC5947:44: error: 'uint8_t TLC5947::_dc_data [1][8][3]' is not a static data member of 'class TLC5947'
uint8_t TLC5947::_dc_data[TLC5947::_tlc_count][TLC5947::LEDS_PER_CHIP][TLC5947::COLOR_CHANNEL_COUNT];
^
TLC5947: In function 'void setup()':
TLC5947:62: error: no matching function for call to 'TLC5947::init(int, int, int)'
tlc.init(LAT, SPI_MOSI, SPI_CLK);
^
In file included from /sequences/Arduino/libraries/TLC5947-master/examples/TLC5947/TLC5947.ino:30:0:
/sequences/Arduino/libraries/TLC5947-master/TLC5947.h:56:6: note: candidate: void TLC5947::init(int8_t, int8_t, uint8_t, uint8_t, uint8_t)
void init(int8_t num_latches, int8_t num_tlc_one_row, uint8_t spi_mosi, uint8_t spi_clk, uint8_t blank);
^
/sequences/Arduino/libraries/TLC5947-master/TLC5947.h:56:6: note: candidate expects 5 arguments, 3 provided
TLC5947:65: error: 'class TLC5947' has no member named 'setAllDcData'
tlc.setAllDcData(127);
^
TLC5947:68: error: 'class TLC5947' has no member named 'setMaxCurrent'
tlc.setMaxCurrent(3, 3, 3); // Go up to 7
^
TLC5947:72: error: 'class TLC5947' has no member named 'setFunctionData'
tlc.setFunctionData(true, true, true, true, true);
^
TLC5947:81: error: 'class TLC5947' has no member named 'updateControl'
tlc.updateControl();
^
conflicting declaration 'const uint8_t TLC5947::_tlc_count'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

To thebigg: Yes I tried every different combination of variables and nothing seemed to work. Something is off or missing.

Thank you everyone for taking a look.

Nick

EDIT:

I posted about this error on the github. I got this message from someone on there:

"Yeah... This library isn't exactly stable.

Trust us that it works, just that the example was not kept up to date.
We made some bad decisions in terms of the hardware design that cause this code to be more complicated than it should be."
 
Last edited:
Hey everyone,

I'm still working on this issue. I am giving up on that library above for now because I can't get it the example code to compile.

I did find a thread on this forum which is giving me hope, and is basically the exact same problem I am facing:

https://forum.pjrc.com/threads/42214-Need-help-on-using-SPI-library

This person altered the library from Adafruit and is able to use it with SPIwrite()

I uploaded their altered library and tried running their test code but it's not working for me.

Here is their version of the library with the alterations. You need the #include <Adafruit_TLC5947.h> file.


https://forum.pjrc.com/attachment.php?attachmentid=9831&d=1488089542




I did alter their test code so that it reflects what is suggested in the thread. Namely:

Code:
void setup() { 


  pinMode(latch, OUTPUT);
  digitalWrite(latch, LOW);
  pinMode(clock, OUTPUT);
  digitalWrite(clock, LOW);
  pinMode(data, OUTPUT);
  digitalWrite(data, LOW);
    /*
    SPI.setCS(10);
    SPI.setMOSI(11);
    SPI.setSCK(13);*/
  SPI.begin();
  //tlc.begin();
 Serial.begin(38400);
 delay(1000);
 Serial.println("TLC5974_SPI test");
}

I am wondering if it is because I need to use different pins for latch, clock, data and oe.

I am using a Teensy 3.6 with these pins:

Code:
const int slaveSelectPin = 29;
#define clock 30 // 10 
#define data 28
#define oe  27  //  12
#define latch  29 // 11
#define NUM_TLC5974 10

Here is all the test code I am using. Nothing is happening when I run it. I know everything is connected correctly because the tlc.write() version of this code is working.

Any suggestions on what I can try to make this work with SPIwrite() ?

Code:
#include <Adafruit_TLC5947.h>
#include <SPI.h>

const int slaveSelectPin = 29;
#define clock 30 // 10 
#define data 28
#define oe  27  //  12
#define latch  29 // 11
#define NUM_TLC5974 10

unsigned long frame;
Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch,  oe);
unsigned long tick, dur;

void setup() { 


  pinMode(latch, OUTPUT);
  digitalWrite(latch, LOW);
  pinMode(clock, OUTPUT);
  digitalWrite(clock, LOW);
  pinMode(data, OUTPUT);
  digitalWrite(data, LOW);
    /*
    SPI.setCS(10);
    SPI.setMOSI(11);
    SPI.setSCK(13);*/
  SPI.begin();
  //tlc.begin();
 Serial.begin(38400);
 delay(1000);
 Serial.println("TLC5974_SPI test");
}

void loop() {
  //////
  tick = micros();
  colorWipe(100, 0, 0); // "Red" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  red used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(0, 100, 0); // "Green" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  green used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(0, 0, 100); // "Blue" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  blue used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(5, 5, 5); // "Blue" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  white used");
  Serial.println(" us");
}

void colorWipe(uint16_t r, uint16_t g, uint16_t b) {
  for (uint16_t i = 0; i < 8 * NUM_TLC5974; i++) {
    tlc.setLED(i, r, g, b);
  }
  SPIwrite();
}


void SPIwrite() {
#define TSPEED 1000000 //1Mhz
  unsigned int chan1 = 0;
  unsigned int chan2 = 0;
  byte address1 = 0;
  byte address2 = 0;
  byte address3 = 0;
  SPISettings TLC5947(TSPEED , MSBFIRST, SPI_MODE0);
  // packing each 2 channel (12bit*2) to 3 byte (8bit*3) for transfering
  SPI.beginTransaction(TLC5947);
  // digitalWriteFast(latch, HIGH);
  digitalWriteFast(latch, LOW);
  for (unsigned int ledpos = 24  * NUM_TLC5974 ; ledpos > 0; ledpos = ledpos - 2) {
    chan1 = tlc.getCHAN(ledpos - 1);
    chan2 = tlc.getCHAN(ledpos - 2);
    address1 = (byte)(chan1 >> 4) ;
    address2 = (byte)((chan1 << 4) & (B11110000)) + (byte)((chan2 >> 8) & (B00001111));
    address3 = (byte)chan2;
    /* address1 = B00000000;
      address2 = B00000000;
      address3 = B00000000;*/
    SPI.transfer(address1);
    SPI.transfer(address2);
    SPI.transfer(address3);
  }

  SPI.endTransaction();
  //  digitalWriteFast(latch, LOW);
  digitalWriteFast(latch, HIGH);
  digitalWriteFast(latch, LOW);
  digitalWriteFast(clock, LOW);
}
 
Looking at a Teensy Card it indicates the hardware pins for the busses - for SPI hardware usage the appropriate pins or alternates need to be used. As shown in post #15

These are specified for a reason, not sure if they are not available? But if not those pins then acceptable alternates must be selected for function:
/*
SPI.setCS(10);
SPI.setMOSI(11);
SPI.setSCK(13);*/
 
I just bought a TLC5947 board, I will get it working when I have time, unless someone beats me to it. Maybe this weekend?
 
defragster,

thank you for your help. I changed the pins and tried the test patch again. No luck :(

I tried it with

Code:
const int slaveSelectPin = 10;
#define clock 13 // 10 
#define data 11
#define oe  12  //  12
#define latch  10 // 11
#define NUM_TLC5974 5

and

Code:
const int slaveSelectPin = 11;
#define clock 10 // 10 
#define data 13
#define oe  12  //  12
#define latch  11 // 11
#define NUM_TLC5974 5



I put the full example code below. Hm, I don't know what else to try. I'm pretty sure the hardware is set up correctly..


Code:
#include <Adafruit_TLC5947.h>
#include <SPI.h>

const int slaveSelectPin = 10;
#define clock 13 // 10 
#define data 11
#define oe  12  //  12
#define latch  10 // 11
#define NUM_TLC5974 5

unsigned long frame;
Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch,  oe);
unsigned long tick, dur;

void setup() { 


  pinMode(latch, OUTPUT);
  digitalWrite(latch, LOW);
  pinMode(clock, OUTPUT);
  digitalWrite(clock, LOW);
  pinMode(data, OUTPUT);
  digitalWrite(data, LOW);
    /*
    SPI.setCS(10);
    SPI.setMOSI(11);
    SPI.setSCK(13);*/
  SPI.begin();
  //tlc.begin();
 Serial.begin(38400);
 delay(1000);
 Serial.println("TLC5974_SPI test");
}

void loop() {
  //////
  tick = micros();
  colorWipe(100, 0, 0); // "Red" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  red used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(0, 100, 0); // "Green" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  green used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(0, 0, 100); // "Blue" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  blue used");
  Serial.println("  us");
  delay(300);
  //////
  tick = micros();
  colorWipe(5, 5, 5); // "Blue" (depending on your LED wiring);
  Serial.print((micros() - tick));
  Serial.print("  white used");
  Serial.println(" us");
}

void colorWipe(uint16_t r, uint16_t g, uint16_t b) {
  for (uint16_t i = 0; i < 8 * NUM_TLC5974; i++) {
    tlc.setLED(i, r, g, b);
  }
  SPIwrite();
}


void SPIwrite() {
#define TSPEED 1000000 //1Mhz
  unsigned int chan1 = 0;
  unsigned int chan2 = 0;
  byte address1 = 0;
  byte address2 = 0;
  byte address3 = 0;
  SPISettings TLC5947(TSPEED , MSBFIRST, SPI_MODE0);
  // packing each 2 channel (12bit*2) to 3 byte (8bit*3) for transfering
  SPI.beginTransaction(TLC5947);
  // digitalWriteFast(latch, HIGH);
  digitalWriteFast(latch, LOW);
  for (unsigned int ledpos = 24  * NUM_TLC5974 ; ledpos > 0; ledpos = ledpos - 2) {
    chan1 = tlc.getCHAN(ledpos - 1);
    chan2 = tlc.getCHAN(ledpos - 2);
    address1 = (byte)(chan1 >> 4) ;
    address2 = (byte)((chan1 << 4) & (B11110000)) + (byte)((chan2 >> 8) & (B00001111));
    address3 = (byte)chan2;
    /* address1 = B00000000;
      address2 = B00000000;
      address3 = B00000000;*/
    SPI.transfer(address1);
    SPI.transfer(address2);
    SPI.transfer(address3);
  }

  SPI.endTransaction();
  //  digitalWriteFast(latch, LOW);
  digitalWriteFast(latch, HIGH);
  digitalWriteFast(latch, LOW);
  digitalWriteFast(clock, LOW);
}
 
@wcalvert it works easily with the Adafruit example code and software SPI. It's just slower.

I hope I beat you to it, I've been at this for weeks now! lol
 
Status
Not open for further replies.
Back
Top