M5Dial Touch
Vorsicht Falle[Bearbeiten | Quelltext bearbeiten]
Die Verwendung des Touchscreens hält noch einige Hürden bereit.
Das Grundprinzip ist mit M5.Touch.getCount() abzufragen, ob der Touchscreen berührt wird. Nicht berührt wird 0, bei Berührung 1 zurückgegeben.
Das funktioniert aber nicht als Argument für if und while!
Mit der Einschränkung umgehen[Bearbeiten | Quelltext bearbeiten]
Das folgende Programm enthält eine Funktion Test_01 die bei jedem Aufruf den Touch-Status abfragt. Wenn dieser seit der letzten Abfrage von 0 auf 1 gewechselt hat, dann wird ein Flag gesetzt. Solange das Flag gesetzt ist, wird kein weiterer Tastendruck angenommen. Wenn der Touch-Status wieder 0 wird, wird das Flag zurückgesetzt und es kann ein neuer Tastendruck identifiziert werden.
Das hilft aber auch nicht wirklich weiter, weil der Aufruf von test_01 aus einer while-Schleife heraus ebenfalls scheitert.
Ich war auf dem Holzweg[Bearbeiten | Quelltext bearbeiten]
Es gibt eine einfache in der Firmware enthaltene Möglichkeit einen Touch zu erkennen:
Aber auch diese Funktion arbeitet nicht in einer Schleife!
Wie kann ich damit auf einen Touch warten?
Hilfe aus dem Forum[Bearbeiten | Quelltext bearbeiten]
Da habe ich 2 Tage erfolglos versucht den Touchscreen zum laufen zu bekommen. Zu meinem großen Erstaunen hat das M5-Forum dann tatsächlich Hilfe geliefert und das nach 14 Minuten. Bisher kam meistens keine Antwort.
Die Lösung[Bearbeiten | Quelltext bearbeiten]
M5.update() ist die Lösung! Mir ist noch immer nicht klar was diese Funktion macht, aber hier wirkt sie Wunder.
Ideen für eine Touch-Service-Routine[Bearbeiten | Quelltext bearbeiten]
Ich möchte eine Funktion schreiben, die aktiverte Touch-Elemente findet.
Sie soll eine ID des aktivierten Elementes und die Dauer der Berührung zurückgeben oder eine Funktion ausführen und ggf. deren Rückgabe zurückgeben.
Als Eingabe bekommt sie eine Liste, die für jedes abzufragende Touch-Element die folgende Datenstruktur enthält:
Datenstruktur für jedes Touch-Element[Bearbeiten | Quelltext bearbeiten]
Die unten dargestellte Datenstruktur soll für jedes aktuell zu überwachende Touch-Element erstellt und in einer Liste zusammengefasst werden. Diese Liste wird an die Funktion übergeben.
# so: touch_data = {'x1':0, 'y1':0, 'x2':100, 'y2':50, 'id':42, 'func':None} # oder so: touch_data_1 = {'startpoint':(0, 0), 'endpoint':(100, 50), 'id':42, 'func':None}
- x1, y1, startpoint
- die Koordinaten oben links des Touch-Elementes
- x2, y2, endpoint
- die Koordinaten unten rechts des Touch-Elementes
- id
- individuelle Kennung des Touch-Elementes
- func
- Name einer Funktion die ausgeführt werden soll, wenn das Touch-Element aktiviert wird.
Identifikation eines Touch-Elementes[Bearbeiten | Quelltext bearbeiten]
Dieser Codeschnippsel kann als Orientierung dienen:
>>> def detect(x): if 0<x<42: print('innerhalb') else: print('ausserhalb') >>> x = 25 >>> detect(x) innerhalb >>> detect(125) ausserhalb
Mit folgender Abfrage kann ein Touch-Element identifiziert werden:
if x1<x<x2 and y1<y<y2: # dann wurde ein Element gefunden!
Das muss aber noch getestet werden!
Erster erfolgreicher Versuch mit Blockly[Bearbeiten | Quelltext bearbeiten]
Dieses Micropython-Script hat UIFlow2 bei meinem ersten erfolgreichen Versuch die obige Idee zu implementieren erzeugt.
Es werden die 3 Buchstabe "A", "B" und "C" angezeigt. Außerdem befindet sich oben noch ein Feld das "-" anzeigt. Dieses ist das Ausgabefeld. Wenn ein Buchstabe berührt wird erscheint er im Ausgabefeld. Ein Touch auf das Ausgabefeld stellt dieses wieder auf "-".
Zuerst hatte ich die Eingabeflächen 20 x 20 Pixel groß gemacht. Das erbrachte aber nur unsichere Erkennung. Bei 40 x 40 Pixel erfolgt die Erkennung sicher.
Außerdem habe ich die x- und y-Werte nicht wie vorgesehen in Tuple packen können. Diese gibt es in Blockly nicht. Deshalb habe Listen genommen. In einer reinen Micropython Implementierung können wieder Tuple benutzt werden.
import os, sys, io import M5 from M5 import * lab_A = None lab_C = None lab_B = None lab_anzeige = None touch_A = None touch_x = None touch_B = None touch_y = None touch_C = None k = None touch_anzeige = None touch_area = None ergebnis = None def setup(): global lab_A, lab_C, lab_B, lab_anzeige, touch_A, touch_x, touch_B, touch_y, touch_C, touch_anzeige, touch_area, ergebnis, k M5.begin() lab_A = Widgets.Label("A", 50, 120, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24) lab_C = Widgets.Label("C", 170, 120, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24) lab_B = Widgets.Label("B", 110, 185, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu24) lab_anzeige = Widgets.Label("-", 110, 30, 1.0, 0xffffff, 0x222222, Widgets.FONTS.DejaVu40) #Für sicheres Erkennen sind 40x40 Pixel nötig touch_A = {'anfang':[50, 120],'ende':[90, 160],'id':'A','func':'None','arg':'None'} touch_B = {'anfang':[110, 185],'ende':[150, 225],'id':'B','func':'None','arg':'None'} touch_C = {'anfang':[170, 120],'ende':[210, 160],'id':'C','func':'None','arg':'None'} touch_anzeige = {'anfang':[110, 30],'ende':[150, 70],'id':'-','func':'None','arg':'None'} touch_area = [touch_A, touch_B, touch_C, touch_anzeige] def loop(): global lab_A, lab_C, lab_B, lab_anzeige, touch_A, touch_x, touch_B, touch_y, touch_C, touch_anzeige, touch_area, ergebnis, k M5.update() if M5.Touch.getCount(): touch_x = M5.Touch.getX() touch_y = M5.Touch.getY() for k in touch_area: ergebnis = (k['anfang'][0] < touch_x < k['ende'][0]) and (k['anfang'][1] < touch_y < k['ende'][1]) if ergebnis: lab_anzeige.setText(str(k['id'])) lab_anzeige.setVisible(True) if __name__ == '__main__': try: setup() while True: loop() except (Exception, KeyboardInterrupt) as e: try: from utility import print_error_msg print_error_msg(e) except ImportError: print("please update to latest firmware")