LCD I2C issue with backlight

I have a strange issue. For me.

I am building some sort of an RGB controller, based on Atmega328p. There are 5 buttons, an LCD I2C, MOSFETs, etc. The idea is to change a value or two, and control an RGB LED strip. The problem is with the backlight.

I use this library:

When I use Hello World example it works just fine.

However, when I used this sketch, it doesn't work as expected.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
//touch inputs
const int switch1 = 8;  //sw2 - plus default
const int switch2 = 3;  //sw3 - minus default
const int switch3 = 4;  //SW4 - Red plus
const int switch4 = 5;  //sw5 - Green plus
const int switch5 = 7;  //sw6 - Blue plus
//RGB outputs
const int ledG = 9;    //ch1
const int ledR = 10;   //ch2
const int ledB = 11;   //ch3
const int ledW = 6;   //ch4
//IR
const int IRpin = 7;
//misc
int switchCase = 0;
int valueG, valueR, valueB;
void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("hello, wolrd");
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledW, OUTPUT);
  digitalWrite(ledG, LOW);
  digitalWrite(ledR, LOW);
  digitalWrite(ledB, LOW);
  digitalWrite(ledW, LOW);
  delay(2000);
  lcd.clear();
}
void loop() {
  switchRead();
  switchMode();
  lcdDisplay();
  //delay(500);
}
void switchRead(){
  //plus case
  if(digitalRead(switch1)== HIGH && switchCase != 9){
    //Serial.println("+1");
    switchCase = ++switchCase;
    }
  //minus case
  if(digitalRead(switch2) == HIGH && switchCase != 0){
      //Serial.println("-1");
      switchCase = --switchCase;
      }
  //plus RED
  if(digitalRead(switch3) == HIGH && valueR != 255){
      switchCase = 10;
      //Serial.println("red +1");
      }
  //plus green
  if(digitalRead(switch4) == HIGH && valueG != 255){
      switchCase = 11;
      //Serial.println("green +1");
      }
  //plus blue
  if(digitalRead(switch5) == HIGH && valueB != 255){
      switchCase = 12;
      //Serial.println("blue +1");
      }
//Serial.println((String)valueG+" "+valueR+" "+valueB);
}
void switchMode(){
  switch(switchCase){
    case 0: //red
    valueG = 0;
    valueR = 255;
    valueB = 0;
    //Serial.println("0");
    break;
    case 1: //green
    valueG = 255;
    valueR = 0;
    valueB = 0;
    //Serial.println("1");
    break;
    case 2: //blue
    valueG = 0;
    valueR = 0;
    valueB = 255;
    //Serial.println("2");
    break;
    case 3: //violet
    valueG = 0;
    valueR = 128;
    valueB = 255;
   //Serial.println("3");
    break;
    case 4: //pink
    valueG = 0;
    valueR = 255;
    valueB = 255;
    //Serial.println("4");
    break;
    case 5: //yellow
    valueG = 255;
    valueR = 255;
    valueB = 0;
   //Serial.println("5");
    break;
    case 6: //tirquise
    valueG = 128;
    valueR = 0;
    valueB = 128;
    //Serial.println("6");
    break;
    case 7: //orange
    valueG = 128;
    valueR = 255;
    valueB = 0;
    //Serial.println("7");
    break;
    case 8: //bordo
    valueG = 0;
    valueR = 128;
    valueB = 128;
    //Serial.println("8");
    break;
    case 9: //white
    valueG = 255;
    valueR = 255;
    valueB = 255;
    //Serial.println("9");
    break;
    case 10: //red +
    valueR = valueR+1;
    //Serial.println("10");
    switchCase = -1;
    break;
    case 11: //green +
    valueG = valueG+1;
    //Serial.println("11");
    switchCase = -1;
    break;
    case 12: //blue +
    valueB = valueB+1;
    //Serial.println("12");
    switchCase = -1;
    break;
    }
}
void lcdDisplay(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Red");
  lcd.setCursor(4,0);
  lcd.print("Grn");
  lcd.setCursor(8,0);
  lcd.print("Blu");
  lcd.setCursor(14,0);
  lcd.print("Ps");

  lcd.setCursor(0,1);
  lcd.print("Blu");
  lcd.setCursor(4,1);
  lcd.print("Blu");
  lcd.setCursor(8,1);
  lcd.print("Blu");
  lcd.setCursor(14,1);
  lcd.print("Blu");
}

When I use this sketch I wrote, I get the first character most bright, and the brightness goes down to the last character at the bottom row. LCD is 16x2, with PCF8574. Just like it doesn't get enough power. But it works with the example on the same board. I measured the voltage on the LCD, it is 5V. Pot can not fix this problem

I believe I messed something with the code. But not sure what. The bottom line should print RGB values, etc.

I repeat, everything is fine with the example from the library, this sketch above is not.

The problem is that lcd.clear() in a lcdDisplay function. If I add a delay of some 500, it is ok, but it flicks.

The clear() function is very slow. It is better to not use that function in loop() code.

You could send fixed length strings to the display and overwrite old data with the new data.
Only update the display when the data changes. And only update that which changes.

Your data does not seem to change so I see no need to clear the display.

Nope. It will be. Here is the code I came up with so far.


#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
//touch inputs
const int switch1 = 8;  //sw2 - plus default
const int switch2 = 3;  //sw3 - minus default
const int switch3 = 4;  //SW4 - Red plus
const int switch4 = 5;  //sw5 - Green plus
const int switch5 = 7;  //sw6 - Blue plus
//RGB outputs
const int ledG = 9;    //ch1
const int ledR = 10;   //ch2
const int ledB = 11;   //ch3
const int ledW = 6;   //ch4
//IR
const int IRpin = 7;
//misc
int switchCase = 0;
int valueG, valueR, valueB;
void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("hello, wolrd");
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledW, OUTPUT);
  digitalWrite(ledG, LOW);
  digitalWrite(ledR, LOW);
  digitalWrite(ledB, LOW);
  digitalWrite(ledW, LOW);
  delay(2000);
  lcd.clear();
}
void loop() {
  switchRead();
  switchMode();
  lcdDisplay();
  rgbWrite();
  delay(500);
}
void switchRead(){
  //plus case
  if(digitalRead(switch1)== HIGH && switchCase != 9){
    //Serial.println("+1");
    switchCase = ++switchCase;
    }
  //minus case
  if(digitalRead(switch2) == HIGH && switchCase != 0){
      //Serial.println("-1");
      switchCase = --switchCase;
      }
  //plus RED
  if(digitalRead(switch3) == HIGH && valueR != 255){
      switchCase = 10;
      //Serial.println("red +1");
      }
  //plus green
  if(digitalRead(switch4) == HIGH && valueG != 255){
      switchCase = 11;
      //Serial.println("green +1");
      }
  //plus blue
  if(digitalRead(switch5) == HIGH && valueB != 255){
      switchCase = 12;
      //Serial.println("blue +1");
      }
Serial.println((String)valueG+" "+valueR+" "+valueB);
}
void switchMode(){
  switch(switchCase){
    case 0: //red
    valueG = 0;
    valueR = 255;
    valueB = 0;
    //Serial.println("0");
    break;
    case 1: //green
    valueG = 255;
    valueR = 0;
    valueB = 0;
    //Serial.println("1");
    break;
    case 2: //blue
    valueG = 0;
    valueR = 0;
    valueB = 255;
    //Serial.println("2");
    break;
    case 3: //violet
    valueG = 0;
    valueR = 128;
    valueB = 255;
   //Serial.println("3");
    break;
    case 4: //pink
    valueG = 0;
    valueR = 255;
    valueB = 255;
    //Serial.println("4");
    break;
    case 5: //yellow
    valueG = 255;
    valueR = 255;
    valueB = 0;
   //Serial.println("5");
    break;
    case 6: //tirquise
    valueG = 128;
    valueR = 0;
    valueB = 128;
    //Serial.println("6");
    break;
    case 7: //orange
    valueG = 128;
    valueR = 255;
    valueB = 0;
    //Serial.println("7");
    break;
    case 8: //bordo
    valueG = 0;
    valueR = 128;
    valueB = 128;
    //Serial.println("8");
    break;
    case 9: //white
    valueG = 255;
    valueR = 255;
    valueB = 255;
    //Serial.println("9");
    break;
    case 10: //red +
    valueR = valueR+1;
    //Serial.println("10");
    switchCase = -1;
    break;
    case 11: //green +
    valueG = valueG+1;
    //Serial.println("11");
    switchCase = -1;
    break;
    case 12: //blue +
    valueB = valueB+1;
    //Serial.println("12");
    switchCase = -1;
    break;
    }
}
void lcdDisplay(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Red Grn Blu   Ps");

  lcd.setCursor(0,1);
  lcd.print(valueR);
  lcd.setCursor(4,1);
  lcd.print(valueG);
  lcd.setCursor(8,1);
  lcd.print(valueB);
  lcd.setCursor(14,1);
  lcd.print(switchCase);
}
void rgbWrite(){
  analogWrite(ledG,valueG);
  analogWrite(ledR,valueR);
  analogWrite(ledB,valueB);
}

I gotta check this you suggested. If you have some sort of example would be nice. Also, it will speed up. :slight_smile:

Get rid of the clear() function.

Move the static displayed part to setup. There is no reason to write it over and over.
At the end of setup():

  delay(2000);
  lcd.clear();  // OK to use clear in setup().  Only happens once
  lcd.setCursor(0,0);
  lcd.print("Red Grn Blu   Ps");  // static display data
}

Clear the second line by writing spaces, do not use clear. Writing is much faster.

Do not update the display every time through loop(). No human can read it that fast. Use a millis() timer to update the display at a reasonable rate.

void lcdDisplay()
{
   // lcd.clear(); ***** NO!!!
   static unsigned long timer = 0;
   unsigned long interval = 500; // update every 1/2 second
   if (millis() - timer >= interval)
   {
      timer = millis();
      lcd.setCursor(0, 0);
      lcd.print("                ");  // overwrite old data with 16 spaces
      lcd.setCursor(0, 1);  // reset cursor
      lcd.print(valueR);
      lcd.setCursor(4, 1);
      lcd.print(valueG);
      lcd.setCursor(8, 1);
      lcd.print(valueB);
      lcd.setCursor(14, 1);
      lcd.print(switchCase);
   }
}

I leave it to you to do the update only changed data part.

If you want a faster display use the hc44780 library. The library is available via the IDE library manager. It is faster and has many useful features like automatic detection on I2C address and I2C backpack to LCD pin mapping, line wrap (if enabled) among others. It is easy to change to the hd44780 library. Only change the library includes and the constructor. All the other functions work the same.

FYI, millis() timer tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

1 Like

@who_took_my_nick

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print(" RGB Controller");
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledR, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledW, OUTPUT);
  digitalWrite(ledG, LOW);
  digitalWrite(ledR, LOW);
  digitalWrite(ledB, LOW);
  digitalWrite(ledW, LOW);
  delay(2000);
  lcd.clear();
  lcd.print("Red ");
  lcd.print("Grn ");
  lcd.print("Blu ");
  lcd.print(" Ps");
}
void loop() {
  switchRead();
  switchMode();
  lcdDisplay();
  delay(500);
}

void lcdDisplay(){
  lcd.setCursor(0,1);
  lcd.print(valueR);
  lcd.setCursor(4,1);
  lcd.print(valueG);
  lcd.setCursor(8,1);
  lcd.print(valueB);
}

The above code will print RGB values, and eliminate LCD clearing in the loop function, you'll have to remove delays yourself as I'm not editing your whole code.

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