Using LCD and PWM in ESP32

zhil
5 min readMar 5, 2022

--

In THIS ARTICLE, I will show you my exploits using ESP32, LCD, and the PWM concept. This little project is carried out under the guidance of the excellent Luqman Muhammad Zagi, S.T., M.T. of the Bandung Institute of Technology.

Prerequisites

  1. An ESP32 microcontroller, along with its vertebrate
  2. A 16×2 LCD, complete with its I2C serial communication bus (soldered!)
  3. A breadboard
  4. A Micro-USB cord
  5. A few male-to-male jumper wires
  6. A few male-to-female jumper wires
  7. A few 3mm LEDs
  8. A few 330Ω resistors
  9. Arduino IDE installed for ESP32. I have made a detailed installation guide in my previous article: https://zhillan-arf.medium.com/blink-the-led-with-esp32-5c3f358ea2ff

Setting up the LCD

Last week, I actually tried set up an LCD — you may read it at https://zhillan-arf.medium.com/using-bme280-to-display-temperature-humidity-and-pressure-with-esp32-91333957c9e . But it was filled with various forms of interesting catastrophe and inefficiencies, so now I try to actually do it well.

First, I set up the LCD physical wirings using this arrangement:

  1. ESP32 GPIO21 ← → LCD SDA (Green)
  2. ESP32 GPIO22 ← → LCD SCL (Yellow)
  3. LCD GND and VCC outlets to their respective ESP32 pins.

I then run this program as a sanity test:

#include <LiquidCrystal_I2C.h>// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;
// set LCD address, number of columns and rows
// if you don’t know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
void setup(){
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
}
void loop(){
// set cursor to first column, first row
lcd.setCursor(0, 0);
// print message
lcd.print(“Hello, World!”);
delay(1000);
// clears the display to print new message
lcd.clear();
// set cursor to first column, second row
lcd.setCursor(0,1);
lcd.print(“Hello, World!”);
delay(1000);
lcd.clear();
}

And it works! The LCD displays the “Hello, world!” message as intended. However, the issue I ran into last week persisted: namely that the letters in the LCD are shockingly faint.

To combat this contrast/brightness problem, I first try to rotate the potentiometer behind the LCD using a screwdriver. It was harder than it seems. In any case, this is what I got:

  1. The potentiometer indeed regulates the contrast between the letters and their alighted background, but the scope is shockingly small.
  2. It is still shockingly bad, even in maximum contrast. Some camera tricks are needed just to ensure that the writing is legible.

As such, it was quite a shocker when I moved the power and ground wires further closer to the board, behold: an ancient revelation from God.

However, when I recompiled the code, it returned to the standard Hello World sanity test. Apparently, I found a mystical phenomenon:

  1. When you pluck out the power from a running LCD, it switches from the program to the eldritch celestial messages.
  2. If you leave it for some time long enough, it also reverts to the messages.

Importantly, this little celestial phenomenon reveals that my equipment CAN display nice white texts, it just refuses to do so.

How? (Idk, I have to study for UTS)

Setting up the PWM

A bit of explanation first. There is a problem with ESP32: it can only output digital current — that is, its pin either has a 3.3V voltage, or it doesn’t have anything at all. However, we can get around this limitation using pulse-width modulation (PWM), which manages the average power delivered by the pins, such that it resembles an analog power.

With this little trick, we can, for example, set LEDs of different brightness.

I created a contraption that will gradually charge or discharge a set of LEDs at the push of a pushbutton, while also displaying its brightness on the LCD screen.

I then used this code to regulate the PWM using the “ledc” series of functions and the LCD to visually display its current dutyCycle.

#include <LiquidCrystal_I2C.h>
// pins
#define buttonPin 4
#define ledPin 5
// PWM properties
const int freq = 5000; //Hz
const int ledChannel = 0;
const int resolution = 8;
// LED
const int delayDuty = 10;
int dutyCycle = 0; // [0,255]
int ledStatus = 0;
// Button
int buttonState = 0; // pushbutton status
// LCD setup
int lcdColumns = 16;
int lcdRows = 2;
int i;
int progressBar = 0;
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); //0x27 acquired from I2C testing
void setup() {
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
ledcSetup(ledChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(ledPin, ledChannel);
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
}
void loop() {
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, switch state:
if (buttonState == HIGH) {
if ((ledStatus == -1) || (dutyCycle <= 0)) {
ledStatus = 1; // Now charging
lcd.setCursor(0, 0);
lcd.print(“Charging…”);
}
else if ((ledStatus = 1) || (dutyCycle >= 255)) {
ledStatus = -1; // Now discharging
lcd.setCursor(0, 0);
lcd.print(“Discharging…”);
}
}
// else, nothing happens if button is still pressed

// Change the LED
if (((dutyCycle <= 0) && (ledStatus == -1)) || ((dutyCycle >= 255) && (ledStatus == 1))) {
ledStatus = 0;
}
else if (ledStatus == 1) {
ledcWrite(ledChannel, dutyCycle);
dutyCycle++;
delay(delayDuty);
}
else if (ledStatus == -1) {
ledcWrite(ledChannel, dutyCycle);
dutyCycle — ;
delay(delayDuty);
}

// Change the LCD
progressBar = (dutyCycle / 16);
lcd.setCursor(0, 1);
lcd.print(“ “);
for (i=0; i < progressBar; i++) {
lcd.setCursor(i, 1);
lcd.write(byte(0));
}
}

This was the result.

(Again, it’s still faint, but I promise it works as intended).

In any case, that is all from me the week. Next week is pain weel: midterms, meaning that a Grand Project related to ESP32 should be in order. Stay tuned!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

zhil
zhil

Written by zhil

Five coffee a day keeps your esophagus away

No responses yet

Write a response