This post demonstrates a minimal LCD library for MicroPython, used on an ESP8266. This is a small collection of commands that I put together (mostly ported) to have simple control over an HD44780 compatible LCD. There are a couple of existing LCD libraries for MicroPython so make sure to check them out first, since this is a minimalistic approach and may be limiting for you project. The post is merely a reference to the code rather than full explanation on how HD44780 LCD works. There are plenty of sources about that as well as the post of the code’s original author.
I am using the NodeMCU board so make sure to adjust the connections according to the board you are using. The LCD uses an 8-bit data bus but it also supports 4-bit mode. That means we can break a byte to two nibbles (4 bits) and save up 4 wired connections.
Let’s take a look at the code. Credit goes to Matt Hawkins over raspberrypi-spy.co.uk who is the original author of the code. I just ported it over to MicroPython and made a couple of simple changes.
import machine import time LCD_RS = 16 LCD_E = 5 LCD_D4 = 4 LCD_D5 = 0 LCD_D6 = 2 LCD_D7 = 14 LCD_WIDTH = 16 LCD_CHR = True LCD_CMD = False LCD_LINE_1 = 0x80 LCD_LINE_2 = 0xC0 E_PULSE = 0.0005 E_DELAY = 0.0005 pin_lcd_e = machine.Pin(LCD_E, machine.Pin.OUT) pin_lcd_rs = machine.Pin(LCD_RS, machine.Pin.OUT) pin_lcd_d4 = machine.Pin(LCD_D4, machine.Pin.OUT) pin_lcd_d5 = machine.Pin(LCD_D5, machine.Pin.OUT) pin_lcd_d6 = machine.Pin(LCD_D6, machine.Pin.OUT) pin_lcd_d7 = machine.Pin(LCD_D7, machine.Pin.OUT) def main(): lcd_init() lcd_string("HD44780 LCD", LCD_LINE_1) lcd_string("with MicroPython", LCD_LINE_2) def lcd_init(): lcd_byte(0x33, LCD_CMD) lcd_byte(0x32, LCD_CMD) lcd_byte(0x0C, LCD_CMD) lcd_byte(0x01, LCD_CMD) lcd_byte(0x28,LCD_CMD) lcd_byte(0x06,LCD_CMD) time.sleep(E_DELAY) def lcd_byte(bits, mode): pin_lcd_rs.value(mode) pin_lcd_d4.low() pin_lcd_d5.low() pin_lcd_d6.low() pin_lcd_d7.low() if bits & 0x10 == 0x10: pin_lcd_d4.high() if bits & 0x20 == 0x20: pin_lcd_d5.high() if bits & 0x40 == 0x40: pin_lcd_d6.high() if bits & 0x80 == 0x80: pin_lcd_d7.high() lcd_toggle_enable() pin_lcd_d4.low() pin_lcd_d5.low() pin_lcd_d6.low() pin_lcd_d7.low() if bits & 0x01 == 0x01: pin_lcd_d4.high() if bits & 0x02 == 0x02: pin_lcd_d5.high() if bits & 0x04 == 0x04: pin_lcd_d6.high() if bits & 0x08 == 0x08: pin_lcd_d7.high() lcd_toggle_enable() def lcd_toggle_enable(): time.sleep(E_DELAY) pin_lcd_e.high() time.sleep(E_PULSE) pin_lcd_e.low() time.sleep(E_DELAY) def lcd_string(message, line): lcd_byte(line, LCD_CMD) for c in message: # Print out the message lcd_byte(ord(c), LCD_CHR) for i in range(LCD_WIDTH - len(message)): # Fill the rest of the line with empty characters lcd_byte(32, LCD_CHR) main()
Copy the above code in a file, for example
lcd.py and then use the following command to give it a test run (assuming your port is
ampy --port /dev/ttyUSB0 run lcd.py
Here is how it should look like 🙂
I did some changes in the
lcd_string function in order to support multi length strings. So what it does, it first prints the contents of the
message and then fills the rest of the line with empty characters in order to delete any remains from the previous refresh.
Hope this helps you out. Let me know in the comments.