1

I am attempting to use 3 x TLC5917 chips to drive a row of LEDs in PWM. The LEDs share a common anode being powered through a transistor, with each LEDs cathode going to pins on the TLC5917 Chips.

There are obviously other chips specifically designed for PWM but my questions relate to the Arduino SPI Implementation.

The chips I am using are rated for 30MHz Max Speed. The Arduino (Uno) I am using runs at 16MHz. SPI can only run at half speed which means the SPI Transfer Max Speed for this hardware is 8MHz.

With this in mind, before overhead it should take 1/8Million seconds per clock cycle, equivalent to 1/8th of a Microsecond. This means that SPI should take 24 clock cycles to send out 24 bits. Clocking out all 3 bytes (24 bits) should take about 3 Microseconds before overhead. Then a few more microseconds to flip the latch pin.

Instead I see it taking about 12 Microseconds to send the 24 bits and another 12 Microseconds to latch the pin low and high, 4 times what I expected. Obviously there is some overhead but 400% seems excessive.

I have looked at the Arduino SPI Library to see if there is any obvious overhead but I cant see anything that would quadruple the theoretical transfer time.

This is the sketch I used to time the data transfers

#include <SPI.h>

void SSHigh(){
  PORTB = PORTB | 10000000;
}

void SSLow(){
  PORTB = PORTB ^ 10000000;
}

void setup() {
   SPI.begin();
   Serial.begin(9600);
   pinMode(2, OUTPUT);
   digitalWrite(2, LOW);
}

void writeChips(byte red, byte green, byte blue){
    SPI.transfer(blue);
    SPI.transfer(green);
    SPI.transfer(red);  

}

long start;
long end;
long delta;

void loop() {

  start = micros();
  writeChips(B11000110,B01110010,B00011110);
  end = micros();
  delta = end - start;
  Serial.println(delta);


}
  • There is always overhead, since the UNO doesn't have DMA. So it's waiting for the transfer the be completed, before it can send new data. This checking takes a few cycles, and doesn't always neatly align with the exact moment the transfer is done. There might also be overhead from the function call, and the return value, but the compiler might inline all the code. It might be useful to look at the compiled assembly code, to see what's going on. – Gerben Sep 25 '18 at 10:01
  • Is there any way we can meaningfully reduce the overhead without having access to DMA? – Zano Sep 25 '18 at 10:05
  • You could not use the SPI library. But I'm not sure if this would help, as I wouldn't be surprised if the compiler already optimized the code. Also note that the calling micros and storing it's value takes some time, so your results are already off by a bit. – Gerben Sep 25 '18 at 10:10
  • I'm also not sure how you are going to use this in driving the leds, as you'd need some additional code to do the pretty animations. Do you plan on updating the leds in a timer interrupt? What framerate are you striving for, and how many bit of PWM (how many different brightnesses)? – Gerben Sep 25 '18 at 10:13
  • 1
    Crap, your right. Setting it to DIV_2 bring it down to about 8 Microseconds. The rest must be overhead. – Zano Sep 25 '18 at 10:38

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.