-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlcd_hd44780.py
219 lines (178 loc) · 6.55 KB
/
lcd_hd44780.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
"""
This module provides a simple interface for controlling character LCDs
based on the HD44780 driver. It supports displaying text, controlling the
cursor position, and creating custom characters on the LCD screen.
Example
-------
.. code-block:: python
from machine import Pin
import time
from lcd_hd44780 import LcdHd44780
# Initialize the LCD with control pins (RS, E) and data pins (D4, D5, D6, D7)
lcd = LcdHd44780(rs=26, e=25, d=[13, 10, 9, 27])
# Move cursor to line 1, column 3 and display text
lcd.move_to(1, 3)
lcd.write("Hello, World!")
lcd.move_to(2, 5)
lcd.write("MicroPython")
Authors
-------
- Shujen Chen et al. Raspberry Pi Pico Interfacing and Programming with MicroPython
- Tomas Fryza
Modification history
--------------------
- **2024-11-11** : Added Sphinx-style comments for documentation.
- **2024-10-26** : Added `demo` method to demonstrate usage of the display.
- **2023-10-17** : File created, initial release.
"""
from machine import Pin
import time
class LcdHd44780:
def __init__(self, rs, e, d):
"""
Initialize the LCD with control (RS, E) and data (D4-D7) pins.
:param rs: Pin number for the RS (Register Select) pin.
:param e: Pin number for the E (Enable) pin.
:param d: List of pin numbers for the data pins (D4-D7).
"""
# Create machine.Pin objects within the constructor
self.RS = Pin(rs, Pin.OUT)
self.E = Pin(e, Pin.OUT)
self.D = [Pin(pin_number, Pin.OUT) for pin_number in d]
# Send initialization sequence
self._init()
def _init(self):
"""
Initialize the HD44780 LCD controller with a predefined sequence of
commands. This method is automatically called in the constructor.
"""
self.RS.off()
time.sleep_ms(20)
self._write_nibble(0x30)
time.sleep_ms(5)
self._write_nibble(0x30)
time.sleep_ms(1)
self._write_nibble(0x30)
time.sleep_ms(1)
self._write_nibble(0x20)
time.sleep_ms(1)
self.command(0x28) # 4-bit, 2 lines, 5x7 pixels
self.command(0x06) # Increment, no shift
self.command(0x01) # Clear display
# Select one command:
# self.command(0x0f) # Display on, cursor on and blinking
# self.command(0x0e) # Display on, cursor on but not blinking
self.command(0x0c) # Display on, cursor off
def _set_data_bits(self, val):
"""
Set the data pins (D4-D7) based on the provided value.
:param val: A 8-bit value where the upper 4 bits are sent to the data pins.
"""
for i in range(4):
# For each pin, set the value according to the corresponding bit
self.D[i].value(val & (1 << (i + 4)))
def _write_nibble(self, val):
"""
Write the upper nibble (4 bits) of the byte to the LCD.
:param val: The upper 4 bits of the byte to write to the LCD.
"""
self._set_data_bits(val)
self.E.on()
time.sleep_us(1)
self.E.off()
def _write_byte(self, val):
"""
Write a byte to the LCD controller by sending both the upper and
lower nibbles.
:param val: The byte to write to the LCD (8 bits).
"""
self._write_nibble(val) # Write upper nibble
self._write_nibble(val << 4) # Write lower nibble
def command(self, cmd):
"""
Send a command byte to the LCD controller. This method writes to
the command register of the LCD (RS = 0).
:param cmd: The command byte to send to the LCD.
"""
# RS pin = 0, write to command register
self.RS.off()
# Write the command
self._write_byte(cmd)
time.sleep_ms(2)
def data(self, val):
"""
Send a data byte to the LCD controller. This method writes to
the data register of the LCD (RS = 1).
:param val: The data byte to send to the LCD.
"""
# RS pin = 1, write to data register
self.RS.on()
# Write the data
self._write_byte(val)
def write(self, s):
"""
Display a string of characters on the LCD. This method writes
each character of the string to the LCD, one by one.
:param s: The string of characters to display on the LCD.
"""
for c in s:
self.data(ord(c))
def move_to(self, line, column):
"""
Move the cursor to a specified position on the LCD. The method
supports two lines.
:param line: The line number (1 or 2).
:param column: The column number (1 to 20).
"""
if line == 1:
cmd = 0x80
elif line == 2:
cmd = 0xc0
else:
return
if column < 1 or column > 20:
return
cmd += column - 1
self.command(cmd)
def custom_char(self, addr, charmap):
"""
This method writes the pixel data for the custom character to one of
the 8 available character generator RAM (CGRAM) locations.
:param addr: The address (0 to 7) in the CGRAM to store the custom
character.
:param charmap: A list of 8 bytes representing the custom character's
pixel pattern.
.. note::
Inspired by `peppe8o <https://peppe8o.com/download/micropython/LCD/lcd_api.py>`_
and `MicrocontrollersLab <https://microcontrollerslab.com/i2c-lcd-esp32-esp8266-micropython-tutorial/>`_.
"""
addr = addr & 0x07
self.command(0x40 | (addr << 3)) # Set CG RAM address
time.sleep_us(40)
for i in range(8):
self.data(charmap[i])
time.sleep_us(40)
self.command(0x80) # Move to origin of DD RAM address
def demo():
"""
Demonstrates the usage of the `LcdHd44780` class by initializing an
LCD display, positioning text, and displaying a sample message.
"""
# Four-data pins order: [D4, D5, D6, D7]
lcd = LcdHd44780(rs=26, e=25, d=[13, 10, 9, 27])
# Default LCD screen
lcd.move_to(1, 3)
lcd.write("Using LCD...")
print("Start using HD44780-based LCD. Press `Ctrl+C` to stop")
try:
# Forever loop
while True:
pass
except KeyboardInterrupt:
# This part runs when Ctrl+C is pressed
print("Program stopped. Exiting...")
# Optional cleanup code
lcd.command(0x01) # Clear display
if __name__ == "__main__" :
# Code that runs only if this script is executed directly
demo()