module:micropython:esp32displaykey:esp32displaykey
Table of Contents
MicroPython: Esp32DisplayKey
Übersicht
KeyPad4x4
- 4×4 KeyPad: 8x IOPin: 4x Input(34, 35, 36, 39) und 4x Output(12, 13, 14, 27)
- Keyboard-KeyCode-Buffer: SIZE_KEYCODEBUFFER = 5
- minimale Zeitauflösung Erkennung einer Taste: TIME_KEYPRESSED = 0.1
- minimale Zeit zur Erkennung von Tastenwiederholungen: ZeitTIME_KEYREPETITION = 0.5
- Eigener Thread mit permanenter Tastatur-Abfrage
- Entprellung über TIME_KEYPRESSES
- Tasten-Wiederholung über TIME_KEYREPETITION
- MainLoop: periodische Abfrage GetKeyCode()
- Keys beim IT01:
Col : 0 1 2 3 Row 0 : [1]<24> [2]<40> [3]<72> [A]<136> Row 1 : [4]<20> [5]<36> [6]<68> [B]<132> Row 2 : [7]<18> [8]<34> [9]<66> [C]<130> Row 3 : [*]<17> [0]<33> [#]<65> [D]<129>
LCDisplayI2C
- Ansteuerung über I2C (PCF8574)
- Eigener Thread zur Verhinderung von Blockaden ohne time-sleep in MainLoop
- permanente Ausgabe von Zeilen/Spalten in DisplayThread
Version
Beschreibung
Ausgabe MicroPython-Terminal: Esp32CheckDisplayKey.py
- Ausgabe der KeyCodes (mit Wiederholungen)
>>> >>> *** CheckEsp32DisplayKey: begin 66 66 66 34 34 40 40 65 65 65 68 68 136 130 129 40 *** CheckEsp32DisplayKey: end >>>
Library-Module: Define.py
# #----------------------------------------- # Uart0 / 1 / 2 #----------------------------------------- ID_UART0 = 0 PIN_UART0_TX = 1 # USB PIN_UART0_RX = 3 # USB # ID_UART1 = 1 PIN_UART1_RX = 25 # 9 - not usable PIN_UART1_TX = 26 # 10 - not usable # ID_UART2 = 2 PIN_UART2_RX = 16 PIN_UART2_TX = 17 # #----------------------------------------- # LCDisplayI2C #----------------------------------------- I2CADDRESS_LCDISPLAY_T = 0x27 I2CADDRESS_LCDISPLAY_A = 0x3F # LCDISPLAY_COUNT_ROWS = 4 LCDISPLAY_COUNT_COLUMNS = 20 # #----------------------------------------- # Keyboard4x4 #----------------------------------------- PIN_KEYBOARD_IN0 = 39 PIN_KEYBOARD_IN1 = 36 PIN_KEYBOARD_IN2 = 34 PIN_KEYBOARD_IN3 = 35 PIN_KEYBOARD_OUT0 = 13 PIN_KEYBOARD_OUT1 = 12 PIN_KEYBOARD_OUT2 = 14 PIN_KEYBOARD_OUT3 = 27 # SIZE_KEYCODEBUFFER = 5 TIME_KEYPRESSED = 0.1 TIME_KEYREPETITION = 0.5 #
Main-Module: Esp32CheckDisplayKey.py
# import time import machine # import Define as DEF import Thread as THR import LCDisplayI2C as LCD import ThreadDisplay as TDP import Keyboard4x4 as KBD # # #------------------------------------------------------------------ # Main #------------------------------------------------------------------ if ('__main__' == __name__): print('*** CheckEsp32DisplayKey: begin') # # Display I2CDisplay = machine.SoftI2C(scl=machine.Pin(22), sda=machine.Pin(21), freq=2000000) LCDisplay = LCD.CLCDisplayI2C(I2CDisplay, DEF.I2CADDRESS_LCDISPLAY_T, \ DEF.LCDISPLAY_COUNT_ROWS, DEF.LCDISPLAY_COUNT_COLUMNS) ThreadDisplay = TDP.CThreadDisplay(I2CDisplay, LCDisplay) # Keyboard Keyboard = KBD.CKeyboard4x4(DEF.PIN_KEYBOARD_IN0, DEF.PIN_KEYBOARD_IN1, DEF.PIN_KEYBOARD_IN2, DEF.PIN_KEYBOARD_IN3, DEF.PIN_KEYBOARD_OUT0, DEF.PIN_KEYBOARD_OUT1, DEF.PIN_KEYBOARD_OUT2, DEF.PIN_KEYBOARD_OUT3) # Open ThreadDisplay.Open() Keyboard.Open() # # MainLoop .... for I in range(0, 10000): KC = Keyboard.GetKeyCode() if (0 < KC): print(KC) time.sleep(0.001) # # Close Keyboard.Close() ThreadDisplay.Close() # print('*** CheckEsp32DisplayKey: end') # #
Library-Module: Keyboard4x4.py
# import time from machine import Pin # import Define as DEF import Thread as THR # class CKeyboard4x4(): #----------------------------------------------------------------- # Constructor #----------------------------------------------------------------- def __init__(self, \ pinin0, pinin1, pinin2, pinin3, \ pinout0, pinout1, pinout2, pinout3): # self.CountRepeat = 3 self.KeySleep = 0.001 # self.PinIn = [] self.PinIn.append(Pin(pinin0, mode=Pin.IN, pull=Pin.PULL_DOWN)) self.PinIn.append(Pin(pinin1, mode=Pin.IN, pull=Pin.PULL_DOWN)) self.PinIn.append(Pin(pinin2, mode=Pin.IN, pull=Pin.PULL_DOWN)) self.PinIn.append(Pin(pinin3, mode=Pin.IN, pull=Pin.PULL_DOWN)) # self.PinOut = [] self.PinOut.append(Pin(pinout0, mode=Pin.OUT, pull=Pin.PULL_DOWN)) self.PinOut.append(Pin(pinout1, mode=Pin.OUT, pull=Pin.PULL_DOWN)) self.PinOut.append(Pin(pinout2, mode=Pin.OUT, pull=Pin.PULL_DOWN)) self.PinOut.append(Pin(pinout3, mode=Pin.OUT, pull=Pin.PULL_DOWN)) # self.Thread = THR.CThread(self.CBOnStart, self.CBOnBusy, self.CBOnAbort, self.CBOnEnd) # self.KeyCodes = [] return # #----------------------------------------------------------------- # Callback #----------------------------------------------------------------- def CBOnStart(self, thread): return def CBOnBusy(self, thread): while (THR.stBusy == self.Thread.State): KeyCode0 = 0x00 KeyCode1 = 0x00 KeyCode2 = 0x00 KeyCode3 = 0x00 #----------------------------------------- # Row0 #----------------------------------------- self.PinOut[0].on() self.PinOut[1].off() self.PinOut[2].off() self.PinOut[3].off() CS0 = 0 CS1 = 0 CS2 = 0 CS3 = 0 for SI in range(0, self.CountRepeat): CS0 += self.PinIn[0].value() CS1 += self.PinIn[1].value() CS2 += self.PinIn[2].value() CS3 += self.PinIn[3].value() time.sleep(self.KeySleep) if (self.CountRepeat <= CS0): KeyCode0 = 0x11 if (self.CountRepeat <= CS1): KeyCode0 = 0x21 if (self.CountRepeat <= CS2): KeyCode0 = 0x41 if (self.CountRepeat <= CS3): KeyCode0 = 0x81 #----------------------------------------- # Row1 #----------------------------------------- self.PinOut[0].off() self.PinOut[1].on() self.PinOut[2].off() self.PinOut[3].off() CS0 = 0 CS1 = 0 CS2 = 0 CS3 = 0 for SI in range(0, self.CountRepeat): CS0 += self.PinIn[0].value() CS1 += self.PinIn[1].value() CS2 += self.PinIn[2].value() CS3 += self.PinIn[3].value() time.sleep(self.KeySleep) if (self.CountRepeat <= CS0): KeyCode1 = 0x12 if (self.CountRepeat <= CS1): KeyCode1 = 0x22 if (self.CountRepeat <= CS2): KeyCode1 = 0x42 if (self.CountRepeat <= CS3): KeyCode1 = 0x82 #----------------------------------------- # Row2 #----------------------------------------- self.PinOut[0].off() self.PinOut[1].off() self.PinOut[2].on() self.PinOut[3].off() CS0 = 0 CS1 = 0 CS2 = 0 CS3 = 0 for SI in range(0, self.CountRepeat): CS0 += self.PinIn[0].value() CS1 += self.PinIn[1].value() CS2 += self.PinIn[2].value() CS3 += self.PinIn[3].value() time.sleep(self.KeySleep) if (self.CountRepeat <= CS0): KeyCode2 = 0x14 if (self.CountRepeat <= CS1): KeyCode2 = 0x24 if (self.CountRepeat <= CS2): KeyCode2 = 0x44 if (self.CountRepeat <= CS3): KeyCode2 = 0x84 #----------------------------------------- # Row3 #----------------------------------------- self.PinOut[0].off() self.PinOut[1].off() self.PinOut[2].off() self.PinOut[3].on() CS0 = 0 CS1 = 0 CS2 = 0 CS3 = 0 for SI in range(0, self.CountRepeat): CS0 += self.PinIn[0].value() CS1 += self.PinIn[1].value() CS2 += self.PinIn[2].value() CS3 += self.PinIn[3].value() time.sleep(self.KeySleep) if (self.CountRepeat <= CS0): KeyCode3 = 0x18 if (self.CountRepeat <= CS1): KeyCode3 = 0x28 if (self.CountRepeat <= CS2): KeyCode3 = 0x48 if (self.CountRepeat <= CS3): KeyCode3 = 0x88 # if (0 < KeyCode0): self.KeyCodes.append(KeyCode0) if (0 < KeyCode1): self.KeyCodes.append(KeyCode1) if (0 < KeyCode2): self.KeyCodes.append(KeyCode2) if (0 < KeyCode3): self.KeyCodes.append(KeyCode3) # while (DEF.SIZE_KEYCODEBUFFER < len(self.KeyCodes)): self.KeyCodes.pop(0) # if (0 < len(self.KeyCodes)): time.sleep(DEF.TIME_KEYREPETITION) else: time.sleep(DEF.TIME_KEYPRESSED) return def CBOnAbort(self, thread): return def CBOnEnd(self, thread): return #----------------------------------------------------------------- # Manager #----------------------------------------------------------------- def Open(self): self.Thread.Start() return def Close(self): self.Thread.Abort() return def GetKeyCode(self): if (0 < len(self.KeyCodes)): KC = self.KeyCodes.pop(0) return KC return 0 # #------------------------------------------------------------------ # Check Library #------------------------------------------------------------------ if '__main__' == __name__: print('*** Check Keyboard4x4: begin') # Keyboard = CKeyboard4x4(DEF.PIN_KEYBOARD_IN0, DEF.PIN_KEYBOARD_IN1, DEF.PIN_KEYBOARD_IN2, DEF.PIN_KEYBOARD_IN3, DEF.PIN_KEYBOARD_OUT0, DEF.PIN_KEYBOARD_OUT1, DEF.PIN_KEYBOARD_OUT2, DEF.PIN_KEYBOARD_OUT3) # Open Keyboard.Open() # MainLoop .... for I in range(0, 10000): KC = Keyboard.GetKeyCode() if (0 < KC): print(KC) time.sleep(0.001) # Close Keyboard.Close() # print('*** Check Keyboard4x4: end') # #
Library-Module: LCDisplay.py
# 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) # #
Library-Module: LCDisplayI2C.py
# """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: Thread.py
import time import _thread as THR # # States - EStateThread : stIdle = 0 stBusy = 1 stEnd = 2 # class CThread(): # def __init__(self, onstart, onbusy, onabort, onend): self.State = stIdle self.Thread = None self.OnStart = onstart self.OnBusy = onbusy self.OnAbort = onabort self.OnEnd = onend return # def Start(self): self.State = stBusy if (None != self.OnStart): self.OnStart(self) self.ThreadID = THR.start_new_thread(self.CBOnExecute, [self]) return # def Abort(self): self.State = stEnd if (None != self.OnAbort): self.OnAbort(self) return # def CBOnExecute(self, thread): if (None != self.OnBusy): self.OnBusy(self) if (None != self.OnEnd): self.OnEnd(self) return # # #------------------------------------------------------------- # Check Library #------------------------------------------------------------- def OnStart(thread): return def OnBusy(thread): while (stBusy == thread.State): print('.') time.sleep(0.5) return def OnAbort(thread): return def OnEnd(thread): return # if ('__main__' == __name__): print('*** Check Thread: begin') # Thread = CThread(OnStart, OnBusy, OnAbort, OnEnd) Thread.Start() time.sleep(5.0) Thread.Abort() # print('*** Check Thread: end') #
Library-Module: ThreadDisplay.py
# import machine import time # import Define as DEF import Thread as THR import LCDisplayI2C as LCD # class CCommandDisplay(): def __init__(self, lcdisplay): self.LCDisplay = lcdisplay return # def Execute(self): return # class CClear(CCommandDisplay): def __init__(self, lcdisplay): super(CClear, self).__init__(lcdisplay) return def Execute(self): self.LCDisplay.Clear() return # class CWrite(CCommandDisplay): def __init__(self, lcdisplay, row, col, text): super(CWrite, self).__init__(lcdisplay) self.Row = row self.Col = col self.Text = text return def Execute(self): self.LCDisplay.MoveTo(self.Row, self.Col) self.LCDisplay.PutText(self.Text) return # class CThreadDisplay(THR.CThread): # def __init__(self, i2cdisplay, lcdisplay): super(CThreadDisplay, self).__init__(self.OnStart, self.OnBusy, self.OnAbort, self.OnEnd) self.I2CDisplay = i2cdisplay self.LCDisplay = lcdisplay self.CommandList = [] return #--------------------------------------------- def OnStart(self, thread): return def OnBusy(self, thread): while (THR.stBusy == thread.State): self.Clear() Col = 0 while (Col <= 19): self.Write(0, Col, ' Hello0') self.Write(1, Col, ' Hello1') self.Write(2, Col, ' Hello2') self.Write(3, Col, ' Hello3') while (0 < len(self.CommandList)): Command = self.CommandList.pop(0) Command.Execute() time.sleep(0.5) Col += 1 if (THR.stBusy != thread.State): break return def OnAbort(self, thread): return def OnEnd(self, thread): return #--------------------------------------------- def Open(self): self.Start() return def Close(self): self.Abort() return #--------------------------------------------- def Clear(self): self.CommandList.append(CClear(self.LCDisplay)) return def Write(self, row, col, text): self.CommandList.append(CWrite(self.LCDisplay, row, col, text)) return # # #------------------------------------------------------------------------------------------ if ('__main__' == __name__): print('*** CheckEsp32DisplayKey: begin') # I2CDisplay = machine.SoftI2C(scl=machine.Pin(22), sda=machine.Pin(21), freq=2000000) LCDisplay = LCD.CLCDisplayI2C(I2CDisplay, DEF.I2CADDRESS_LCDISPLAY_T, \ DEF.LCDISPLAY_COUNT_ROWS, DEF.LCDISPLAY_COUNT_COLUMNS) TD = CThreadDisplay(I2CDisplay, LCDisplay) TD.Open() # time.sleep(10.0) # TD.Close() # print('*** CheckEsp32DisplayKey: end') # #
Entwicklung
211225 : "echte" Parallelisierung
211224 : Versuch zur Thread-Entkopplung
- Multithreading mit LCDisplay in MicroPython zeigt jetzt (hoffentlich) keine Mucken mehr….
- zweiter Thread zur Tastatur-Überwachung (ohne Blockade)
- Trick: die CommandExecutionTime-Blockaden des Displays in einen Thread auszulagern !
- Klasse CDisplay mit eigenem Thread self.Thread und CCommandList(Row, Col, Text)
- Commands:
- Clear()
- Write(R, C, T)
211223 : Basis
- ganz grosses Problem mit MultiThreading:
- Keyboard4x4 mit eigenem Key-Erkennungs-Thread
- Display mit eigenem Periodic-Display-Thread
- laufen nicht unabhängig voneinander !!! Ganz grosser MIST!!!!
Open Hard- & Software [ DokuWiki WebSites MediaWiki NextCloud ]
module/micropython/esp32displaykey/esp32displaykey.txt · Last modified: 2022/09/13 11:58 by 127.0.0.1