Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Help with SPI and Adafruit TLC59711 RGB LED board with Teensy Audio

  1. #1
    Junior Member
    Join Date
    Mar 2019
    Posts
    5

    Help with SPI and Adafruit TLC59711 RGB LED board with Teensy Audio

    Hi

    I am trying to run my Teensy 3.6 using both the Teensy Audio board and an Adafruit TLC59711 12 channel SPI RGB LED board. I want to be able to easily pulse the LEDs in sync with the music using the features of the Teensy's great audio system design tool. However I am struggling to get the Adafruit TLC59711 to work properly.

    Since I am using the teensy audio shield I cannot use the SPI0 pins or the default SPI1 pins. So I have tried to use the alternative SPI1 pins (eventually I'll use the SPI2 pins on the back) -but it won't work using those pins.

    I can get it to work using software SPI -using pins 36 (data) and 35 (clock) but I can't using pins 20 & 21. Here is the code -it's basically the adafruit example but with the pins changed. RGB.h.

    I think part of my problem is that I don't really know how to 'begin' SPI1 or SPI2, also I'm wondering if the Adafruit_TLC59711 library hardcodes for use of SPI0 or software SPI -but I can't check as my coding skills are way too limited.

    I have seen that you can use commands such as ' SPI.setMOSI(pin)' to change the default pin to an alternative, and I'm guessing I can use 'SPI1.begin' to start the SPI1 channel. However I don't know where to add them into the code -as I don't understand why the example code doesn't include an SPI.begin line at all? Does the library kick off it's own software SPI channel using the pins that are defined in my code? So it works when I define generic pins (35, 36) but conflicts with the hardware SPI1 when I set it to use those pins?

    Also, one further observation -when I upload this code it disables the USB serial. Why would it do that? How do I stop it doing that?

    Can anyone point me in the right direction?

  2. #2
    Junior Member
    Join Date
    Mar 2019
    Posts
    5
    Bump
    Can no one help?
    Any guidance on even a little bit would be appreciated.
    Thanks

  3. #3
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    5,605
    I don't know this board - if it is SPI, you use the pins mentioned for the ili9341 (spi) display on this page: https://www.pjrc.com/store/display_ili9341.html
    ("Usage with Audio Board Connections")

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,088
    Quote Originally Posted by Tenumen View Post
    I have seen that you can use commands such as ' SPI.setMOSI(pin)' to change the default pin to an alternative,
    This is probably the right path.

    Look at the audio library WavFilePlayer example. It uses a SD card over SPI (in 2 of the 3 ways to configure). Using Adafruit's library should be similar. Configure the pins before you begin their lib, and then it should do the SPI access on those pins. Simple, right?


    and I'm guessing I can use 'SPI1.begin' to start the SPI1 channel.
    This is probably *NOT* the best way.


    However I don't know where to add them into the code
    Unless Adafruit designed their library to allow selecting a different SPI port, this would be a difficult path. You'd have to dig deep into Adafruit's library. Not simple or easy.

    Lately Adafruit has been designing many of their libs to use different I2C ports. But with SPI, normally they give you the choice between the main SPI port or slower software bitband on any pins, but not SPI1, SPI2, etc. Maybe they will someday start designing for different hardware SPI ports, but as things are now, using SPI1 with their libs is a painful path.


    -as I don't understand why the example code doesn't include an SPI.begin line at all?
    Generally, most libraries which use SPI tend to do a SPI.begin() for you within their code.

    But this is only a general rule which can have exceptions. It all depends on the specific design of whatever lib you're using. Most of Adafruit's libs have a similar design... but keep in mind you are asking questions about a specific library that we don't necessarily know (and I don't see any links to the code in these messages)


    Also, one further observation -when I upload this code it disables the USB serial. Why would it do that?
    Anything that interferes with the USB port can prevent Teensy from responding to the automatic reboot request. Every Teensy has the program pushbutton so you can recover from that situation, of course with the slight inconvenience of having to press the button.

    While there are many ways to mess up the USB, the most most common are leaving interrupts disabled and buffer overflow mistakes in code your code (or the libraries - though that's not common) which overwrite memory needed for the USB packets or other USB details.



    Can anyone point me in the right direction?
    Hopefully the helped?

    If you'd like us to look briefly at this Adafruit library, please give us a link directly to its github repository. Also tell us exactly which of its examples you're using, or show us your code... or better, a small version of your code that you've double-checked really does demonstrate the issue. Don't make us try to guess which code you're really using.

  5. #5
    Junior Member
    Join Date
    Mar 2019
    Posts
    5
    Great, thanks for the input
    I'll work on this a bit more and prepare something more detailed.

  6. #6
    Junior Member
    Join Date
    Mar 2019
    Posts
    5
    So, i've had a look in the adafruit library (github here https://github.com/adafruit/Adafruit_TLC59711) and I have found out where it starts SPI so I went through everywhere to change SPI to SPI1 -as follows:

    Code:
    /*************************************************** 
      This is a library for our Adafruit 24-channel PWM/LED driver
    
      Pick one up today in the adafruit shop!
      ------> http://www.adafruit.com/products/1455
    
      These drivers uses SPI to communicate, 3 pins are required to  
      interface: Data, Clock and Latch. 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>
    
    Adafruit_TLC59711::Adafruit_TLC59711(uint8_t n, uint8_t c, uint8_t d) {
      numdrivers = n;
      _clk = c;
      _dat = d;
    
      BCr = BCg = BCb = 0x7F;
    
      pwmbuffer = (uint16_t *)calloc(2, 12*n);
    }
    
    Adafruit_TLC59711::Adafruit_TLC59711(uint8_t n) {
      numdrivers = n;
      _clk = -1;
      _dat = -1;
    
      SPI1.setBitOrder(MSBFIRST);
    #ifdef __arm__
      SPI1.setClockDivider(42);
    #else
      SPI1.setClockDivider(SPI_CLOCK_DIV8);
    #endif
      SPI1.setDataMode(SPI_MODE0);
      BCr = BCg = BCb = 0x7F;
    
      pwmbuffer = (uint16_t *)calloc(2, 12*n);
    }
    
    void  Adafruit_TLC59711::spiwriteMSB(uint32_t d) {
    
      if (_clk >= 0) {
        uint32_t b = 0x80;
        //  b <<= (bits-1);
        for (; b!=0; b>>=1) {
          digitalWrite(_clk, LOW);
          if (d & b)  
    	digitalWrite(_dat, HIGH);
          else
    	digitalWrite(_dat, LOW);
          digitalWrite(_clk, HIGH);
        }
      } else {
        SPI1.transfer(d);
      }
    }
    
    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 <<= 7;
      command |= BCr;
    
      command <<= 7;
      command |= BCg;
    
      command <<= 7;
      command |= BCb;
    
      noInterrupts();
      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);
      interrupts();
    }
    
    
    
    void Adafruit_TLC59711::setPWM(uint8_t chan, uint16_t pwm) {
      if (chan > 12*numdrivers) return;
      pwmbuffer[chan] = pwm;  
    }
    
    
    void Adafruit_TLC59711::setLED(uint8_t lednum, uint16_t r, uint16_t g, uint16_t b) {
      setPWM(lednum*3, r);
      setPWM(lednum*3+1, g);
      setPWM(lednum*3+2, b);
    }
    
    
    boolean Adafruit_TLC59711::begin() {
      if (!pwmbuffer) return false;
    
      if (_clk >= 0) {
        pinMode(_clk, OUTPUT);
        pinMode(_dat, OUTPUT);
      } else {
        SPI1.begin();
      }
      return true;
    }
    I then call the library using this code:
    Code:
    #include "Adafruit_TLC59711.h"
    #include <SPI.h>
    
    // How many boards do you have chained?
    #define NUM_TLC59711 1
    
    #define data   21
    #define clock  20
    
    Adafruit_TLC59711 tlc = Adafruit_TLC59711(NUM_TLC59711, clock, data);
    
    void setup() {
      SPI1.setMOSI(21);
      SPI1.setSCK(20);
      Serial.begin(9600);
      Serial.println("TLC59711 test");
      tlc.begin();
      tlc.write();
    }
    
    void loop() {
      colorWipe(65535, 0, 0, 100); // "Red" (depending on your LED wiring)
      delay(200);
      colorWipe(0, 65535, 0, 100); // "Green" (depending on your LED wiring)
      delay(200);
      colorWipe(0, 0, 65535, 100); // "Blue" (depending on your LED wiring)
      delay(200);
      Serial.println("colourwipe complete");
    }
    
    // Fill the dots one after the other with a color
    void colorWipe(uint16_t r, uint16_t g, uint16_t b, uint8_t wait) {
      for(uint16_t i=0; i<8*NUM_TLC59711; i++) {
          tlc.setLED(i, r, g, b);
          tlc.write();
          delay(wait);
      }
    }
    Unfortunately this doesn't work. I get an error saying Error compiling for board Teensy 3.6.

    I am a bit stumped.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,088
    Maybe the bottom console area of the Arduino window has more info about the error, like which file and the line number within that file where the error is?

    By default that bottom section is small. You can drag the divider between the sections to make it bigger. You may need to scroll up to see the actual info about the error.

  8. #8
    Junior Member
    Join Date
    Mar 2019
    Posts
    5
    Well things are progressing. I think yesterday's issues were due to me messing up multiple instances of the libraries. A clean install has fixed the issues and the code now runs. LED lights won't work yet but the code runs -so I think I need to spend a bit more time to see whats happening.
    Thanks for your help getting me this far.

  9. #9
    Junior Member
    Join Date
    Dec 2017
    Posts
    2
    Any progress on this issue yet? I'm running into a similar issue with the tlc59711 chip and teensy 3.6. I am able to run a successful code using pins 7(data) and 27(clock) with real time audio processing and 16-bit LED output at the same time, but I do this using two separate power supplies to run the teensy (5V) and LED strips and driver (12V). My issue is when trying to power both teensy and tlc59711 on one power supply (12v power supply EPS-65S-12 with a LM2576 5V regulator) I get really a bad flickering with any RGB values between 4000-4500 and no visible light below 4000. I haven't done any configuring to the pins other than assign them with Adafruit_TLC59711(NUM_TLC59711, TLC_CLOCK, TLC_DATA);.... perhaps more configuring is needed?



    I also use the same 12v power supply EPS-65S-12 to test the Adafruit example code and I run into the same flickering issue (see below):




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

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

    //#define data 17
    //#define clock 16
    #define data 7
    #define clock 27

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

    int ledNum = 5000;
    int ledFadeAmount = 1;

    void setup() {
    Serial.begin(9600);

    Serial.println("TLC59711 test");
    pinMode(10, OUTPUT);
    tlc.begin();
    tlc.write();

    }

    void loop() {
    tlc.setPWM(0, 0);
    tlc.setPWM(1, 0);
    tlc.setPWM(2, ledNum);

    tlc.setPWM(3, 0);
    tlc.setPWM(4, 0);
    tlc.setPWM(5, ledNum);

    tlc.write();

    ledNum = ledNum + ledFadeAmount;

    if (ledNum <= 0 || ledNum >= 5000)
    {
    ledFadeAmount = -ledFadeAmount;
    }
    Serial.println(ledNum);
    delay(100);

    }
    Last edited by sHorist; 04-18-2019 at 04:47 AM. Reason: Need to add code example

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •