====== Esp32LCDisplayI2C ======
[[http://www.openhardsoftware.de/ | Open Hard- & Software]]
[
[[http://www.openhardsoftware.de/dokuwiki | DokuWiki]]
[[http://www.openhardsoftware.de/websites | WebSites]]
[[http://www.openhardsoftware.de/mediawiki | MediaWiki]]
[[http://www.openhardsoftware.de/nextcloud | NextCloud]]
]
===== Übersicht =====
* Esp32-Ansteuerung eines LCDisplays mit I2C-Interface(PCF8574)
* das LCDisplay besitzt 4 Zeilen und 20 Spalten
==== Links ====
* [[https://github.com/dhylands/python_lcd | dhylands-python_lcd]]
==== Quell-Code====
**Main-Program: CheckEsp32LCDisplayI2C.py**
#
import time
import machine
import LCDisplayI2C
#
I2CADDRESS_LCDISPLAY_T = 0x27
I2CADDRESS_LCDISPLAY_A = 0x3F
#
LCDISPLAY_COUNT_ROWS = 4
LCDISPLAY_COUNT_COLUMNS = 20
#
def TestLoop():
for S in range(0, 10):
LCDisplay.MoveTo(0, 0)
LCDisplay.PutText('********************')
LCDisplay.MoveTo(1, 0)
LCDisplay.PutText('* Esp32LCDisplay *')
LCDisplay.MoveTo(2, 0)
LCDisplay.PutText('* Version 01V01 *')
LCDisplay.MoveTo(3, 0)
LCDisplay.PutText('********************')
time.sleep_ms(2000)
LCDisplay.Clear()
for P in range(0, 30):
LCDisplay.MoveTo(0, 0)
LCDisplay.PutText('Line0[{}]'.format(time.ticks_ms()))
LCDisplay.MoveTo(1, 0)
LCDisplay.PutText('Line1[{}]'.format(time.ticks_ms()))
LCDisplay.MoveTo(2, 0)
LCDisplay.PutText('Line2[{}]'.format(time.ticks_ms()))
LCDisplay.MoveTo(3, 0)
LCDisplay.PutText('Line3[{}]'.format(time.ticks_ms()))
#
#-------------------------------------------------------------
if '__main__' == __name__:
print('*** CheckEsp32LCDisplayI2C: begin')
#
I2CDisplay = machine.SoftI2C(scl=machine.Pin(22), sda=machine.Pin(21), freq=2000000)
LCDisplay = LCDisplayI2C.CLCDisplayI2C(I2CDisplay, I2CADDRESS_LCDISPLAY_T, \
LCDISPLAY_COUNT_ROWS, LCDISPLAY_COUNT_COLUMNS)
#
TestLoop()
#
print('*** CheckEsp32LCDisplayI2C: end')
#
#
**Library-Module: LCDisplayI2C.py (derived from Basic-Class)**
#
"""Implements a HD44780 character LCD connected via PCF8574 on I2C"""
#
from LCDisplay import CLCDisplay
from time import sleep_ms
#
# The PCF8574 has a jumper selectable address: 0x20 - 0x27
DEFAULT_I2C_ADDR = 0x27
#
MASK_RS = 0x01
MASK_RW = 0x02
MASK_E = 0x04
SHIFT_BACKLIGHT = 3
SHIFT_DATA = 4
#
class CLCDisplayI2C(CLCDisplay):
#
def __init__(self, i2c, i2caddress, countrows, countcolumns):
self.I2C = i2c
self.I2CAddress = i2caddress
self.I2C.writeto(self.I2CAddress, bytearray([0]))
sleep_ms(20) # Allow LCD time to powerup
# Send reset 3 times
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
sleep_ms(5) # need to delay at least 4.1 msec
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
sleep_ms(1)
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
sleep_ms(1)
# Put LCD into 4 bit mode
self.hal_write_init_nibble(self.LCD_FUNCTION)
sleep_ms(1)
CLCDisplay.__init__(self, countrows, countcolumns)
cmd = self.LCD_FUNCTION
if countrows > 1:
cmd |= self.LCD_FUNCTION_2LINES
self.hal_write_command(cmd)
#
def hal_write_init_nibble(self, nibble):
byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA
self.I2C.writeto(self.I2CAddress, bytearray([byte | MASK_E]))
self.I2C.writeto(self.I2CAddress, bytearray([byte]))
#
def hal_backlight_on(self):
self.I2C.writeto(self.I2CAddress, bytearray([1 << SHIFT_BACKLIGHT]))
#
def hal_backlight_off(self):
self.I2C.writeto(self.I2CAddress, bytearray([0]))
#
def hal_write_command(self, cmd):
"""Data is latched on the falling edge of E."""
byte = ((self.Backlight << SHIFT_BACKLIGHT) | (((cmd >> 4) & 0x0f) << SHIFT_DATA))
self.I2C.writeto(self.I2CAddress, bytearray([byte | MASK_E]))
self.I2C.writeto(self.I2CAddress, bytearray([byte]))
byte = ((self.Backlight << SHIFT_BACKLIGHT) | ((cmd & 0x0f) << SHIFT_DATA))
self.I2C.writeto(self.I2CAddress, bytearray([byte | MASK_E]))
self.I2C.writeto(self.I2CAddress, bytearray([byte]))
if cmd <= 3: # The home and clear commands require a worst case delay of 4.1 msec
sleep_ms(5)
#
def hal_write_data(self, data):
byte = (MASK_RS | (self.Backlight << SHIFT_BACKLIGHT) | (((data >> 4) & 0x0f) << SHIFT_DATA))
self.I2C.writeto(self.I2CAddress, bytearray([byte | MASK_E]))
self.I2C.writeto(self.I2CAddress, bytearray([byte]))
byte = (MASK_RS | (self.Backlight << SHIFT_BACKLIGHT) | ((data & 0x0f) << SHIFT_DATA))
self.I2C.writeto(self.I2CAddress, bytearray([byte | MASK_E]))
self.I2C.writeto(self.I2CAddress, bytearray([byte]))
#
#
**Library-Module: LCDisplay.py (Basic-Class)**
"""Provides an API for talking to HD44780 compatible character LCDs."""
#
import time
#
class CLCDisplay:
# HD44780 LCD controller command set
LCD_CLR = 0x01 # DB0: clear display
LCD_HOME = 0x02 # DB1: return to home position
#
LCD_ENTRY_MODE = 0x04 # DB2: set entry mode
LCD_ENTRY_INC = 0x02 # --DB1: increment
LCD_ENTRY_SHIFT = 0x01 # --DB0: shift
#
LCD_ON_CTRL = 0x08 # DB3: turn lcd/cursor on
LCD_ON_DISPLAY = 0x04 # --DB2: turn display on
LCD_ON_CURSOR = 0x02 # --DB1: turn cursor on
LCD_ON_BLINK = 0x01 # --DB0: blinking cursor
#
LCD_MOVE = 0x10 # DB4: move cursor/display
LCD_MOVE_DISP = 0x08 # --DB3: move display (0-> move cursor)
LCD_MOVE_RIGHT = 0x04 # --DB2: move right (0-> left)
#
LCD_FUNCTION = 0x20 # DB5: function set
LCD_FUNCTION_8BIT = 0x10 # --DB4: set 8BIT mode (0->4BIT mode)
LCD_FUNCTION_2LINES = 0x08 # --DB3: two lines (0->one line)
LCD_FUNCTION_10DOTS = 0x04 # --DB2: 5x10 font (0->5x7 font)
LCD_FUNCTION_RESET = 0x30 # See "Initializing by Instruction" section
#
LCD_CGRAM = 0x40 # DB6: set CG RAM address
LCD_DDRAM = 0x80 # DB7: set DD RAM address
#
LCD_RS_CMD = 0
LCD_RS_DATA = 1
#
LCD_RW_WRITE = 0
LCD_RW_READ = 1
#
def __init__(self, num_lines, num_columns):
self.num_lines = num_lines
if self.num_lines > 4:
self.num_lines = 4
self.num_columns = num_columns
if self.num_columns > 40:
self.num_columns = 40
self.CursorY = 0
self.CursorX = 0
self.ImpliedNewline = False
self.Backlight = True
self.DisplayOff()
self.BacklightOn()
self.Clear()
self.hal_write_command(self.LCD_ENTRY_MODE | self.LCD_ENTRY_INC)
self.HideCursor()
self.DisplayOn()
#
def Clear(self):
self.hal_write_command(self.LCD_CLR)
self.hal_write_command(self.LCD_HOME)
self.CursorY = 0
self.CursorX = 0
#
def ShowCursor(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR)
#
def HideCursor(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
#
def BlinkCursorOn(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR | self.LCD_ON_BLINK)
#
def BlinkCursorOff(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
self.LCD_ON_CURSOR)
#
def DisplayOn(self):
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
#
def DisplayOff(self):
self.hal_write_command(self.LCD_ON_CTRL)
#
def BacklightOn(self):
self.backlight = True
self.hal_backlight_on()
#
def BacklightOff(self):
self.backlight = False
self.hal_backlight_off()
#
def MoveTo(self, cursory, cursorx):
self.CursorY = cursory
self.CursorX = cursorx
Address = cursorx & 0x3f
if cursory & 1:
Address += 0x40 # Lines 1 & 3 add 0x40
if cursory & 2: # Lines 2 & 3 add number of columns
Address += self.num_columns
self.hal_write_command(self.LCD_DDRAM | Address)
#
def PutCharacter(self, character):
if character == '\n':
if self.implied_newline:
self.implied_newline = False
else:
self.CursorX = self.num_columns
else:
self.hal_write_data(ord(character))
self.CursorX += 1
if self.CursorX >= self.num_columns:
self.CursorX = 0
self.CursorY += 1
self.implied_newline = (character != '\n')
if self.CursorY >= self.num_lines:
self.CursorY = 0
self.MoveTo(self.CursorY, self.CursorX)
#
def PutText(self, text):
for C in text:
self.PutCharacter(C)
#
def custom_char(self, location, charmap):
location &= 0x7
self.hal_write_command(self.LCD_CGRAM | (location << 3))
self.hal_sleep_us(40)
for i in range(8):
self.hal_write_data(charmap[i])
self.hal_sleep_us(40)
self.MoveTo(self.cursor_y, self.cursor_x)
#
def hal_backlight_on(self):
pass
#
def hal_backlight_off(self):
pass
#
def hal_write_command(self, cmd):
raise NotImplementedError
#
def hal_write_data(self, data):
raise NotImplementedError
#
def hal_sleep_us(self, usecs):
time.sleep_us(usecs)
#
#
===== Entwicklung =====
==== 211216 : Esp32LCDisplayI2C 01V01 ====
* Minimierung abgeschlossen
* Download: {{:module:micropython:Esp32LCDisplayI2C:2112161443_Esp32LCDisplayI2C_01V01.zip|2112161443_Esp32LCDisplayI2C_01V01.zip}}
** VSCode: Testprogramm Esp32LCDisplayI2C 01V01** \\
{{:module:micropython:Esp32LCDisplayI2C:2112161443_VSCodeEsp32LCDisplayI2C.jpg?400|2112161443_VSCodeEsp32LCDisplayI2C.jpg}}
** Funktionsweise Ansteuerung LCDisplayI2C** \\
{{:module:micropython:Esp32LCDisplayI2C:2112161443_Esp32LCDisplayI2C_01V01.mp4|2112161443_Esp32LCDisplayI2C_01V01.mp4}}
==== 211216 : DokuWiki:Esp32LCDisplayI2C ====
* WICHTIG: **LCDisplayI2C(PCF8574T) 4row x 20columns muss mit 5V betrieben werden!**
* Versuch, die Github-Original-Files zu minimieren und optimieren
==== 211215 : Erster Versuch Esp32-LCDisplayI2C ====
* Download [[https://github.com/dhylands/python_lcd | Github: DHylands: lcd_api and i2c_lcd]]
* Erzeugung lcd-Projekt unter VSCode
* Upload aller (25!) Files zum Esp32-MicroPython
* run 'esp8266_i2c_lcd_test.py'
* DEFAULT_I2C_ADDR = 0x27
* i2c = I2C(scl=Pin(22), sda=Pin(21), freq=100000)
* lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 4, 20)
* {{:module:micropython:Esp32LCDisplayI2C:2112151800_Esp32LCDisplayI2C_lcd_00V01.zip|2112151800_Esp32LCDisplayI2C_lcd_00V01.zip}}
{{:module:micropython:Esp32LCDisplayI2C:2112151800_Esp32LCDisplayI2C_lcd_00V01.mp4|2112151800_Esp32LCDisplayI2C_lcd_00V01.mp4}}
-----
[[http://www.openhardsoftware.de/ | Open Hard- & Software]]
[
[[http://www.openhardsoftware.de/dokuwiki | DokuWiki]]
[[http://www.openhardsoftware.de/websites | WebSites]]
[[http://www.openhardsoftware.de/mediawiki | MediaWiki]]
[[http://www.openhardsoftware.de/nextcloud | NextCloud]]
]