Close

No More I2C Expander!

A project log for ESP8266 Karaoke

ESP-powered lyrics display for Spotify

dolenDolen 10/20/2022 at 09:191 Comment

For expediency's sake I had originally chosen to drive my LCD using an I2C "backpack" board, specifically one with the PCF8574 GPIO expander. Along with the help of the New-LiquidCrystal library, I was able to get it running fairly easily (after determining the pin assignments on the backpack board).

However, this never felt like an optimal solution. The ESP8266 lacks hardware I2C, and the knowledge that it was bit-banged was keeping me awake at night. Besides, I wasn't using any other IOs from the ESP, so I might as well control the LCD directly. On the software front, it would just be a matter of changing an include file. And although the LCD runs at 5V, the HD44780 controller accepts logic VIH of >2.2V, which means it should work fine with the ESP 3.3V IOs.

And yet, having made all the requisite changes and plugged the display directly into the breadboard, I was greeted with garbled text:

This led me down a frustrating rabbit hole of messing with pin assignments, trying to modify the library, and even attempting to run the LCD at 3.3V, all to no avail. Although the screen worked just fine when using the I2C backpack, it had issues when connected directly, despite using the same library. I could write a whole separate post about this ordeal, but at the end of it I was certain that this was a timing issue.

The HD44780 datasheet gives max execution times for various commands (such as clearing the screen or writing a character). But these values assume a typical controller frequency of 270kHz, and it was evident that my particular screen was running much slower than that. In a "proper" application you're expected to read the LCD's busy flag and wait for the commands to complete. The LCD library code instead delays by fixed amounts (or in some cases, not at all), and just assumes that the controller has had enough time to complete its operation. This is an acceptable method, but you need to be 110% certain that the allotted delays are compatible with the display modules in question.  

Ultimately I gave up on the 3rd party library and wrote my own driver code (which has been merged). To optimize for speed I took advantage of the fact that the four SPI pins are muxed to consecutive bits of the GPIO port, so I could write 4-bit values in parallel instead of the repeated calls to digitalWrite() which had been employed by the New-LiquidCrystal library. Although this means that the pin assignments are fixed, I wasn't using those pins anyway. A full screen clear-and-refresh takes just under 10 milliseconds, compared to 75ms via I2C at 100kHz.

After some trial-and-error and checking timings on an oscilloscope, I was finally able to get the proper text display that I had been looking for:

I also cleaned up the wiring a bit, if you couldn't tell.

Discussions

Ken Yap wrote 10/20/2022 at 09:26 point

Yes the 44780 is quite fussy about time delays for operations. Code that worked with one MCU may not work for a faster MCU. So you did the right thing.

  Are you sure? yes | no