Understanding the LCM1602C LCD Display: Programming with the Arduino, Part 1
In my previous article, I walked through how tying the various connections on the LCD between ground (GND) and +5V would program the LCD to display pretty much anything you wanted. I'll even point you towards a video tutorial by RC Tractor Guy that actually demonstrates how you can use simple switches to program the LCD. Frankly, it explains things a lot better than I do.
As you might have guessed, it would take a looooooong time to use such a basic circuit to program an LCD. It would also be time-consuming to make any changes to the LCD display. This means you need something that you can change more easily. I'm going to use an Arduino to do just that. I have an Arduino Uno (that has an Ethernet shield mounted on top) to do just that.
I want to start from the beginning and take this a single step at a time. In my last post, I explained that programming the Hitachi LCD is nothing more than connecting certain inputs to either ground or +5V, then connecting the EN line to +5V, then back to ground. That's exactly what RC Tractor Guy demonstrates in his video. Using the Arduino, we're going to replace the physical switches with the basic Arduino commands digitalWrite and delay. Yes, I realize that there is an entire library of Arduino code that does this with a lot less coding. We'll get there. Be patient.
The connections I'm using are straight out of the Arduino Starter Kit book. Specifically, on the LCD:
- Pin 1 is connected directly to ground.
- Pin 2 is connected directly to +5V. (NOTE: This, in turn, comes directly from the +5V output of the Arduino Uno.)
- Pin 3 is connected to the middle pin of the 10k potentiometer, and is used to adjust the contrast of the LCD.
- Pin 4 (RS or "register select") is connected to pin 12 on the Arduino Uno.
- Pin 5 (RW or "read/write") is connected directly to ground. By doing this, we're saying that we're only going to write to the LCD, not read anything from it. Which is fine. We just want to put text onto the LCD, not read anything from it anyway.
- Pin 6 (EN or "enable") is connected to pin 11 on the Arduino Uno.
- Pins 7 - 10: Not connected.
- Pin 11 on the LCD is connected to pin 5 on the Arduino Uno.
- Pin 12 on the LCD is connected to pin 4 on the Arduino Uno.
- Pin 13 on the LCD is connected to pin 3 on the Arduino Uno.
- Pin 14 on the LCD is connected to pin 2 on the Arduino Uno.
- Pin 15 is connected to one end of a 1k resistor, and the other end of the resistor is connected to +5V.
- Pin 16 is connected directly to ground.
With everything connected, the next part is to code the commands for the Arduino. For this, I'm only going to need to code for six connections. These are the RS (register select) line (pin 12 on the Arduino), the EN (enable) line (pin 11 on the Arduino), and the four data lines (pins 2 - 5 on the Arduino). Everything else is already set.
All I have to do now is to set the commands on the four data lines (again, pins 2 - 5 on the Arduino), set the RS line (pin 12 on the Arduino), then pulse the EN (enable) line on the Arduino HIGH, then LOW. Using the chart from the previous post, in which a "1" means "HIGH" and "0" means "LOW", I get
Command | RS | D7 | D6 | D5 | D4 |
Function set (4-bit, 2-lines, 5x8 font), high-order bits. | 0 | 0 | 0 | 1 | 0 |
Function set (4-bit, 2-lines, 5x8 font), these particular high-order bits have to be repeated this one time. | 0 | 0 | 0 | 1 | 0 |
Function set (4-bit, 2-lines, 5x8 font), low-order bits. | 0 | 1 | 0 | 0 | 0 |
Turn the display and cursor ON, and set the cursor to blinking, high-order bits. | 0 | 0 | 0 | 0 | 0 |
Turn the display and cursor ON, and set the cursor to blinking, low-order bits. | 0 | 1 | 1 | 0 | 0 |
Set the entry mode, with the cursor incrementing and the display not shifting, high-order bits. | 0 | 0 | 0 | 0 | 0 |
Set the entry mode, with the cursor incrementing and the display not shifting, low-order bits. | 0 | 0 | 1 | 1 | 0 |
Change the cursor position to the 2nd line, 4th position from the left, high-order bits. | 0 | 1 | 1 | 0 | 0 |
Change the cursor position to the 2nd line, 4th position from the left, low-order bits. | 0 | 0 | 0 | 1 | 1 |
Enter a character "H" into the display at the current cursor position, high-order bits. | 1 | 0 | 1 | 0 | 0 |
Enter a character "H" into the display at the current cursor position, low-order bits. | 1 | 1 | 0 | 0 | 0 |
Enter a character "e" into the display, high-order bits. | 1 | 0 | 1 | 1 | 0 |
Enter a character "e" into the display, low-order bits. | 1 | 0 | 1 | 0 | 1 |
Enter a character "l" into the display, high-order bits. | 1 | 0 | 1 | 1 | 0 |
Enter a character "l" into the display, low-order bits. | 1 | 1 | 1 | 0 | 0 |
Enter a character "l" into the display, high-order bits. | 1 | 0 | 1 | 1 | 0 |
Enter a character "l" into the display, low-order bits. | 1 | 1 | 1 | 0 | 0 |
Enter a character "o" into the display, high-order bits. | 1 | 0 | 1 | 1 | 0 |
Enter a character "o" into the display, low-order bits. | 1 | 1 | 1 | 1 | 1 |
This should result in the following image:
This is programming the LCD at its most basic, nothing more than connecting the various lines to either +5 V or ground, in a particular sequence. It's "assembly language for the LCD". (Okay. Not really. We're not moving bits around registers. But I hope you get the point.) Many Arduino-to-LCD projects use only four data lines (4-bit transfers), such as this one and this one. Regardless of how its programmed, whether with an Arduino or with a Raspberry Pi running through its GPIO ports, ultimately, the logic being sent to the LCD must be that as shown above. For example, if you're programming the Arduino to display the letter "H", then it's sending the same two 4-bit transfers as shown when you sent the letter "H" in the table above. It's just that you've now created an abstract layer in between you and the LCD. You told the program "Display the letter 'H'", the program figured out what logic needs to be sent to the LCD (set RS line HIGH, set data lines D7-D0 to 01001000, then flash the EN line one time), then sent it. It's that straightforward.
In Part 3, we'll cover creating special characters.