When you have a free PWM pin, you can use that pin to drive the backlight.
If you need to combine the LiquidCrystal_I2C with an "external" PWM pin, you could create your own class, inherit from the legacy class and add the needed functions to control the PWM pin.
something like that:
/*
https://forum.arduino.cc/t/adjusting-the-light-intensity-with-lcd-backlight-function/1333947
by noiasca
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//create your own backlight enabled I2C class:
class MyLCD : public LiquidCrystal_I2C {
const uint8_t blPin; // UNO: 3, 5, 6, 9, 10, 11
public :
MyLCD (uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t blPin) : LiquidCrystal_I2C(lcd_Addr, lcd_cols, lcd_rows), blPin(blPin) {}
void init() {
LiquidCrystal_I2C::init();
pinMode(blPin, OUTPUT);
}
void backlight() {
digitalWrite(blPin, HIGH); // assumption HIGH active (on most PCF8574 a NPN transistor drives the LED cathode)
}
void noBacklight() {
digitalWrite(blPin, LOW);
}
void setBacklight(byte val) {
analogWrite(blPin, val);
}
};
//LiquidCrystal_I2C lcd(0x3F, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display
MyLCD lcd(0x3F, 20, 4, 9); // address, columns, rows, PWM enabled backlight pin
constexpr uint16_t interval = 1500;
void setup() {
Serial.begin(115200);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.setCursor(3, 0);
lcd.print(F("Hello, world!"));
lcd.setCursor(2, 1);
lcd.print(F("backlight"));
}
void loop() {
Serial.println(F("switch backlight off"));
lcd.noBacklight();
delay(interval);
Serial.println(F("switch backlight on"));
lcd.backlight();
delay(interval);
Serial.println(F("set backlight to 0"));
lcd.setBacklight(0);
delay(interval);
Serial.println(F("set backlight to 64"));
lcd.setBacklight(64);
delay(interval);
Serial.println(F("set backlight to 128"));
lcd.setBacklight(128);
delay(interval);
Serial.println(F("set backlight to 192"));
lcd.setBacklight(192);
delay(interval);
Serial.println(F("set backlight to 255"));
lcd.setBacklight(255);
delay(interval);
Serial.println(F("set backlight to 0"));
lcd.setBacklight(0);
delay(interval);
}
You can disconnect the jumper and connect pin 1 to the PWM pin.
See also Dimming 16×2 and 20×4 LCD displays – Garry's blog