Looking for Library that uses hardware SPI to control TLC5947 chip

Hi,

I am making a midi controller, using a Teensy 3.6. I am trying to implement a bunch of button swithces with RGB LEDs in them.

To control the LEDs I am using this breakout board from Adafruit:

This board has a TLC5947 chip in it.

When I add the example code from Adafruit to use this board the timing of things get off. I learned that this is because the Adafruit library to use this board uses software SPI, which apparently has some interrupts in it.

I made a video to illustrate what I am talking about:

I was told I need to find a library, or way to use the hardware SPI on the Teensy.

Does anyone know of a library that uses hardware SPI to send messages to a TLC5947 chip?

Or some example code I can adapt to my situation?

Thank you.

Did you copy the colorWipe and rainbowCycle example code from the library demo program?
If so, did you set the 'wait' parameter to zero?
If not, then you will see delays as per the numeric setting of the 'wait' parameter.

Hi mikb55

no i didn’t use that colorWipe or rainbow stuff. I’m not going to use those because all I am doing is turning on individual LEDs. THey will all act independently. But they will be all getting messages and I’d like them to respond as soon as possible.

I’m going to post my code. If you look in myControlChange() you will see the code that turns on and off the LEDs.

But I really don’t think it’s my code. I could be wrong, but I think it’s because it’s not hardware SPI.

Anyway let me know what you think or if you notice something.

I had to delete a lot of the code that deals with the LEDs becuase it’s too long for this forum. It’s at the bottom.

#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   18     // digital pins on the Teensy
#define clock   19
#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);

// the MIDI channel number to send messages
const int channel = 1;
const int MIDIchannel = 1;   // this will only apply to midi channel 1


// the MIDI continuous controller for each analog input
const int controllerA0 = 1; //  control change 1, ribbon
const int controllerA1 = 2; //control change 2
const int controllerA2 = 3; //control change 3
const int controllerA3 = 4; // control change 4
const int controllerA4 = 5; // control change 5
const int controllerA5 = 6; // control change 6
const int controllerA6 = 7; // control change 7
const int controllerA7 = 8; // control change 8
const int controllerA8 = 9; // control change 9  last ribbon
const int controllerA9 = 10; // control change 10 joystick
const int controllerA10 = 11; // joystick
const int controllerA11 = 12; // control change 12
const int controllerA12 = 13; // control change 13  joystick

const int controllerD14 = 14; // toggle, control change 14
const int controllerD15 = 15; //  Button, control change 15
const int controllerD16 = 16; //
const int controllerD17 = 17;
const int controllerD18 = 18;  //
const int controllerD19 = 19;
const int controllerD20 = 20;
const int controllerD21 = 21;
const int controllerD22 = 22;
const int controllerD23 = 23;
const int controllerD24 = 24;
const int controllerD25 = 25;
const int controllerD26 = 26;
const int controllerD27 = 27;




// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5);  // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5);  // to rapid touch, you can
Bounce button7 = Bounce(7, 5);  // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
Bounce button12 = Bounce(12, 5);  // goes out of order because other pins double as analog inputs

Bounce button24 = Bounce(24, 5);
Bounce button25 = Bounce(25, 5);
Bounce button26 = Bounce(26, 5);
Bounce button27 = Bounce(27, 5);


const int ledcontroller15 = 15;    // midi control change 15
const int ledcontroller16 = 16;    // midi control change 16
const int ledcontroller17 = 17;    // midi control change 15
const int ledcontroller18 = 18;    // midi control change 16
const int ledcontroller19 = 19;    // midi control change 15
const int ledcontroller20 = 20;    // midi control change 16
const int ledcontroller23 = 23;    // midi control change 16

const int numMatrixControllers = 5;
const int firstMatrixController = 76;



Adafruit_7segment matrix = Adafruit_7segment();

Adafruit_8x16matrix matrix2 = Adafruit_8x16matrix();

void setup() {


  tlc.begin();




  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);


  usbMIDI.setHandleControlChange(myControlChange);
  setupLedDisplays();


}

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 (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 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);
    }

   


  }

  // 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
  }
}



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();



}

Load the dtlc5947test.ino demo.
Set the waits to zero.
Remove the delays.
Time the loop().
How long in microseconds or milliseconds does each loop take?

Hi mikb55,

It's a little hard for me to time it because I have no idea when it starts.

It looks almost the same if I make wait = 0; and if I make all the delays(0);

When the delay is delays(0); it seems like the color wipe isn't as coordinated. But other than that hard to see a differince.

I did find this example code:

which might be what I need. I uses hardware spi and I don't need addressable LEDs, like neopixels. I'm going to try this out.

Before you go chasing perceived speed problems, first you need to be able to time things using code, not your eyes.

The basic pattern is

unsigned long starttime = millis();

// do something that you think is taking too long

unsigned long endtime = millis();
Serial.print("elapsed time = ");
Serial.println(endtime - starttime);

If you get a result of zero then you need to replace millis() with micros().

mikb55 Ok i'll try it out.

The speed problems are more when I do a lot of commands an once, not just one command.

But i can probably make up a test where each LED turns on twice and time that. Or something similar.

thank you.