The standard character-based display used on many Arduino projects are based on the Hitachi HD44780 chip. They are available quite inexpensively, as little as $2.59 on eBay shipped from China for a 16×2 display. Sizes go up to 20×4 (what I usually buy), and common modes include black on green, some with backlight, and white on blue, which requires a backlight. These displays are supported by the native LiquidCrystal library built into the Arduino LCD. Using these displays requires, at a minimum, 6 data pins, on the Arduino. That can eat up a lot of data pins if you are using other items.
I2C to the rescue! I2C is a 2-wire serial communication protocol also natively supported by the Arduino. For a little extra money, you can purchase I2C displays with a “backpack” attached that reduce the display down to an addressable I2C device, and all is needed is a clock and data line attached to pins A4 and A5. You can make your own with shift register. You can also purchase the backpack separately. Several exist, based on a variety of chips. The most common (and the subject of this post) are based on the PCF8574 (and variants PCF 8574A and 8574A) I2C shift register.
In theory, all you need to do is:
- Connect power, ground, and the two wires
- Identify the I2C address of your display
- You are up and running!
In practice, #2 and #3 are a time-consuming trade-off. Identification of the I2C address is not hard — if not provided by the vendor, there are many Arduino sketches out there that will scan your I2C bus and identify the address of any device that responds — it has worked on the 3 I2C devices that I have.
The hard part, and the reason I am writing this blog post, is the frustrating aspect of finding the right library to use, and the correct pin configuration for your particular LCD backpack.
If you purchased your backpack from a vendor like Adafruit or Sparkfun, they have a library on their website. And it will work, and they will help you (as well as the online community). The downside of these libraries is that they make affect your use of non-I2C LCD displays.
If you purchased your I2C LCD display or backback from a cheap vendor on eBay or Amazon, you (like me) likely have no documentation. Not only is the address unknown, but the exact configuration (what pins on the shift register are connected to the LCD display, issue with how the enable and backlight are configured, etc) varies from manufacturer to manufacturer. To make it more complicated, there are MANY LCD I2C libraries out there, and they vary in terms of how much they give you controlto specify these pin configurations vs making assumptions.
I got to a point where my display was powered and visible to the I2C scanner, but various libraries I tried were not working. I probed the pin connections and verified there were no bad solder joints, and I even bought a 2nd LCD I2C display to compare (different vendor) and had similar problems. I became convinced that the problem was getting the library to match the exact pin configuration between the 8574 chip on the backpack and the LCD display, and a few assumptions about other LCD pins.
I found a solution. It works!
I highly recommend using this LCD library. I like that it covers all possible displays and interfaces, but it also retains sufficient flexibility to change the pin configuration to work with your display. It is also well-documented and actively maintained. It replaces the native LiquidCrystal library in the Arduino IDE, but works fine with my non-I2C displays. The only downside, at least on my Mac, is that by replacing a built-in library, it means any upgrade to the IDE means re-replacing the library. Installation is a bit tricky, but this is true for most replacement Arduino libraries.
I also highly recommend reading this post. This post identifies 3 common variants of the 8574 backpack, and how to configure the aforementioned library to work with each variant. My two displays were of the #3 variety on that page, and that is what ultimately worked for me.
Once your backpack is working, I recommend you also read my blog post about using a potentiometer to control the backlight power. The jumper on the backpack just turns the backlight on and off. Putting a potentiometer between 5V and GND and using the wiper to control the display backlight can reduce current draw from 30 mA to as low as 4 mA with no loss of readability.
Ultimately, this is a tradeoff of time and money. You can pay a lot less on eBay, Amazon, Alibaba, etc for a low-cost display, and devote some time to getting them to work (and you may learn something, too!) Or you can buy something from a company like Adafruit or Sparkfun, use their provided libraries, and be up and running. You will pay more, but it will work out of the box (you hope). For me personally, I wanted a particular display configuration they did not sell, and I found their libraries more limiting (although they work with what they sell!) than several of the open-source libraries out there.
I am somewhat surprised, given the utility of I2C devices, that there is not a more consistent standard for I2C LCD displays (this would not be hard), enforced by built-in support to the Arduino IDE LiquidCrystal library. At least, that is what I would do if I controlled the IDE development 🙂
These are really notes to myself, but I hope someone finds them useful. For reference, here are links to the displays I actually purchased on eBay and Amazon.
eBay 20×4 LCD I2C display white-on-blue – $8.49 (including shipping)
Amazon 20×4 LCD I2C display white-on-blue – $5.49+$2.49 shipping
I particularly like the eBay vendor frentaly since they offer prices similar to those shipped from Asia, but are located in the US in an Atlanta suburb, so shipping is quite fast! (especially since I live in Atlanta). Not a paid endorsement — I just like their prices and location due to fast shipping. I cannot speak to product quality beyond this display and another I2C backpack I have purchased.