User Tools

Site Tools


module:micropython:esp32displaykey:esp32displaykey

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
module:micropython:esp32displaykey:esp32displaykey [2021/12/25 14:04] – [Ausgabe MicroPython-Terminal: Esp32CheckDisplayKey.py] omdevelopmodule:micropython:esp32displaykey:esp32displaykey [2022/09/13 11:58] (current) – external edit 127.0.0.1
Line 18: Line 18:
   * minimale Zeit zur Erkennung von Tastenwiederholungen: ZeitTIME_KEYREPETITION = 0.5   * minimale Zeit zur Erkennung von Tastenwiederholungen: ZeitTIME_KEYREPETITION = 0.5
   * Eigener Thread mit permanenter Tastatur-Abfrage   * Eigener Thread mit permanenter Tastatur-Abfrage
 +  * Entprellung über TIME_KEYPRESSES
 +  * Tasten-Wiederholung über TIME_KEYREPETITION
   * MainLoop: periodische Abfrage GetKeyCode()   * MainLoop: periodische Abfrage GetKeyCode()
   * Keys beim IT01:   * Keys beim IT01:
Line 42: Line 44:
  
 ===== Version =====  ===== Version ===== 
-{{:module:micropython:Esp32DisplayKey:2112251329_Esp32DisplayKey_01V02.zip | 2112251329_Esp32DisplayKey_01V02.zip}} +{{:module:micropython:Esp32DisplayKey:2112251413_Esp32DisplayKey_01V03.zip | 2112251413_Esp32DisplayKey_01V03.zip}} 
  
 ===== Beschreibung ===== ===== Beschreibung =====
  
 +{{:module:micropython:Esp32DisplayKey:2112251421_Esp32DisplayKey_01V03.png?600|2112251421_Esp32DisplayKey_01V03.png}}
 ==== Ausgabe MicroPython-Terminal: Esp32CheckDisplayKey.py ==== ==== Ausgabe MicroPython-Terminal: Esp32CheckDisplayKey.py ====
   * Ausgabe der KeyCodes (mit Wiederholungen)   * Ausgabe der KeyCodes (mit Wiederholungen)
Line 70: Line 73:
 >>> >>>
 </code> </code>
-==== Haupt-Module: Esp32CheckDisplayKey.py ====+ 
 +==== Library-Module: Define.py ==== 
 +<code python> 
 +
 +#----------------------------------------- 
 +#   Uart0 / 1 / 2 
 +#----------------------------------------- 
 +ID_UART0     
 +PIN_UART0_TX =  1 # USB 
 +PIN_UART0_RX =  3 # USB 
 +
 +ID_UART1     
 +PIN_UART1_RX = 25 #  9 - not usable  
 +PIN_UART1_TX = 26 # 10 - not usable  
 +
 +ID_UART2     
 +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 
 +
 +</code> 
 + 
 + 
 +==== Main-Module: Esp32CheckDisplayKey.py ====
 <code python> <code python>
 # #
Line 120: Line 170:
  
  
-==== Main-Program: Esp32CheckUart.py ==== +==== Library-Module: Keyboard4x4.py ====
-<code python> +
-</code> +
- +
-==== Library-Module: Uart.py ==== +
-<code python> +
-</code> +
- +
- +
-==== Library-Module: .py ==== +
-<code python> +
-</code> +
- +
-==== Library-Module: .py ==== +
-<code python> +
-</code> +
- +
-==== Library-Module: .py ==== +
-<code python> +
-</code> +
- +
-==== Library-Module: .py ==== +
-<code python> +
-</code> +
- +
-==== Library-Module: .py ====+
 <code python> <code python>
 +#
 +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')
 +    #
 +#
 </code> </code>
  
Line 298: Line 530:
 </code> </code>
  
-==== Library-Module: Define.py ====+ 
 +==== Library-Module: LCDisplayI2C.py ====
 <code python> <code python>
 # #
-#----------------------------------------- +"""Implements a HD44780 character LCD connected via PCF8574 on I2C"""
-#   Uart0 / 1 / 2 +
-#----------------------------------------- +
-ID_UART0     +
-PIN_UART0_TX =  1 # USB +
-PIN_UART0_RX =  3 # USB+
 # #
-ID_UART1      1 +from LCDisplay import CLCDisplay 
-PIN_UART1_RX = 25 #  9 - not usable  +from time import sleep_ms
-PIN_UART1_TX = 26 # 10 - not usable +
 # #
-ID_UART2     +# The PCF8574 has a jumper selectable address: 0x20 - 0x27 
-PIN_UART2_RX = 16 +DEFAULT_I2C_ADDR 0x27
-PIN_UART2_TX 17+
 # #
-#----------------------------------------- +MASK_RS = 0x01 
-#   LCDisplayI2C +MASK_RW = 0x02 
-#----------------------------------------- +MASK_E = 0x04 
-I2CADDRESS_LCDISPLAY_T  0x27 +SHIFT_BACKLIGHT 3 
-I2CADDRESS_LCDISPLAY_A  0x3F+SHIFT_DATA 4
 # #
-LCDISPLAY_COUNT_ROWS    4 +class CLCDisplayI2C(CLCDisplay): 
-LCDISPLAY_COUNT_COLUMNS = 20+    
 +    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])) 
 +    # 
 +#     
 +</code> 
 + 
 +==== Library-Module: Thread.py ==== 
 +<code python> 
 +import time 
 +import _thread as THR
 # #
-#----------------------------------------- +States EStateThread : 
-#   Keyboard4x4 +stIdle 0 
-#----------------------------------------- +stBusy 1 
-PIN_KEYBOARD_IN0 = 39 +stEnd 2
-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 +class CThread(): 
-TIME_KEYPRESSED = 0.1 +    # 
-TIME_KEYREPETITION = 0.5+    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'
 +
 +</code> 
 + 
 +==== Library-Module: ThreadDisplay.py ==== 
 +<code python> 
 +
 +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'
 +    #
 # #
 </code> </code>
Line 347: Line 782:
  
  
 +
 +==== 211225 : "echte" Parallelisierung ====
 +  * {{:module:micropython:Esp32DisplayKey:2112251329_Esp32DisplayKey_01V02.zip | 2112251329_Esp32DisplayKey_01V02.zip}} 
  
 ==== 211224 : Versuch zur Thread-Entkopplung ==== ==== 211224 : Versuch zur Thread-Entkopplung ====
module/micropython/esp32displaykey/esp32displaykey.1640437498.txt.gz · Last modified: 2021/12/25 15:04 (external edit)