Skip to content

Commit 00b7098

Browse files
Synapskidhylands
authored andcommitted
Add driver and example for ESP32 (#15)
* Add driver and example for ESP32 * Update documentation for ESP32
1 parent f3a52d4 commit 00b7098

File tree

3 files changed

+225
-0
lines changed

3 files changed

+225
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Files
3434

3535
| File | Description |
3636
| ----- | ----------- |
37+
| esp32_gpio_lcd.py | ESP32 GPIO HAL |
38+
| esp32_gpio_lcd_test.py | ESP32 test using 4-bit GPIO |
3739
| esp8266_i2c_lcd.py | ESP8266 PCF8574 I2C HAL |
3840
| esp8266_i2c_lcd_test.py | ESP8266 test using PCF8574 backpack |
3941
| i2c_lcd.py | Linux PCF8574 I2C HAL |

lcd/esp32_gpio_lcd.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
"""Implements a HD44780 character LCD connected via ESP32 GPIO pins."""
2+
3+
from lcd_api import LcdApi
4+
from machine import Pin
5+
from utime import sleep_ms, sleep_us
6+
7+
8+
class GpioLcd(LcdApi):
9+
"""Implements a HD44780 character LCD connected via ESP32 GPIO pins."""
10+
11+
def __init__(self, rs_pin, enable_pin, d0_pin=None, d1_pin=None,
12+
d2_pin=None, d3_pin=None, d4_pin=None, d5_pin=None,
13+
d6_pin=None, d7_pin=None, rw_pin=None, backlight_pin=None,
14+
num_lines=2, num_columns=16):
15+
"""Constructs the GpioLcd object. All of the arguments must be machine.Pin
16+
objects which describe which pin the given line from the LCD is
17+
connected to.
18+
19+
When used in 4-bit mode, only D4, D5, D6, and D7 are physically
20+
connected to the LCD panel. This function allows you call it like
21+
GpioLcd(rs, enable, D4, D5, D6, D7) and it will interpret that as
22+
if you had actually called:
23+
GpioLcd(rs, enable, d4=D4, d5=D5, d6=D6, d7=D7)
24+
25+
The enable 8-bit mode, you need pass d0 through d7.
26+
27+
The rw pin isn't used by this library, but if you specify it, then
28+
it will be set low.
29+
"""
30+
self.rs_pin = rs_pin
31+
self.enable_pin = enable_pin
32+
self.rw_pin = rw_pin
33+
self.backlight_pin = backlight_pin
34+
self._4bit = True
35+
if d4_pin and d5_pin and d6_pin and d7_pin:
36+
self.d0_pin = d0_pin
37+
self.d1_pin = d1_pin
38+
self.d2_pin = d2_pin
39+
self.d3_pin = d3_pin
40+
self.d4_pin = d4_pin
41+
self.d5_pin = d5_pin
42+
self.d6_pin = d6_pin
43+
self.d7_pin = d7_pin
44+
if self.d0_pin and self.d1_pin and self.d2_pin and self.d3_pin:
45+
self._4bit = False
46+
else:
47+
# This is really 4-bit mode, and the 4 data pins were just
48+
# passed as the first 4 arguments, so we switch things around.
49+
self.d0_pin = None
50+
self.d1_pin = None
51+
self.d2_pin = None
52+
self.d3_pin = None
53+
self.d4_pin = d0_pin
54+
self.d5_pin = d1_pin
55+
self.d6_pin = d2_pin
56+
self.d7_pin = d3_pin
57+
self.rs_pin.init(Pin.OUT)
58+
self.rs_pin.value(0)
59+
if self.rw_pin:
60+
self.rw_pin.init(Pin.OUT)
61+
self.rw_pin.value(0)
62+
self.enable_pin.init(Pin.OUT)
63+
self.enable_pin.value(0)
64+
self.d4_pin.init(Pin.OUT)
65+
self.d5_pin.init(Pin.OUT)
66+
self.d6_pin.init(Pin.OUT)
67+
self.d7_pin.init(Pin.OUT)
68+
self.d4_pin.value(0)
69+
self.d5_pin.value(0)
70+
self.d6_pin.value(0)
71+
self.d7_pin.value(0)
72+
if not self._4bit:
73+
self.d0_pin.init(Pin.OUT)
74+
self.d1_pin.init(Pin.OUT)
75+
self.d2_pin.init(Pin.OUT)
76+
self.d3_pin.init(Pin.OUT)
77+
self.d0_pin.value(0)
78+
self.d1_pin.value(0)
79+
self.d2_pin.value(0)
80+
self.d3_pin.value(0)
81+
if self.backlight_pin is not None:
82+
self.backlight_pin.init(Pin.OUT)
83+
self.backlight_pin.value(0)
84+
85+
# See about splitting this into begin
86+
87+
sleep_ms(20) # Allow LCD time to powerup
88+
# Send reset 3 times
89+
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
90+
sleep_ms(5) # need to delay at least 4.1 msec
91+
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
92+
sleep_ms(1)
93+
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
94+
sleep_ms(1)
95+
cmd = self.LCD_FUNCTION
96+
if not self._4bit:
97+
cmd |= self.LCD_FUNCTION_8BIT
98+
self.hal_write_init_nibble(cmd)
99+
sleep_ms(1)
100+
LcdApi.__init__(self, num_lines, num_columns)
101+
if num_lines > 1:
102+
cmd |= self.LCD_FUNCTION_2LINES
103+
self.hal_write_command(cmd)
104+
105+
def hal_pulse_enable(self):
106+
"""Pulse the enable line high, and then low again."""
107+
self.enable_pin.value(0)
108+
sleep_us(1)
109+
self.enable_pin.value(1)
110+
sleep_us(1) # Enable pulse needs to be > 450 nsec
111+
self.enable_pin.value(0)
112+
sleep_us(100) # Commands need > 37us to settle
113+
114+
def hal_write_init_nibble(self, nibble):
115+
"""Writes an initialization nibble to the LCD.
116+
117+
This particular function is only used during initialization.
118+
"""
119+
self.hal_write_4bits(nibble >> 4)
120+
121+
def hal_backlight_on(self):
122+
"""Allows the hal layer to turn the backlight on."""
123+
if self.backlight_pin:
124+
self.backlight_pin.value(1)
125+
126+
def hal_backlight_off(self):
127+
"""Allows the hal layer to turn the backlight off."""
128+
if self.backlight_pin:
129+
self.backlight_pin.value(0)
130+
131+
def hal_write_command(self, cmd):
132+
"""Writes a command to the LCD.
133+
134+
Data is latched on the falling edge of E.
135+
"""
136+
self.rs_pin.value(0)
137+
self.hal_write_8bits(cmd)
138+
if cmd <= 3:
139+
# The home and clear commands require a worst
140+
# case delay of 4.1 msec
141+
sleep_ms(5)
142+
143+
def hal_write_data(self, data):
144+
"""Write data to the LCD."""
145+
self.rs_pin.value(1)
146+
self.hal_write_8bits(data)
147+
148+
def hal_write_8bits(self, value):
149+
"""Writes 8 bits of data to the LCD."""
150+
if self.rw_pin:
151+
self.rw_pin.value(0)
152+
if self._4bit:
153+
self.hal_write_4bits(value >> 4)
154+
self.hal_write_4bits(value)
155+
else:
156+
self.d3_pin.value(value & 0x08)
157+
self.d2_pin.value(value & 0x04)
158+
self.d1_pin.value(value & 0x02)
159+
self.d0_pin.value(value & 0x01)
160+
self.hal_write_4bits(value >> 4)
161+
162+
def hal_write_4bits(self, nibble):
163+
"""Writes 4 bits of data to the LCD."""
164+
self.d7_pin.value(nibble & 0x08)
165+
self.d6_pin.value(nibble & 0x04)
166+
self.d5_pin.value(nibble & 0x02)
167+
self.d4_pin.value(nibble & 0x01)
168+
self.hal_pulse_enable()

lcd/esp32_gpio_lcd_test.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Implements a HD44780 character LCD connected via ESP32 GPIO pins."""
2+
3+
from machine import Pin
4+
from esp32_gpio_lcd import GpioLcd
5+
from utime import sleep_ms, ticks_ms
6+
7+
# Wiring used for this example:
8+
#
9+
# 1 - Vss (aka Ground) - Connect to one of the ground pins on you pyboard.
10+
# 2 - VDD - I connected to VIN which is 5 volts when your pyboard is powered via USB
11+
# 3 - VE (Contrast voltage) - I'll discuss this below
12+
# 4 - RS (Register Select) connect to G4 (as per call to GpioLcd)
13+
# 5 - RW (Read/Write) - connect to ground
14+
# 6 - EN (Enable) connect to G11 (as per call to GpioLcd)
15+
# 7 - D0 - leave unconnected
16+
# 8 - D1 - leave unconnected
17+
# 9 - D2 - leave unconnected
18+
# 10 - D3 - leave unconnected
19+
# 11 - D4 - connect to G5 (as per call to GpioLcd)
20+
# 12 - D5 - connect to G18 (as per call to GpioLcd)
21+
# 13 - D6 - connect to G21 (as per call to GpioLcd)
22+
# 14 - D7 - connect to G22 (as per call to GpioLcd)
23+
# 15 - A (BackLight Anode) - Connect to VIN
24+
# 16 - K (Backlight Cathode) - Connect to Ground
25+
#
26+
# On 14-pin LCDs, there is no backlight, so pins 15 & 16 don't exist.
27+
#
28+
# The Contrast line (pin 3) typically connects to the center tap of a
29+
# 10K potentiometer, and the other 2 legs of the 10K potentiometer are
30+
# connected to pins 1 and 2 (Ground and VDD)
31+
#
32+
# The wiring diagram on the following page shows a typical "base" wiring:
33+
# http://www.instructables.com/id/How-to-drive-a-character-LCD-displays-using-DIP-sw/step2/HD44780-pinout/
34+
# Add to that the EN, RS, and D4-D7 lines.
35+
36+
37+
def test_main():
38+
"""Test function for verifying basic functionality."""
39+
print("Running test_main")
40+
lcd = GpioLcd(rs_pin=Pin(4),
41+
enable_pin=Pin(17),
42+
d4_pin=Pin(5),
43+
d5_pin=Pin(18),
44+
d6_pin=Pin(21),
45+
d7_pin=Pin(22),
46+
num_lines=2, num_columns=20)
47+
lcd.putstr("It Works!\nSecond Line\nThird Line\nFourth Line")
48+
sleep_ms(3000)
49+
lcd.clear()
50+
count = 0
51+
while True:
52+
lcd.move_to(0, 0)
53+
lcd.putstr("%7d" % (ticks_ms() // 1000))
54+
sleep_ms(1000)
55+
count += 1

0 commit comments

Comments
 (0)