I2C LCD & TLC5940

Hi there,

working with one project there I use I2C LCD display (128x32) and TLC5940. Separately both work fine but then I combine libraries strange things begin. To TLC5940 I connect LED strips. So then I combine libraries LCD works fine but LED strips start blinking very fast, then I disconnect LCD library LED strips shine smooth. I read about similar situation and many say that Wire.h library fault, because both LCD ant TLC5940 use same library. Can I do something with this? Maybe use other libraries or other LCD address?

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <EEPROM.h>

#include "Tlc5940.h"

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

int button_up = 0;
int button_down = 0;
int button_ok = 0;
int ir_1 = 0;
int ir_2 = 0;
int light_sensor = 0;
int switch_1 = 0;
int switch_2 = 0;
bool lcd = false;
int eeprom;

/*
  eeprom reiksmes:
  1 - pakopu skaicius
  2 - pirmo IR jutiklio veikimo atstumas
  3 - antro IR jutiklio veikimo atstumas
  4 - jungikliu skaicius
  5 - sviesos jutiklis
  6 - pakopu apsvietimas
  7 - sviesos stiprumas procentais
  8 - apsvietimo laikas sekundemis
  9 - sviesos intesyvumas
*/

void setup()   {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  display.clearDisplay();
  display.display();
  Tlc.init();
  Serial.begin(9600);

  pinMode(2, INPUT);  //mygtukas OK
  pinMode(4, INPUT);  //mygtukas UP
  pinMode(5, INPUT);  //mygtukas DOWN
  pinMode(6, INPUT);  //jungiklis 1
  pinMode(7, OUTPUT); //LED IR1
  pinMode(8, OUTPUT); //LED IR2
  pinMode(12, INPUT); //jungiklis 2
  /*
      A0 - IR1
      A1 - IR2
      A4 - LCD
      A5 - LCD
      A6 - sviesos jutiklis
  */
}

void loop() {

  ir_1 = analogRead(A0);
  ir_2 = analogRead(A1);
  light_sensor = analogRead(A6);
  button_ok = digitalRead(2);
  switch_1 = digitalRead(6);
  switch_2 = digitalRead(12);

  //=============================================== Ijungia LED meniu

  if (button_ok == HIGH) {
    lcd = true;
  }

  if (lcd == true) {
    menu();
  }

  //=============================================== Suveikia laiptu apsvietimas nuo IR

  eeprom = 2;
  if (ir_1 > EEPROM.read(eeprom)) {
    aukstyn();
  }

  eeprom = 3;
  if (ir_2 > EEPROM.read(eeprom)) {
    zemyn();
  }

  //=============================================== Suveikia laiptu apsvietimas nuo jungiklio

  eeprom = 4;
  while (EEPROM.read(eeprom) == 1 && switch_1 == HIGH) {
    //visi();
  }

  while (EEPROM.read(eeprom) == 2 && switch_1 != switch_2) {
    //visi();
  }

  //=============================================== Ijungia pastovia pakopu sviesa

  /*eeprom = 6;
    if (EEPROM.read(eeprom) == 1) {
    int step_last;
    eeprom = 1;
    step_last = EEPROM.read(eeprom);
    eeprom = 7;
    Tlc.set(0, EEPROM.read(eeprom) * 40.95);
    Tlc.set(step_last, EEPROM.read(eeprom));
    Tlc.update();
    }*/

      Tlc.set(0, 4095);
  Tlc.set(1, 4095);
  Tlc.set(2, 4095);
  Tlc.set(3, 4095);
  Tlc.set(4, 4095);
  Tlc.set(5, 4095);
  Tlc.set(6, 4095);
  Tlc.set(7, 4095);
  Tlc.set(8, 4095);
  Tlc.set(9, 4095);
  Tlc.set(10, 4095);
  Tlc.set(11, 4095);
  Tlc.set(12, 4095);
  Tlc.set(13, 4095);
  Tlc.set(14, 4095);
  Tlc.set(15, 4095);
  Tlc.set(16, 4095);
  Tlc.set(17, 4095);
  Tlc.set(18, 4095);
  Tlc.set(19, 4095);
  Tlc.update();
}

I don’t need LCD run all the time, just to set parameters and that’s it. I try to use

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

in loop then I need it but LCD doesn’t work fine (all the time scrolling thru menu).

many say that Wire.h library fault, because both LCD ant TLC5940 use same library. Can I do something with this? Maybe use other libraries or other LCD address?

As far as I can tell the TLC5940 is an SPI device and uses the SPI library and the I2C display uses the Wire library so the above is not true. You need to look elsewhere.

A schematic of your project would be very helpful.

Putting display.begin in loop will never do any good.

The code for the menu(), aukstyn() and zemyn() functions is missing. What do those functions do?

sorry don't have schematic, but wire like this:
TLC5940
I2C LCD (I use ARDUINO NANO)

  • three buttons

aukstyn() and zemyn() still empty.
menu() is to big to show here, but I don't think it is matter what is written there.

If it does not use same library so maybe I made mistakes in code?
Maybe menu() is to big so it take a little time to go thru all code and get back to loop() and that's why I get blinking LED strips?

Idea: then I press "ok" button LCD show menu window and I can make settings. Then I finish with menu window I choose "ISEITI" and press "ok" button - LCD turn off until I press "ok" button again.

Maybe I can go to menu() different way, not using if structure?

no, menu() size doesn’t matter. I test using code:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <EEPROM.h>

#include "Tlc5940.h"

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  display.clearDisplay();
  display.display();
  Tlc.init();

}

void loop() {
  Tlc.set(0, 4095);
  Tlc.update();

}

and get same problem (blinking LED strip). I can fix blinking only if I delete:

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

but then cant use LCD…

OK!
make interesting move and I think it helps.
I write line:

display.begin();

in setup()

void setup()   {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  display.clearDisplay();
  display.display();
  display.begin(); // <---------

  Tlc.init();

  pinMode(2, INPUT);  //mygtukas OK
  pinMode(4, INPUT);  //mygtukas UP
  pinMode(5, INPUT);  //mygtukas DOWN
  pinMode(6, INPUT);  //jungiklis 1
  pinMode(7, OUTPUT); //LED IR1
  pinMode(8, OUTPUT); //LED IR2
  pinMode(12, INPUT); //jungiklis 2
  /*
      A0 - IR1
      A1 - IR2
      A4 - LCD
      A5 - LCD
      A6 - sviesos jutiklis
  */
}

and now it looks like work fine yet… no more LED strip blinking and I can use LCD.

BUT! Can anyone tell me what’s happening? Why extra display.begin(); fix everything?

Here is the function prototype from the Adafruit_SSD1306.h file from here.

boolean      begin(uint8_t switchvcc=SSD1306_SWITCHCAPVCC, uint8_t i2caddr=0, boolean reset=true,
boolean periphBegin=true);

The begin() function with no parameters uses a set of default parameters. When you call the begin() function with no parameters after calling

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

the default parameters "overwrite" the parameters from

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

So, I guess, the default parameters are the right ones for your LCD.

What happens if you use just the display.begin() and comment out the

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

if I comment out:

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

LCD don't work. Still don't understand how it woks but overwriting display.begin helps.