MicroPython: uasyncio

OP #7337850
Lesenswert?

Im Moment beschäftige ich mich gerade mit Micropython.

Ich habe folgende Problemstellung:

  1. Es soll jede Sekunde ein Zählerwert ausgegeben werden
  2. Gleichzeitig soll es möglich sein, mittels eine User Input (REPL) den Zähler auf 0 zu setzen.

Ich habe es mal mit "uasyncio" probiert und zwei Tasks erzeugt. https://github.com/peterhinch/micropython-async/blob/master/v3/docs/TUTORIAL.md Im einen wird der Wert kontinuierlich ausgeben und der andere versucht, den User-Input zu lesen. Leider scheint aber das lesen wollen eines User-Inputs

1
        x=input()
2
        print(x)

das gesamte System zu blockieren und es geht erst weiter, wenn man eine Taste drückt. Hat jemand eine Lösung für so ein Problem?

Gast #7337986
Lesenswert?

Welcher Controller? Welche Eingabeschnittstelle?

Eingabe via UARTx:

1
...
2

3
z = UARTx.any()                # Anzahl der Zeichen im Eingabepuffer
4

5
if z > 0:
6
    c = UARTx.read(1)          # Zeichen abholen
7
    ...                        # Zeichen verarbeiten   
8

9
...
#7338063
Lesenswert?

Ich habe auf mehreren ESP32 µPython mit uasyncio laufen für Benutzereingaben über TCP und gleichzeitigem ansteueren von sk9822 LEDs. Würde helfen, wenn du uns deinen Code mal zeigst.

Welche Verbindung nutzt du um die REPL aufzurufen? Ich nehme an, der ESP32 ist über USB als virtueller Com-Port am PC erreichbar und du nutzt ein Terminal-Programm?

Alex

OP #7338190
Lesenswert?

Ich habe auf mehreren ESP32 µPython mit uasyncio laufen für Benutzereingaben über TCP und gleichzeitigem ansteueren von sk9822 LEDs.

Klingt gut. Hier ist der Code:

1
import uasyncio
2

3
async def count():
4
    counter=0
5
    while True:
6
        print(counter)
7
        counter=counter+1
8
        await uasyncio.sleep_ms(1000)
9

10
async def userInput():
11
    while True:
12
        print("wait for input")
13
        x=input()
14
        print(x)
15
        await uasyncio.sleep_ms(100)
16
        
17
async def main():
18
    uasyncio.create_task(count())
19
    uasyncio.create_task(userInput())
20
    await uasyncio.sleep_ms(10_000)
21

22
uasyncio.run(main())

Obwohl der Counter jede Sekunde ausgegeben werden sollte, passiert das nur, wenn man den "userInput" drückt. Vielleicht liegt es ja an der Ausgabe und eine LED würde trotzdem blinken.

Gast #7338211
Lesenswert?

Du kannst es mit einer nichtblockierenden Abfrage von 'stdin' lösen.

1
import sys, select
2

3
spoll = select.poll()
4
spoll.register(sys.stdin, select.POLLIN)
5

6
...
7

8
if spoll.poll(0):           # Zeichen im Eingangspuffer von stdin?
9
    c = sys.stdin.read(1)   # Zeichen abholen
10
    print(c)                # Zeichen verarbeiten/ausgeben
11

12
...
OP #7338236
Lesenswert?

Du kannst es mit einer nichtblockierenden Abfrage von 'stdin' lösen.

Danke, das scheint sehr gut zu funktionieren. Ich habe es mal in die Routine mit dem Zähler verpackt:

1
import sys, select
2
import utime as time
3

4
spoll = select.poll()
5

6
spoll.register(sys.stdin, select.POLLIN)
7

8
counter=0
9

10
while True:
11
    if spoll.poll(0):           # Zeichen im Eingangspuffer von stdin?
12
        c = sys.stdin.read(1)   # Zeichen abholen
13
        print("input: "+c)      # Zeichen verarbeiten/ausgeben
14
    time.sleep(0.1)
15
    print(counter)
16
    counter=counter+1

Wenn man es in der "Thonny" Umgebung debugged, muss man erst mal "Enter" drücken. Danach werden immer erst alle Zeichen im Tastaturbuffer gesammel und bei Enter erst übertragen. Das scheint aber eine Eigenschaft von "Thonny" zu sein.

Wenn man es mit minicom benutzt

1
minicom -D /dev/ttyUSB0

funktioniert es perfekt.

OP #7338286
Lesenswert?

Die verwendete Funktion

1
time.sleep(0.1)

bremst das Polling auf 100ms pro Zeichen.
Es wäre besser, das Polling "full speed" während der Wartezeit zu machen. Kennt jemand eine gute Methode dazu?

Es gibt hier

https://docs.micropython.org/en/latest/library/time.html

die Methode time_ticks_diff. Aber ich habe die Befürchtung, dass es einen Zeitbasis Überlauf geben könnte und dann das System hängt:

1
# Wait for GPIO pin to be asserted, but at most 500us
2
start = time.ticks_us()
3
while pin.value() == 0:
4
    if time.ticks_diff(time.ticks_us(), start) > 500:
5
        raise TimeoutError

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren