Seite 3 von 4
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 17:12
von __deets__
Das ist doch grosser Quatsch. Wieso soll denn irgendwie ein Task aus dem NEC_16 werden? Das hast du doch vorher auch nicht gemacht. Ein simples
Code: Alles auswählen
ir = NEC_16 (Pin(16, Pin.IN), lambda val, addr, ext : callback(command_queue, val, addr, ext))
sollte reichen. Achtung, da ist ein ext drin, weil das der callback wohl braucht. Das habe ich uebersehen, aber hatte dein callback ja auch schon.. ein bisschen mitdenken ist schon erwuenscht.
Laut Code sollte aber auch das hier klappen:
Code: Alles auswählen
ir = NEC_16 (Pin(16, Pin.IN), callback, callback_queue)
weil zusaetzliche Argumente einfach weitergeleitet werden. Dann muss die Signatur des Callbacks so aussehen:
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 21:58
von egon11
Ich habe jetzt das ganze nochmal ausführlich getestet. In der Callback-Funktion ist immer der 1. Parameter data, also die daten, der 2. ist die adresse und der 3. ist ctl (was auch immer das ist) queue ist dann als 4. parameter (durch print getestet).
Dann bin ich nochmal das Beispiel von __deets__ (2. Seite ganz oben) durchgegangen, das zeigte mir, das was dort in der Funktion callback bei dem code 'uasyncio.create_task(queue.put(val))' als Parameter bei 'queue.put' stehen kann was will, denn das kann man in der Funktion dispatcher per 'await queue.get()' ausgeben lassen, bzw wird übermittelt.
Soweit so gut, alles verstanden. Nur genau das macht es in meinen Code nicht. Habe das nochmal geändert wie vorgeschlagen (vielen dank dafür), aber wenn ich das Programm starte, wird startet bei der Funktion dispatcher die while-Schleife nicht.
Hier nochmal der Code, ich denke mal es liegt an der Callback Methode.
Das Objekt queue wird aber am Anfang der Methode dispatcher als print ausgegeben
, also sollte das Prinzip ja funktionieren. Nur die while-Schleife im dispatcher startet nicht.
Code: Alles auswählen
def callback(data, addr, ctl,queue):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
uasyncio.create_task(queue.put(data))
async def dispatcher(queue):
print(queue)
task = None
while True:
command = await queue.get()
print(command)
print("dispatcher")
async def main():
command_queue = Queue()
ir = NEC_16 (Pin(16, Pin.IN), callback, command_queue)
await dispatcher(command_queue)
if __name__ == '__main__':
uasyncio.run(main())
Re: Funktion beenden
Verfasst: Sonntag 12. März 2023, 11:24
von __deets__
Kann ich erstmal nach Studium des NEC_16 Codes so nicht erklaeren - meines Erachtens laeuft das alles nur in IRQs und Timern (die denke ich auch IRQs sind), und sollte dann *eigentlich* problemlos gehen. Die while-Schleife startet auch, das Problem ist eher, dass das queue.put nie durchgefuehrt wird, bzw. nicht die gewuenschten Ergebnisse hat. Denn ich vermute mal das print("Data...") findet statt?
Es kann sein, dass die IRQ/Timer Funktionalitaet da doch irgendwas komisches machen. Ggf. hilft im callback
https://docs.micropython.org/en/latest/ ... n.schedule
einzusetzen, um dadurch dann die Daten in die Queue zu packen via create_task. Also so in etwa:
Code: Alles auswählen
def callback(data, addr, ctl,queue):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
micropython.schedule(lambda: uasyncio.create_task(queue.put(data)))
Re: Funktion beenden
Verfasst: Montag 13. März 2023, 09:50
von egon11
Ja genau, print("Data...") findet statt.
Was mir als Fehler auf die Füße fällt ist, dass mir angezeigt wird, das micropython.schedule 2 Argumente erwartet wird, aber nur 1 gegeben ist.
Laut der Dokumentation sollte aber 1 Argument reichen 'micropython.schedule(func, arg)'.
Jetzt habe ich mal nach dem lambda-Argument einfach ein String angehängt, da wären wieder 3 Argumente gegeben, aber nur 2 würden akzeptiert werden.
Re: Funktion beenden
Verfasst: Montag 13. März 2023, 10:05
von __deets__
Dann muss das lambda einfach ein Argument bekommen, das du ja auch ignorieren kannst.
Re: Funktion beenden
Verfasst: Montag 13. März 2023, 10:11
von egon11
auch mir Argument(en) ist laut Ausgabe nur 1 gegeben.
Re: Funktion beenden
Verfasst: Montag 13. März 2023, 10:18
von __blackjack__
Das Problem dürfte sein, dass `schedule()` *zwei* Argumente will, eine Funktion und ein Argument, und hier egal ob nun mit ``lambda`` oder nicht, nur *eins* übergeben wird, nämlich der Rückgabewert der Funktion die mit dem Argument aufgerufen wurde — statt dort beides zu übergeben, statt die Funktion schon aufzurufen.
Re: Funktion beenden
Verfasst: Montag 13. März 2023, 10:33
von __deets__
Ah. Klar. Beides natürlich. Ein dummy Argument beim Aufruf, und im lambda muss das angegeben werden, aber kann ignoriert werden.
Re: Funktion beenden
Verfasst: Dienstag 14. März 2023, 07:55
von egon11
Das ganze habe ich in
Code: Alles auswählen
micropython.schedule(lambda x:uasyncio.create_task(queue.put(data)),"y")
geändert.
Es läuft ohne Fehler durch, nur die while-Schleife im dispatcher will nicht starten.
Re: Funktion beenden
Verfasst: Dienstag 14. März 2023, 08:40
von __deets__
Dann ist da erstmal das Ende meiner Fahnenstange erreicht. Um das tiefgreifender zu analysieren, müsste ich das selbst auf einem Micro laufen lassen, und ggf. alles auf uasyncio umschreiben. Ob und wann ich dazu komme, kann ich nicht sagen.
Eine Alternative, die aber nicht wirklich deiner Forderung nach einem Task zum abbrechen entspricht , sondern ein ganz anderes Vorgehen bedeutet: Bau einen superloop, der mittels verschiedener Zustandsmaschinen die Aufgabe erledigt. Das ist allerdings eher ätzend, uasyncio ist eigentlich genau das, was man da will. Aber wenn es nicht tut…
Re: Funktion beenden
Verfasst: Dienstag 14. März 2023, 09:31
von egon11
OK trotzdem vielen dank für die Hilfe.
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 09:24
von egon11
Oder kann man das auch noch anders lösen?
Ziel ist: Beim Tastendruck der IR- Fernbedienung soll eine bestimmte Funktion ausgeführt werden, darunter sollen auch Funktionen sein, die eine "while True" Schleife haben (z.b. unendliche Laufleiste der Led's).
Meine nächste Überlegung wäre, in der "while True" -Schleife ein Wert zu überprüfen ob eine Taste gedrückt wurde.
Nur leider fällt mir nichts dazu ein wie und ob überhaupt man das realisieren kann.
Hat dazu jemand noch ein Tipp für mich?
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 10:17
von __deets__
Die Alternative habe ich ja skizziert. Um es ganz klar zu sagen: while True in den Funktionen geht nicht. Das Modell funktioniert nur mit Tasks, weil die cancelbar sind. Eine Hauptschleife mit Zustandsmaschine hingegen geht. Schrieb ich ja schon.
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 10:23
von egon11
Wie meinst du das mit einer Hauptschleife mit Zustandsmaschine?
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 10:30
von __deets__
Eine Schleife & abhängig vom Zustand in verschiedene Funktionen springen, die aber natürlich schnell wiederkehren müssen. Ein verwandtes Stichwort ist superloop. Kannst du mal suchen.
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 11:02
von __deets__
Das ist ja am Ende nur algebraisch umgeformt, sozusagen:
Code: Alles auswählen
def eins():
while True:
print("eins")
sleep(0.5)
def zwei():
while True:
print("zwei")
sleep(0.5)
Das war dein Code. Daraus wird (in Naeherung, und ungetestet)
Code: Alles auswählen
def eins():
print("eins")
def zwei():
print("zwei")
def hauptschleife():
while True:
modus = pruefe_ir_eingabe()
if modus == 1:
eins()
elif modus == 2:
zwei()
Du kannst pro Programm (ohne Scheduler wie asyncio oder threading) halt nur eine Hauptschleife haben.
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 15:00
von Kebap
Sieht ja so ähnlich aus wie mein Ansatz oben..
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 16:36
von __deets__
Voellig richtig, aber es ist ja auch nur die Notloesung. Man will einen solchen Scheduler eigentlich nicht selbst schreiben.
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 16:42
von egon11
Irgenwie ist das mit der Callback-Funktion alles triggi. Wenn ich darin eine While-True Schleife ausführen lasse um auf bestimmte Dinge zu reagieren dann läuft sie nicht weiter...
Re: Funktion beenden
Verfasst: Mittwoch 15. März 2023, 16:50
von __deets__
Im callback darf man das *niemals* machen. Du darfst im callback nur die Information ueber den geaenderten Modus oder Werte an eine staendig laufende Hauptschleife schicken.