Seite 1 von 1
PI Pico UART IRQ mit Callback
Verfasst: Sonntag 26. Oktober 2025, 12:01
von DL3AD
Hallo in die Runde,
ich versuche seit Tagen einen UART IRQ mit Callback ans laufen zu bekommen.
Bei Datenempfang über den UART soll ein IRQ gefeuert werden um dann eine Callback oder ISR aufzurufen.
Hier
https://docs.micropython.org/en/latest/ ... chine-uart habe ich nachgelesen und im Netz nach einem Beispiel gesucht
habe aber nicht brauchbares gefunden oder ans laufen bekommen.
Der µC ist ein original RP2040 board, UART an sich funktioniert tadellos.
Hat jemand vieleicht ein Beispiel oder ein Link wo diese Problematik behandelt wird ?
Frank
Re: PI Pico UART IRQ mit Callback
Verfasst: Montag 27. Oktober 2025, 13:52
von __blackjack__
@DL3AD: Was ist denn das konkrete Problem?
Wie es aussieht kann man sich beim Pico nur einen IRQ generieren lassen wenn die RX-Leitung „idle“ wird, also wenn die Gegenseite aufhört Zeichen zu schicken oder zumindest eine Pause einlegt. Nicht für jedes einzelne empfangene Zeichen.
Welches Problem soll denn mit IRQs hier gelöst werden?
Re: PI Pico UART IRQ mit Callback
Verfasst: Montag 27. Oktober 2025, 15:23
von DeaD_EyE
Nicht jede Architektur unterstützt die IRQs. Hier ist eine Tabelle:
https://docs.micropython.org/en/latest/ ... T.html#id1
UART unterstützt
asyncio.Stream beim rp2 leider noch nicht.
Beim esp32 ist es bereits implementiert.
Man kann sich aber einen eigenen Wrapper für asyncio bauen. Ist zwar nicht so effizient, aber funktioniert.
Die Frage ist, wie schnell willst du reagieren? Kommt es auf weniger als 10 ms an?
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 07:28
von DL3AD
@__blckjack__,
genau den Fall wenn die RX-Leitung "idle" wird.
Ich möchte eine Funktion aufrufen und was mit den Daten machen.
Bisher habe ich es nicht hinbekommen und suche nach einem Beispiel andem ich mich orientieren kann.
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 14:24
von __blackjack__
@DL3AD: Was hast Du denn gemacht und was funktioniert daran nicht? Und was willst Du mit den Daten machen? Denn in einem ISR darf man ja so gut wie gar nichts machen. Alles was neuen Speicher dynamisch anfordern könnte ist Tabu und das ist in Python so gut wie alles.
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 14:51
von DeaD_EyE
Bei harten Interrupts kann man keinen Speicher zuweisen, d.h. man muss außerhalb der Funktion (z.B. auf Modulebene) einen Buffer (z.B. bytearray) anlegen und diesen dann beim Aufruf des IRQ befüllen.
Code: Alles auswählen
from machine import UART, Pin
BUFFER_SIZE = 256
def uart_rx_idle(uart: UART):
if uart.any():
uart.readinto(uart_rx_buffer)
uart_rx_buffer = bytearray(BUFFER_SIZE)
uart = UART(1, baudrate=9600, rx=Pin(10), tx=Pin(11), rxbuf=BUFFER_SIZE)
uart.irq(handler=uart_rx_idle, trigger=UART.IRQ_RXIDLE, hard=False)
# handler is an optional function to be called when the interrupt event triggers.
# The handler must take exactly one argument which is the UART instance.
# kein harter Interrupt, aber es ist trotzdem besser, den Buffer zu verwenden
Code nicht getestet.
Wenn der IRQ
RXIDLE kommt, prüft der
handler, ob daten verfügbar sind und falls ja, werden die Daten vom
rxbuffer des UART in den uart_rx_buffer (bytearray) kopiert.
Der Speicher für den Buffer ist aber bereits vergeben und wird nicht beim Aufruf des Interrupts zugewiesen. D.h. der Code sollte auch mit harten Interrupts funktionieren, sofern der RP2 das unterstützt.
Wenn man die Methode uart.read(xxx) nutzt, wird, soweit ich weiß, neuer Speicher zugewiesen.
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 16:09
von __blackjack__
Die Frage an der Stelle ist warum man das so machen sollte, denn man kopiert hier ja nur aus dem Puffer den `UART` schon hat, in einen anderen Puffer um. Wirklich etwas interessantes kann man nur ausserhalb der ISR machen, da braucht man aber diesen zusätzlichen Puffer nicht wirklich.
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 16:48
von DL3AD
Hallo,
Danke für eure Hilfe - nun funktioniert es.
Code: Alles auswählen
from machine import UART, Pin
def myuart_rx(myuart: UART):
print(myuart.read().decode())
myuart = UART(0, baudrate=9600, rx=Pin(1), tx=Pin(0))
myuart.irq(handler=myuart_rx, trigger=UART.IRQ_RXIDLE, hard=False)
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 18:06
von DeaD_EyE
__blackjack__ hat geschrieben: Dienstag 28. Oktober 2025, 16:09
Die Frage an der Stelle ist warum man das so machen sollte, denn man kopiert hier ja nur aus dem Puffer den `UART` schon hat, in einen anderen Puffer um. Wirklich etwas interessantes kann man nur ausserhalb der ISR machen, da braucht man aber diesen zusätzlichen Puffer nicht wirklich.
Das Modul machine ist in C implementiert. Der UART-Buffer ist dementsprechend nicht direkt von Micropython aus erreichbar. Der zweite Buffer ist unumgänglich, wenn man mit IRQs arbeitet. Die Frage ist halt immer noch, wozu? Interrupts verwendet man, wenn man sehr schnell reagieren muss. Wenn 10 ms reichen, sollte man eher Asyncio nutzen. Leider muss man seinen eigenen Wrapper beim RP2 konstruieren, da asyncio.Stream nur UART-Objekte unterstützt, die die ioctl Methode unterstützen. Soweit ich weiß ist es beim ESP32 implementiert.
Wenn man das z.B. mit pyserial für CPython vergleicht, so ist die Nutzung von asyncio mit Micropython und UART einfacher. Micropythons asyncio fehlen noch einige Funktionen/Klassen. Das ist ein minimalistisches asyncio.
Re: PI Pico UART IRQ mit Callback
Verfasst: Dienstag 28. Oktober 2025, 20:06
von __blackjack__
@DeaD_EyE: Im ISR wird man den UART-internen Puffer ja nur in den eigenen Puffer umkopieren damit der normale Code etwas damit machen kann und da braucht man dass dann aber nicht umkopieren, denn im normalen Code kann man ja einfach die Daten aus dem internen Puffer anfordern, und das ohne sich Gedanken darüber machen zu müssen welche Einschränkungen für ISRs gelten.
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 09:08
von DeaD_EyE
__blackjack__ hat geschrieben: Dienstag 28. Oktober 2025, 20:06
@DeaD_EyE: Im ISR wird man den UART-internen Puffer ja nur in den eigenen Puffer umkopieren damit der normale Code etwas damit machen kann und da braucht man dass dann aber nicht umkopieren, denn im normalen Code kann man ja einfach die Daten aus dem internen Puffer anfordern, und das ohne sich Gedanken darüber machen zu müssen welche Einschränkungen für ISRs gelten.
Während im MainThread nach der Unterbrechung gelesen wird, können sich schon wieder neue Daten im Puffer befinden. Man muss kopieren und auch etwas zur Synchronisation nutzen. Besser wäre eine Queue. Dann ist die Synchronisation kostenlos mit dabei.
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 09:45
von __blackjack__
@DeaD_EyE: Aber genau das gleiche kann einem doch auch beim ISR passieren. Auch dort kann ein weiterer IRQ ausgelöst werden, bevor der normale Code dazu kommt den letzten kopierten Puffer zu verarbeiten. Diese angebliche Notwendigkeit läuft darauf hinaus, dass ein Protokoll verwendet wird, wo man aus den Nachrichten nicht erkennen kann wo sie anfangen/enden wenn man dazu den „idle“-Zustand des Senders missbraucht. Das wäre fehleranfällig und sollte beim Protokoll repariert werden.
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 12:44
von DeaD_EyE
__blackjack__ hat geschrieben: Mittwoch 29. Oktober 2025, 09:45
@DeaD_EyE: Aber genau das gleiche kann einem doch auch beim ISR passieren. Auch dort kann ein weiterer IRQ ausgelöst werden, bevor der normale Code dazu kommt den letzten kopierten Puffer zu verarbeiten. Diese angebliche Notwendigkeit läuft darauf hinaus, dass ein Protokoll verwendet wird, wo man aus den Nachrichten nicht erkennen kann wo sie anfangen/enden wenn man dazu den „idle“-Zustand des Senders missbraucht. Das wäre fehleranfällig und sollte beim Protokoll repariert werden.
Vielleicht kann das passieren. Typischerweise wird beim ISR der Code so minimal gehalten, dass es abgearbeitet werden kann, bevor die nächsten Daten kommen. Wie schnell der RX-Idle nacheinander ausgelöst werden kann, hängt dann von der eingestellten Baudrate ab. Der Code im MainThread wird solange unterbrochen, bis der ISR-Handler fertig ist. Was dann passieren kann, dass der nächste ISR ausgelöst wird, bevor der MainThread wieder dran ist.
Wie auch immer. Ich glaube, die Diskussion führt nicht weiter. Jedenfalls ist der ISR nicht aus Langeweile implementiert worden. AFIK war es eine Anforderung von jemanden und ist gesponsort worden. D.h. einen echten Anwendungsfall gibt es definitiv.
Und nochmal zur Klarstellung, ich würde
asyncio nutzen, wenn 10ms in Ordnung sind. IRQs sind immer problematisch, aber oftmals benötigt.
Für ein zukünftiges Projekt habe ich geprüft, ob es machbar ist, Encoder-Signale via GPIO einzulesen, diese via CAN-Bus @500 kbit/s zu übertragen und auf der Gegenseite mit einem RPi Zero + USBCan auf den GPIO-Pins auszugeben. Der RPi war jetzt die denkbar schlechteste Lösung, weil 1. der USB-Port Latenzen hat, das OS dazwischen hängt und der ISR Python-Code war. Trotz dessen hatte ich nur eine Latenz von 500 bis 700 µS gemessen. Der Sender war ein ESP32S3 + Can-Transceiver. TWAI ist beim ESP32 integriert. Die nennen das so, weil nicht der komplette Can-Bus Standard unterstützt wird. Wenn ich später beide Seiten mit Mikrocontroller realisiert habe, werde ich sicherlich nochmal 100-300 µs einsparen können. Ein Byte @500kbit/s => 16 µs
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 12:54
von __blackjack__
@DeaD_EyE: Das es echte Anwendungsfälle gibt will ich gar nicht in Frage stellen. Die sind aber schon recht speziell und mich würde halt schon interessieren was *hier* der konkrete Anwendungsfall ist, damit man da keine Zeit mit verschwendet wenn das kein sinnvoller oder machbarer Fall ist. Mir würden auch eher sinnvolle Fälle für IRQ nach jedem Zeichen statt wenn IDLE einfallen, aber das gibt der Pico ja nicht her.
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 16:50
von DL3AD
... in meinem Fall kommen von einem Solarregler alle 1000ms Statusdaten die sollen eingelesen einige aufgedröselt und auf einem Display ausgegeben werden.
Da ist massig Zeit zum auswerten.
Hatte zuvor eine Lösung über die Mainloop mit uart.any() gebaut - funktioniert auch tadellos - fand die Sache mit dem ISR interessant und das funktioniert dank Eurer Hilfe nun auch.
Es ist ja nicht falsch verschiedene Lösungen zu probieren - so hat man Ansätze for zukünftige Bastelprojekte
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 17:54
von __blackjack__
Naja, ist halt nicht wirklich ein ISR. Alleine das simple Beispiel ginge schon nicht als ISR weil `decode()` für das Ergebnis neuen Speicher anfordert.
Re: PI Pico UART IRQ mit Callback
Verfasst: Mittwoch 29. Oktober 2025, 18:14
von DL3AD
jaaaa - mir ging es um die Funktionalität mit dem IRQ
