




















































In this article by Samarth Shah, author of the book Learning Raspberry Pi, we will take your Raspberry Pi to the real world. Make sure you have all the components listed for you to go ahead:
Potentiometer is just a fancy word used for variable resistor. Basically, it is just a three-terminal resistor with sliding or rotating contact, which is used for changing the value of the resistor.
(For more resources related to this topic, see here.)
Once you have all the components listed in the previous section, before you get started, there are some software installation that needs to be done:
Sudo apt-get update
For controlling GPIO pins of Raspberry Pi, you will be using Python so for that python-dev, python-setuptools, and rpi.gpio (the Python wrapper of WiringPi) are required. Install them using the following command:
Sudo apt-get install python-dev Sudo apt-get install python-setuptools Sudo apt-get install rpi.gpio
Now, your Raspberry Pi is all set to control the LCD, but before you go ahead and start connecting LCD pins with Raspberry Pi GPIO pins, you need to understand how LCD works and more specifically how HD44780 based LCD works.
The LCD character displays can be found in espresso machines, laser printers, children's toys, and maybe even the odd toaster. The Hitachi HD44780 controller has become an industry standard for these types of displays. If you look at the back side of the LCD that you have bought, you will find 16 pins:
Vcc / HIGH / '1' |
+5 V |
GND / LOW / '0' |
0 V |
The following table depicts the HD44780 pin number and functionality:
Pin number |
Functionality |
1 |
Ground |
2 |
VCC |
3 |
Contrast adjustment |
4 |
Register select |
5 |
Read/Write(R/W) |
6 |
Clock(Enable) |
7 |
Bit 0 |
8 |
Bit 1 |
9 |
Bit 2 |
10 |
Bit 3 |
11 |
Bit 4 |
12 |
Bit 5 |
13 |
Bit 6 |
14 |
Bit 7 |
15 |
Backlight anode (+) |
16 |
Backlight cathode (-) |
Pin 1 and Pin 2 are the power supply pins. They need to be connected with ground and +5 V power supply respectively.
Pin 3 is a contrast setting pin. It should be connected to a potentiometer to control the contrast. However, in a JHD162A LCD, if you directly connect this pin to ground, initially, you will see dark boxes but that will work if you don't have potentiometer.
Pin 4, Pin 5, and Pin 6 are the control pins.
Pin 7 to Pin 14 are the data pins of LCD. Pin 7 is the least significant bit and pin 14 is the most significant bit of the date inputs. You can use LCD in two modes, that is, 4-bit or 8-bit. In the next section, you will be doing 4-bit operation to control the LCD. If you want to display some number/character on the display, you have to input the appropriate codes for that number/character on these pins.
Pin 15 and Pin 16 provide power supply to the backlight of LCD. A backlight is a light within the LCD panel, which makes seeing the characters on the screen easier. When you leave your cell phone or MP3 player untouched for some time, the screen goes dark. This is the backlight turning off. It is possible to use the LCD without the backlight as well. JHD162A has a backlight, so you need to connect the power supply and ground to these pins respectively.
Pin 4, Pin 5, and Pin 6 are the most important pins. As mentioned in the table, Pin 4 is the register select pin. This allows you to switch between two operating modes of the LCD, namely the instruction and character modes. Depending on the status of this pin, the data on the 8 data pins (D0-D7) is treated as either an instruction or as character data. To display some characters on LCD, you have to activate the character mode. And to give some instructions such as "clear the display" and "move cursor to home", you have to activate the command mode. To set the LCD in the instruction mode, set Pin 4 to '0' and to put it in character mode, set Pin 4 to '1'. Mostly, you will be using the LCD to display something on the screen; however, sometimes you may require to read what is being written on the LCD. In this case, Pin 5 (read-write) is used. If you set Pin 5 to 0, it will work in the write mode, and if you set Pin 5 to 1, it will work in the read mode. For all the practical purposes, Pin 5 (R/W) has to be permanently set to 0, that is, connect it with GND (Ground). Pin 6 (enable pin) has a very simple function. This is just the clock input for the LCD. The instruction or the character data at the data pins (Pin 7-Pin 14) is processed by the LCD on the falling edge of this pin. The enable pin should be normally held at 1, that is, Vcc by a pull up resistor. When a momentary button switch is pressed, the pin goes low and back to high again when you leave the switch. Your instruction or character will be executed on the falling edge of the pulse, that is, the moment when the switch get closed.
So, the flow diagram of a typical write sequence to LCD will be:
Having understood the way LCD works, you are ready to connect your LCD with Raspberry Pi. Connect LCD pins with Raspberry Pi pins using following table:
LCD pins |
Functionality |
Raspberry Pi pins |
1 |
Ground |
Pin 6 |
2 |
Vcc |
Pin 2 |
3 |
Contrast adjustment |
Pin 6 |
4 |
Register select |
Pin 26 |
5 |
Read/Write (R/W) |
Pin 6 |
6 |
Clock (Enable) |
Pin 24 |
7 |
Bit 0 |
Not used |
8 |
Bit 1 |
Not used |
9 |
Bit 2 |
Not used |
10 |
Bit 3 |
Not used |
11 |
Bit 4 |
Pin 22 |
12 |
Bit 5 |
Pin 18 |
13 |
Bit 6 |
Pin 16 |
14 |
Bit 7 |
Pin 12 |
15 |
Backlight anode (+) |
Pin 2 |
16 |
Backlight cathode (-) |
Pin 6 |
Your LCD should have come with 16-pin single row pin header (male/female) soldered with 16 pins of LCD. If you didn't get any pin header with the LCD, you have to buy a 16-pin single row female pin header. If the LCD that you bought doesn't have a soldered 16-pin single row pin header, you have to solder it. Please note that if you have not done soldering before, don't try to solder it by yourself. Ask some of your friends who can help or the easiest option is to take it to the place from where you have bought it; he will solder it for you in merely 5 minutes.
The final connections are shown in the following screenshot. Make sure your Raspberry Pi is not running when you are connecting LCD pins with Raspberry Pi pins. Connect LCD pins with Raspberry Pi using hook up wires.
Before you start scripting, you need to understand few more things about operating LCD in a 4-bit mode:
So, the typical 4-bit mode write process will look like this:
Once you have connected LCD pins with Raspberry Pi, as per the previously shown diagram, boot up your Raspberry Pi. The following are the steps to develop a digital clock:
Here is the code that needs to be copied in the DigitalClock.py file:
#!/usr/bin/python import RPi.GPIO as GPIO import time from time import sleep from datetime import datetime from time import strftime class HD44780: def __init__(self, pin_rs=7, pin_e=8, pins_db=[18,23,24,25]): self.pin_rs=pin_rs self.pin_e=pin_e self.pins_db=pins_db GPIO.setmode(GPIO.BCM) GPIO.setup(self.pin_e, GPIO.OUT) GPIO.setup(self.pin_rs, GPIO.OUT) for pin in self.pins_db: GPIO.setup(pin, GPIO.OUT) self.clear() def clear(self): # Blank / Reset LCD self.cmd(0x33) self.cmd(0x32) self.cmd(0x28) self.cmd(0x0C) self.cmd(0x06) self.cmd(0x01) def cmd(self, bits, char_mode=False): # Send command to LCD sleep(0.001) bits=bin(bits)[2:].zfill(8) GPIO.output(self.pin_rs, char_mode) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4): if bits[i] == "1": GPIO.output(self.pins_db[i], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4,8): if bits[i] == "1": GPIO.output(self.pins_db[i-4], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False) def message(self, text): # Send string to LCD. Newline wraps to second line for char in text: if char == 'n': self.cmd(0xC0) # next line else: self.cmd(ord(char),True) if __name__ == '__main__': while True: lcd = HD44780() lcd.message(" "+datetime.now().strftime(%H:%M:%S)) time.sleep(1)
sudo python DigitalClock.py
This code accesses the Raspberry Pi GPIO port, which requires root privileges, so sudo is used.
Only 4 data pins of LCD are being connected, so this script will work for the LCD 4-bit mode.
I have used the JHD162A LCD, which is based on the HD44780 controller. Controlling mechanisms for all HD44780 LCDs are same. So, the preceding class, HD44780, can also be used for controlling another HD44780-based LCD.
Once you have understood the preceding LCD 4-bit operation, it will be much easier to understand this code:
if __name__ == '__main__': while True: lcd = HD44780() lcd.message(" "+datetime.now().strftime(%H:%M:%S)) time.sleep(1)
The main HD44780 class has been initialized and the current time will be sent to the LCD every one second by calling the message function of the lcd object. The most important part of this project is the HD44780 class.
The HD44780 class has the following four components:
The _init_ function initializes the necessary GPIO port for LCD operation:
def __init__(self, pin_rs=7, pin_e=8, pins_db=[18,23,24,25]): self.pin_rs=pin_rs self.pin_e=pin_e self.pins_db=pins_db GPIO.setmode(GPIO.BCM) GPIO.setup(self.pin_e, GPIO.OUT) GPIO.setup(self.pin_rs, GPIO.OUT) for pin in self.pins_db: GPIO.setup(pin, GPIO.OUT) self.clear()
GPIO.setmode(GPIO.BCM): Basically, the GPIO library has two modes in which it can operate. One is BOARD and the other one is BCM. The BOARD mode specifies that you are referring to the numbers printed in the board. The BCM mode means that you are referring to the pins by the "Broadcom SOC channel" number. While creating an instance of the HD44780 class, you can specify which pin to use for a specific purpose. By default, it will take GPIO 7 as RS Pin, GPIO 8 as Enable Pin, and GPIO 18, GPIO 23, GPIO 24, and GPIO 25 as data pins. Once you have defined the mode of the GPIO operation, you have to set all the pins that will be used as output, as you are going to provide output of these pins to LCD pins. Once this is done, clear and initialize the screen.
The clear function clears/resets the LCD:
def clear(self): # Blank / Reset LCD self.cmd(0x33) self.cmd(0x32) self.cmd(0x28) self.cmd(0x0C) self.cmd(0x06) self.cmd(0x01)
You will see some code sequence that is executed in this section. This code sequence is generated based on the HD44780 datasheet instructions. A complete discussion of this code is beyond the scope of this article; however, to give a high-level overview, the functionality of each code is as follows:
The cmd function sends the command to the LCD as per the LCD operation, and is shown as follows:
def cmd(self, bits, char_mode=False): # Send command to LCD sleep(0.001) bits=bin(bits)[2:].zfill(8) GPIO.output(self.pin_rs, char_mode) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4): if bits[i] == "1": GPIO.output(self.pins_db[i], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4,8): if bits[i] == "1": GPIO.output(self.pins_db[i-4], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False)
As the 4-bit mode is used drive the LCD, you will be using the flowchart that has been discussed previously. In the first line, the sleep(0.001) second is used because a few LCD operations will take some time to execute, so you have to wait for a certain time before it gets completed. The bits=bin(bits)[2:].zfill(8) line will convert the integer number to binary string and then pad it with zeros on the left to make it proper 8-bit data that can be sent to the LCD processor. The preceding lines of code does the operation as per the 4-bit write operation flowchart.
The message function sends the string to LCD, as shown here:
def message(self, text): # Send string to LCD. Newline wraps to second line for char in text: if char == 'n': self.cmd(0xC0) # next line else: self.cmd(ord(char),True)
This function will take the string as input, convert each character into the corresponding ASCII code, and then send it to the cmd function. For a new line, the 0xC0 code is used.
Discover more Raspberry Pi projects in Raspberry Pi LED Blueprints - pick up our guide and see how software can bring LEDs to life in amazing different ways!