Seite 1 von 4
Funktion beenden
Verfasst: Freitag 3. März 2023, 16:48
von egon11
Hallo, ich möchte ein Programm bauen, welches bei bestimmten Ereignissen eine Funktion auslöst, die jeweilige Funktion soll per while-True-Schleife so lange gehen bis ein anderes Ereignis auftritt. das Ereignis ist eine Fernbedienung.
Jetzt weiß ich aber nicht, wie ich dann so eine Funktion mit Endlosschleife beenden kann.
Könnte mir jemand einen Tipp geben?
Grüße
Re: Funktion beenden
Verfasst: Freitag 3. März 2023, 17:11
von Kebap
Mal ähnlich allgemein gehalten wie deine Frage:
Innerhalb der Endlosschleife prüfst du, ob das Ereignis aufgetreten ist, und beendest die Schleife dann, bzw. reagierst auf das Ereignis, bevor du sie wieder startest.
Re: Funktion beenden
Verfasst: Freitag 3. März 2023, 17:15
von egon11
Ja die Frage war bewusst allgemein gehalten, weil mir es um das Prinzip geht.
In der Schleiße wird etwas endlos ausgeführt.
Re: Funktion beenden
Verfasst: Freitag 3. März 2023, 18:11
von __deets__
Dann muss es eben einen Abbruchbedingung geben, die in der schleifenbedingung oder innerhalb der Schleife geprüft wird, und dann verlässt man die Schleife.
Re: Funktion beenden
Verfasst: Freitag 3. März 2023, 18:58
von __blackjack__
@egon11: Eine Endlosschleife kann man mit ``break``, ``return``, oder einer Ausnahme verlassen. ``return`` nur falls sich die Schleife innerhalb einer Funktion oder Methode befindet. Und dann wäre da noch ``yield`` womit man eine (Generator-)Funktion/Methode anhalten kann, und sich an anderer Stelle entscheiden kann ob man sie irgendwann noch mal weiterlaufen lässt oder nicht.
Re: Funktion beenden
Verfasst: Samstag 4. März 2023, 11:28
von kbr
Das ist event-basierte Programmierung: Du hast eine Hauptschleife die Events erkennt und eventuell auch Status-Informationen speichert. Anhand dessen rufst du aus der Hauptschleife immer die Funktion auf, die zum aktuellen Status passt. Du lagerst also die Endlosschleife aus der Funktion aus.
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 10:15
von Kebap
egon11 hat geschrieben: Freitag 3. März 2023, 17:15
die Frage war bewusst allgemein gehalten, weil mir es um das Prinzip geht.
In der Schleiße wird etwas endlos ausgeführt.
Dennoch wäre ein Beispiel in Code recht hilfreich, um das allgemeine Prinzip abzubilden.
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 18:16
von egon11
Also es geht um eine event-basierte-Schleife.
Genau gesagt geht es um den folgenden Teil:
Code: Alles auswählen
import time
from machine import Pin
from ir_rx import NEC_16
from time import sleep
wert = {0x45:"1", 0x46:"2"}
def callback(data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
#print('Data {:05x} Addr {:04x}'.format(data, addr))
# print(ir_data)#
# print("huhu")
if wert[data] == "1":
eins()
if wert[data] == "2":
zwei()
ir = NEC_16(Pin(16, Pin.IN), callback)
def eins():
while True:
print("eins")
sleep(0.5)
def zwei():
while True:
print("zwei")
sleep(0.5)
Die Methode ist event-basiert.
Nun möchte ich, je nachdem welche Taste gedrückt wurde folgende Methode aufrufen, um sie bei der nächsten Taste die gedrückt wurde wieder anzuhalten.
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 19:09
von __blackjack__
Das geht so gar nicht, weil der `callback` ziemlich sicher nur kurz etwas tun darf, und nicht in einer Endlosschleife enden darf.
Das Beispiel könnte man so ausdrücken (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
from functools import partial
from queue import Empty, Queue
from ir_rx import NEC_16
from machine import Pin
DATA_TO_TEXT = {0x45: "eins", 0x46: "zwei"}
def callback(queue, data, _addr, _ctrl):
if data > 0: # NEC protocol sends repeat codes.
queue.put(DATA_TO_TEXT[data])
def main():
queue = Queue()
_ir = NEC_16(Pin(16, Pin.IN), partial(callback, queue))
text = None
while True:
if text is not None:
print(text)
try:
text = queue.get(timeout=0.5)
except Empty:
pass # Intentionally ignored.
if __name__ == "__main__":
main()
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 21:11
von egon11
Ich wollte den code gerade versuchen, aber leider bietet Micropython mir kein queue an
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 21:47
von __deets__
Micropython kennt asyncio für solche Zwecke. Eine englische Einführung findet sich zB hier:
https://github.com/peterhinch/micropyth ... UTORIAL.md
Kann man sicher mit Deepl auf Deutsch ausreichend gut übersetzen.
Re: Funktion beenden
Verfasst: Montag 6. März 2023, 22:06
von __deets__
Re: Funktion beenden
Verfasst: Dienstag 7. März 2023, 11:21
von Kebap
Wenn du mit Events arbeitest, dann kannst du kein Sleep benutzen, weil sonst das ganze Programm anhält.
Die Hauptschleife darf aber nicht anhalten, sondern muss kontinuierlich prüfen, ob neue Events aufgetreten sind.
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 09:17
von egon11
Jetzt habe ich folgen (funktionierenden) Code
Code: Alles auswählen
wert = {0x45:"1", 0x46:"2"}
async def test1():
while True:
print("methode 1 zum ausfuhren")
await asyncio.sleep(1)
async def test2():
while True:
print("methode 2 zum ausfuhren")
await asyncio.sleep(1)
async def start(x):
print("übergebener Wert " + x)
if x == "1":
task1 = asyncio.create_task(test1())
await asyncio.sleep(3)
print("beenden")
task1.cancel()
if x == "2":
task2 = asyncio.create_task(test2())
await asyncio.sleep(3)
print("beenden")
task2.cancel()
def callback(data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
print(wert[data])
asyncio.run(start(wert[data]))
if __name__ == "__main__":
ir = NEC_16(Pin(16, Pin.IN), callback)
Sie macht erstmal genau das, was sie soll.
Jetzt muss ich noch in der Methode start() einbauen, welche Methode gerade ausgeführt wird oder nicht. Wenn ich das überprüft habe muss ich jene erstmal beenden und dann eine andere starten.
Wenn ich dann aber in der Methode start() `await asyncio.sleep(3)` und ` task2.cancel()` weg lasse, dann werden die Methoden nur 1x ausgeführt.
Das heißt, ich muss es irgendwie schaffen, dass sie dauerhaft laufen, bis man wider etwas drückt, dann die laufende Methode beenden und eine andere startet.
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 10:20
von Kebap
Ich würde da nicht async benutzen. Wie wäre es denn so?
Code: Alles auswählen
def task_1():
print("methode 1 zum ausfuhren")
def task_2():
print("methode 2 zum ausfuhren")
def start(x):
print("übergebener Wert " + x)
if x == "1":
current_task = task_1
if x == "2":
current_task = task_2
current_task()
sleep(0.5)
x = neues_x_bestimmen()
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 10:30
von egon11
Naja es geht ja darum, das die Methoden task_1 und task_2 eine Endlosschleife beinhalten, und dann irgendwann mal abgebrochen werden sollen, wenn sich x ändert.
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 12:19
von __deets__
Geht. Mit. Asyncio. Weil man da tasks cancels kann. Schon probiert?
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 12:22
von egon11
Ja habe schon getestet, aber die Endlosschleifen laufen nicht weiter, siehe mein Code oben, der Code funktioniert so, aber sobald ich task.cancel() raus nehme, dann funktioniert es nicht mehr.
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 12:32
von __deets__
Du kannst einen task dazu benutzen auf ein Ereignis aus dem Interrupt zu warten, und der canceled dann den laufenden & startet den neuen, bevor er wieder wartet auf eine Eingabe.
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 13:00
von egon11
OK, könntest du das anhand von einen kleinen Code zeigen? Ich weiß gerade nicht wie ich das umsetzen sollte.