Problems while using tlc5940 + uno + 6 digit 7 segment display

Hi, so i have the following issue.

When driving the 7 segment display the tlc takes about a millisecond to change the channels which seems waaay too long, especially since the data sheet of the tlc touts a 30mhz data rate. How did i notice the problem?: Well unless i change the delayMicroseconds(value) line to value = 1000 the number that is displayed on the previous digit is also displayed on the next digit for a short while. Does anybody know why tlc5940 might be so slow to do anything or even how i can fix it?

Code:

< /* Atmega328p based speedometer
    written by 
    updated last:
    19.05.21
*/

#include "FRAM.h"
#include "SparkFun_Tlc5940.h"
#include <FastLED.h>
#define NUM_LEDS 23
#define DATA_PIN 8
#include <stdlib.h>
// Define the array of leds
CRGB leds[NUM_LEDS];

FRAM fram;
uint32_t start;
uint32_t stop;

const static uint8_t kmA = 8;
const static uint8_t kmB = 9;
const static uint8_t kmC = 10;
const static uint8_t kmD = 11;
const static uint8_t kmE = 12;
const static uint8_t kmF = 13;
const static uint8_t kmG = 14;
const static uint8_t kmDP = 15;

const static uint8_t kphA = 0;
const static uint8_t kphB = 1;
const static uint8_t kphC = 2;
const static uint8_t kphD = 3;
const static uint8_t kphE = 4;
const static uint8_t kphF = 5;
const static uint8_t kphG = 6;
const static uint8_t kphDP = 7;

const static uint8_t kmPin0 = 0;
const static uint8_t kmPin1 = 1;
const static uint8_t kmPin2 = 4;
const static uint8_t kmPin3 = 5;
const static uint8_t kmPin4 = 6;
const static uint8_t kmPin5 = 7;
const static uint8_t kmPins[6] = {0, 1, 4, 5, 6, 7};

const static uint8_t kphPin0 = A1;
const static uint8_t kphPin1 = A2;
const static uint8_t kphPin2 = A3;
const static uint8_t kphPins[6] = {A1, A2, A3};

const static uint8_t buttonPin = 12;
const static uint8_t pulseInputPin = 2;
const static uint8_t dimPin = A0;

//don't use the next 10 adresses after these
const static uint8_t kmstandAddress = 0x60;
const static uint8_t kmstandAddressBackup = 0x70;
const static uint8_t pulsesAddress = 0x80;
const static uint8_t pulsesAddressBackup = 0x90;

//value from 0 to 4095
int brightness = 4000;
int r = 255;
int g = 255;
int b = 255;
int kph = 0;
int kphString[3];
int kmDigit = 0;
int kphDigit = 0;
int shortpresses = 0;
int longpresses = 0;

uint32_t kmstand = 0;
int kmstandString[6];
uint32_t kmstandBackup = 0;
int pulsecounter = 0;
int pulsesPerKm = 0;

float dimFactor = 0.3;

unsigned long timer = 0;
unsigned long last_timer = 0;
unsigned long debouncer_timer = 0;
unsigned long pressstart = 0;
unsigned long tenPulseTimer = 0;
unsigned long digitTimer = 0;
unsigned long pressTimer = 0;

boolean displaychange = false;
boolean debouncer = false;
boolean pressactivated = false;
boolean longpress = false;
boolean shortpress = false;
boolean calibrationActivated = false;
boolean menuactivated = false;
int t2 = 0;
int t1 = 0;

void display_all(int kphData[3], int kmData[6]) {
  /*
    kmData[0] = 1;
    kmData[1] = 2;
    kmData[2] = 3;
    kmData[3] = 4;
    kmData[4] = 5;
    kmData[5] = 6;
    kmData[6] = "\0";

    kphData[0] = 5;
    kphData[1] = 0;
    kphData[2] = "\0";*/
  if(kphDigit == 0){
    t1 = 2;
  } else {
    t1 = kphDigit - 1;
  }
  if(kmDigit == 0){
    t2 = 5;
  } else {
    t2 = kmDigit - 1;
  }
  digitalWrite(kphPins[t1], HIGH);
  digitalWrite(kmPins[t2], HIGH);
  Tlc.clear();

  if (kphData[0] == 0) {
    kphData[0] = 99;
    if (kphData[1] == 0) {
      kphData[1] = 99;
    }
  }

  if (kmData[0] == 0) {
    kmData[0] = 99;
    if (kmData[1] == 0) {
      kmData[1] = 99;
      if (kmData[2] == 0) {
        kmData[2] = 99;
        if (kmData[3] == 0) {
          kmData[3] = 99;
          if (kmData[4] == 0) {
            kmData[4] = 99;
            if (kmData[5] == 0) {
              kmData[5] = 99;
            }
          }
        }
      }
    }
  }
  
  int value[2];
  value[0] = kphData[kphDigit];
  value[1] = kmData[kmDigit];

  switch (value[0]) {
    case 0:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphF, brightness);
      break;
    case 1:
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      break;
    case 2:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphG, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphD, brightness);
      break;
    case 3:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphG, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      break;
    case 4:
      Tlc.set(kphC, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphG, brightness);
      Tlc.set(kphF, brightness);
      break;
    case 5:
      Tlc.set(kphA, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphG, brightness);
      Tlc.set(kphF, brightness);
      break;
    case 6:
      Tlc.set(kphA, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphF, brightness);
      Tlc.set(kphG, brightness);
      break;
    case 7:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      break;
    case 8:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphF, brightness);
      Tlc.set(kphG, brightness);
      break;
    case 9:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphF, brightness);
      Tlc.set(kphG, brightness);
      break;
    case 10:
      Tlc.set(kphA, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphD, brightness);
      Tlc.set(kphF, brightness);
      break;
    case 11:
      Tlc.set(kphA, brightness);
      Tlc.set(kphB, brightness);
      Tlc.set(kphC, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphF, brightness);
      Tlc.set(kphG, brightness);
      break;
    case 12:
      Tlc.set(kphF, brightness);
      Tlc.set(kphE, brightness);
      Tlc.set(kphD, brightness);
      break;
  }

  switch (value[1]) {
    case 0:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      Tlc.set(kmE, brightness);
      Tlc.set(kmF, brightness);
      break;
    case 1:
      Tlc.set(kmB, brightness);
      Tlc.set(kmC, brightness);
      break;
    case 2:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmG, brightness);
      Tlc.set(kmE, brightness);
      Tlc.set(kmD, brightness);
      break;
    case 3:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmG, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      break;
    case 4:
      Tlc.set(kmC, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmG, brightness);
      Tlc.set(kmF, brightness);
      break;
    case 5:
      Tlc.set(kmA, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      Tlc.set(kmG, brightness);
      Tlc.set(kmF, brightness);
      break;
    case 6:
      Tlc.set(kmA, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      Tlc.set(kmE, brightness);
      Tlc.set(kmF, brightness);
      Tlc.set(kmG, brightness);
      break;
    case 7:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmC, brightness);
      break;
    case 8:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      Tlc.set(kmE, brightness);
      Tlc.set(kmF, brightness);
      Tlc.set(kmG, brightness);
      break;
    case 9:
      Tlc.set(kmA, brightness);
      Tlc.set(kmB, brightness);
      Tlc.set(kmC, brightness);
      Tlc.set(kmD, brightness);
      Tlc.set(kmF, brightness);
      Tlc.set(kmG, brightness);
      break;
  }

  Tlc.update();
  delayMicroseconds(900);
  digitalWrite(kphPins[kphDigit], LOW);
  digitalWrite(kmPins[kmDigit], LOW);

  kphDigit++;
  if (kphDigit >= 3) {
    kphDigit = 0;
  }
  kmDigit++;
  if (kmDigit >= 6) {
    kmDigit = 0;
  }
}


void calibrationMode() {
  kphString[0] = 10;
  kphString[1] = 11;
  kphString[2] = 12;
  display_all(kphString, kmstandString);
  if (longpress) {
    pulsesPerKm = pulsecounter;
    fram.write16(pulsesAddress, pulsecounter);
    fram.write16(pulsesAddressBackup, pulsecounter);
    calibrationActivated = false;
  }
}

void setup() {

  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);  // GRB ordering is assumed

  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);

  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  dimFactor = analogRead(dimPin) / 1024;

  //start and check fram
  Wire.begin();
  int rv = fram.begin(0x50);
  uint8_t test = fram.read8(0x50);
  if (test != 0) {
    leds[0] = CRGB::Red;
    FastLED.show();
    delay(100);
    FastLED.clear();
    FastLED.show();
  }

  //read out kmstand from fram
  kmstand = fram.read32(kmstandAddress);
  //test
  if (kmstand == 0) {
    kmstand = 123456;
  }
  kmstandBackup = fram.read32(kmstandAddressBackup);

  pulsesPerKm = fram.read16(pulsesAddress);
  int temp = fram.read16(pulsesAddressBackup);

  //compare normal value to backup value
  if (kmstand != kmstandBackup) {
    leds[1] = CRGB::Red;
    FastLED.show();
    delay(100);
    FastLED.clear();
    FastLED.show();
  }

  if (temp != pulsesPerKm) {
    leds[2] = CRGB::Red;
    FastLED.show();
    delay(100);
    FastLED.clear();
    FastLED.show();
  }

  //Interrupt catches signals from transmission
  attachInterrupt(0, pulsedetector, RISING);

  //segmentdisplay numbers off
  digitalWrite(kmPin0, HIGH);
  digitalWrite(kmPin1, HIGH);
  digitalWrite(kmPin2, HIGH);
  digitalWrite(kmPin3, HIGH);
  digitalWrite(kmPin4, HIGH);
  digitalWrite(kmPin5, HIGH);

  digitalWrite(kphPin0, HIGH);
  digitalWrite(kphPin1, HIGH);
  digitalWrite(kphPin2, HIGH);

  Tlc.init();

  //Serial.begin(9600);

  //Clearing 7 segment displays
  Tlc.clear();
  Tlc.update();

  //Setting km stand

  //Cycling through at leds at beginning

  for (int i = 0; i <= 22; i++) {
    leds[i].setRGB(r,g,b);;
    FastLED.show();
    delay(200);
    leds[i] = CRGB::Black;
    FastLED.show();
  }
  FastLED.clear();
  FastLED.show();

  last_timer = millis();
  leds[21].setRGB(r,g,b);
  leds[22].setRGB(r,g,b);
  FastLED.show();
  delay(500);

  tenPulseTimer = millis();
}

void loop() {

  timer = millis();

  //check for rollover with millis function
  if (last_timer >= timer) {
    last_timer = timer;
    timer = millis();
  }

  if ((timer - pressTimer) >= 5000) {
    menuactivated = false;
    shortpresses = 0;
  }

  //menu
  if (shortpress && !calibrationActivated) {
    shortpresses++;
    menuactivated = true;
    switch (shortpresses) {
      case 1:
        if (longpress) {
          pulsecounter = 0;
          longpress = false;
          calibrationActivated = true;
        }
        break;
    }
  }

  //button debouncer
  if (debouncer) {
    if (debouncer_timer = 0) {
      debouncer_timer = timer;
    }
    if (timer - debouncer_timer > 200) {
      debouncer = false;
      debouncer_timer = 0;
    }
  }

  //check button presses
  if (!debouncer) {
    if (digitalRead(buttonPin)) {
      if (!pressactivated) {
        pressactivated = true;
        pressstart = timer;
      }
    }
    if (!digitalRead(buttonPin)) {
      if (pressactivated) {
        if (timer - pressstart > 2000) {
          longpress = true;
        } else {
          shortpress = true;
        }
        pressTimer = millis();
      }
    }
  }

  //do not change postition of this code!
  if (calibrationActivated) {
    calibrationMode();
    return 0;
  }

  //read out kph
  /*if (pulsecounter == 10) {
    unsigned long tenPulseTime = millis() - tenPulseTimer;
    tenPulseTimer = millis();
    float factor1 = pulsesPerKm / 10;
    float tempOneKm = factor1*tenPulseTime;
    kph = round(3600000/tempOneKm);*/
  kph = 53;


  //displaying speed on round bar graph
  //int barleds = round(kph / 10);
  int barleds = 5;
  for (int i = 0; i <= 20; i++) {
    leds[i] = CRGB::Black;
  }
  for (int i = 0; i <= barleds; i++) {
    leds[22 - i].setRGB(r,g,b);;
  }
  //uint8_t temp = 255;
  //FastLED.setBrightness(temp);
  FastLED.show();

  //test
  kmstand = 123456;

  //displaying kmstand
  if (!menuactivated) {
    kphString[0] = kph / 100 ;
    kphString[1] = (kph % 100) / 10;
    kphString[2] = kph % 10;

    kmstandString[0] = kmstand / 100000;
    kmstandString[1] = (kmstand % 100000) / 10000 ;
    kmstandString[2] = (kmstand % 10000) / 1000 ;
    kmstandString[3] = (kmstand % 1000) / 100 ;
    kmstandString[4] = (kmstand % 100) / 10 ;
    kmstandString[5] = kmstand % 10;
    display_all(kphString, kmstandString);
  }
  last_timer = timer;
  //check if dimmer is on
  //dimFactor = analogRead(dimPin) / 1024;
  dimFactor = 0.3;
  uint8_t dimFactorInt = round(255*dimFactor);
  byte dimFactorByte = dimFactorInt;
  //FastLED.setBrightness(dimFactorInt);
  r = dimFactorInt;
  g = dimFactorInt;
  b = dimFactorInt;
  //check if kilometre was driven and update
  if (pulsecounter > pulsesPerKm) {
    kmstand++;
    pulsecounter = pulsecounter - pulsesPerKm;
    fram.write32(kmstandAddress, kmstand);
    fram.write32(kmstandAddressBackup, kmstand);
  }
  //delay(1);
  /*leds[0] = CRGB::Red;
    FastLED.show();
    delay(200);
    leds[0] = CRGB::Black;
    FastLED.show();*/
}

//detects and counts incoming pulses from transmission
void pulsedetector() {
  pulsecounter++;
} />

Wiring diagramm: 
![Bild_2021-06-25_144656|690x376](upload://iDTPLwrwHgSHXR2J1XAHm0FXPHx.png)

A millisecond, or nine hundred microseconds?

That's very, very slow
Did you mean 30MHz?

it starts to be stable at one millisecond but that leads to flickering using 6 digits

Yes 30MHz
heres the datasheet tlc5940 datasheet

Could it be that the arduino spi bus is just that slow?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.