Hallo zusammen! Ich versuche gerade mit dem Raspberry Pi Pico eine RS485 Verbindung zu entwickeln. Leider bin ich da auf einige Schwierigkeiten gestoßen. Für eine saubere Kommunikation via RS485 muss der "output enable" des Trasceivers richtig angesteuert werden. Beim Start des Frames ist das kein Problem, ich kann den Enable ja im gleichen Abschnitt setzten, in dem ich die Daten in die UART schreibe. Am Ende des Frames ist das leider nicht so einfach, weil ich keinen passenden Interrupt gefunden habe. Notwendig wäre ein Interrupt, der erst ausgelöst wird, wenn das Byte wirklich verschickt ist. Es gibt zwar ein BUSY Bit, aber keinen Interrupt dazu. Ich könnte das Bit zwar pollen, aber das ist keine gute Lösung. Hab ich was im Datenblatt übersehen? Gibt es noch eine andere Möglichkeit den output enable zu setzen?
Friedrich K. schrieb: > Gibt es noch eine andere Möglichkeit den output enable zu setzen? Receiver beim Senden eingeschaltet lassen und das Echo der gesendeten Daten auswerten.
> Es gibt zwar ein BUSY Bit, aber keinen Interrupt dazu. Wirklich? Das waere aber echt traurig wenn die das vergessen haetten. > Gibt es noch eine andere Möglichkeit den output enable zu setzen? Du koenntest beim uebertragen des letzen Bytes deines Paketes einen Timer ueber die Uebertragungszeit starten. Oder du implementierst alles selber ueber einen PIO. Olaf
Friedrich K. schrieb: > Notwendig wäre ein Interrupt, der > erst ausgelöst wird, wenn das Byte wirklich verschickt ist. Korrekt. Den gibt es aber sicherlich auch beim RP2040. Hab ich aber noch nicht danach gesucht.
Hmmm schrieb: > Receiver beim Senden eingeschaltet lassen und das Echo der gesendeten > Daten auswerten. Das scheint mit eine gute Lösung zu sein wenn man pollen möchte, insbesondere da die UARTs 32Byte tiefe FIFOs ihr Eigen nennen. Einfach den Rx-FIFO lesen bis das letzte Byte herein gekommen ist und dann abschalten. Wer's mit einem IRQ braucht, einfach den Rx-FIFO per DMA einlesen, der schreit dann nicht nur wenn er fertig ist, der kann die Abschaltung voll automagisch durchführen (chained) Oder aber mit Timer: Timer primen, Daten in den Tx-FIFO, Timer starten, wenn IRQ dann abschalten.
Wenn man bei Google nach "PL011 uart rs485" findet man u.a. das: https://lore.kernel.org/linux-arm-kernel/20200107072831.GB1014453@kroah.com/T/
> Hab ich aber noch nicht danach gesucht.
Mach mal, ich hab gerade auch mal kurz ruebergeschaut und auch nix
gefunden. Allerdings ist die Qualitaet des Datenblatt an dieser
Stelle auch ziemlich unterirdisch.
Olaf
Solch einen speziellen Interrupt gibt es nicht. Am ehesten kann man das BUSY Bit befragen, das aber wie gesagt keinen Interrupt auslösen kann. Man wird sich also anderer Methoden für diesen speziellen Fall bedienen müssen. Die schon erwähnte PIO Lösung ist fraglos die eleganteste Methode und braucht (als netter Nebeneffekt) Null CPU Zyklen. Außerdem kann sie auf einige wenige Nanosekunden genau den Transceiver ein- und abschalten. ›Fire and Forget‹ um es mal martialisch auszudrücken. ;-)
Norbert schrieb: > Die schon erwähnte PIO Lösung ist fraglos die eleganteste Methode und > braucht (als netter Nebeneffekt) Null CPU Zyklen. Außerdem kann sie > auf einige wenige Nanosekunden genau den Transceiver ein- und > abschalten. Was ja gerade bei einem UART soooo wichtig ist . . . Man kann das Problem mit externer Hardware lösen, mittels flankengetriggertem Monoflop.
> Man kann das Problem mit externer Hardware lösen, mittels > flankengetriggertem Monoflop. Ach komm, das ist doch eine Loesung der mangelt es etwas an Eleganz. :) Man koennte es auch den zweiten Core uebernehmen lassen alles im Auge zu behalten. Es gibt ja keinen Mangel an Rechenleistung. Aber PIO ist doch fuer sowas von geradezu schlichter Eleganz. Aber letztlich haengt es natuerlich ab was man sonst noch auf der Kiste laufen haben will.... Traurig ist es nur wenn die das wirklich in ihrem Verilog-Core vergessen haben. Zeigt mir mal wieder das der RP2040 eher von Programmierern als von Hardwaremenschen entwickelt wurde. Olaf
Norbert schrieb: > Die schon erwähnte PIO Lösung ist fraglos die eleganteste Methode Wie Du schon geschrieben hattest, wäre die Verwendung eines (timeout-)Timers die einfachste Vorgehensweise. Falls alle acht Timer schon belegt sind, kann man auch einen DMA-Controller "leer" laufen lassen: Ziel=Quelle und Tranfercount= Wartezeit. Bei niedrigen Baudraten könnte man BUSY im 1 ms Interrupt abfragen. Olaf schrieb: > Allerdings ist die Qualitaet des Datenblatt an dieser > Stelle auch ziemlich unterirdisch. Arduino-LIB-Klicker brauchen kein Datenblatt ;-) Es zeigt sich aber auch, daß der RP2040 nicht gerade für Embedded-Anwendungen konzipiert ist. Von allem ein wenig, aber wenn es speziell wird, wird es eng. Egal, ein schnelles Teil, was man schön übertakten kann und lieferbar ist. Olaf schrieb: > Zeigt mir mal wieder das der RP2040 eher von Programmierern als > von Hardwaremenschen entwickelt wurde. Sag ich doch!
Olaf schrieb: > Traurig ist es nur wenn die das wirklich in ihrem Verilog-Core vergessen > haben. Zeigt mir mal wieder das der RP2040 eher von Programmierern als > von Hardwaremenschen entwickelt wurde. Sie haben einfach den PrimeCell UART (PL011) von ARM genommen, welcher keine Unterstützung für RS485 hat. Die Originaldokumentation von ARM ist im RP2040-Datenblatt auch verlinkt.
Olaf schrieb: >> Man kann das Problem mit externer Hardware lösen, mittels >> flankengetriggertem Monoflop. > > Ach komm, das ist doch eine Loesung der mangelt es etwas an Eleganz. :) Es reicht auch ein Spar-Monoflop, siehe Anhang. Einen "riesigen" IC ala 73HC123 braucht es nicht. Mittels R1 wird die Zeitkonstante eingestellt, sie sollte bei ca. 15-20 Bitzeiten liegen. C1 sollte man nicht allzu groß machen, denn der belastet das TXD Signal. Klar ist eine Softwarelösung eleganter, aber manchmal artet die in einen Krampf aus, wie hier.
> Klar ist eine Softwarelösung eleganter, aber manchmal artet die in einen > Krampf aus, wie hier. Ich fand eigentlich die Beschaeftigung mit der PIO eine durchaus intellektuell stimulierende Erfahrung welche dem Umgang mit dem RP2040 etwas Wuerze verleiht. Ausserdem glaube ich mich dunkel zu entsinnen das ein serieller Ausgang fuer die PIO im Datenblatt als Beispiel drin war. Olaf
Falk B. schrieb: > Olaf schrieb: >>> Man kann das Problem mit externer Hardware lösen, mittels >>> flankengetriggertem Monoflop. >> >> Ach komm, das ist doch eine Loesung der mangelt es etwas an Eleganz. :) > > Es reicht auch ein Spar-Monoflop, siehe Anhang. Einen "riesigen" IC ala > 73HC123 braucht es nicht. Mittels R1 wird die Zeitkonstante eingestellt, > sie sollte bei ca. 15-20 Bitzeiten liegen. C1 sollte man nicht allzu > groß machen, denn der belastet das TXD Signal. So ein Schwachsinn! Am besten noch mit Röhren aufbauen :-( > Klar ist eine Softwarelösung eleganter, aber manchmal artet die in einen > Krampf aus, wie hier. Mit einem Timer ist der Bastler klar überfordert!
Olaf schrieb: >> Klar ist eine Softwarelösung eleganter, aber manchmal artet die > in einen >> Krampf aus, wie hier. > > Ich fand eigentlich die Beschaeftigung mit der PIO eine durchaus > intellektuell stimulierende Erfahrung welche dem Umgang mit dem RP2040 > etwas Wuerze verleiht. Ausserdem glaube ich mich dunkel zu entsinnen das > ein serieller Ausgang fuer die PIO im Datenblatt als Beispiel drin war. > > Olaf Ich glaube du unterliegst hier einer groben Fehleinschätzung. ;-) Wenn man hier im µC Forum die Wahl zwischen einer Lösung mit Bordmitteln eines Controllers und einer Lösung mit angepflanzter TTL-Technik (besser noch Röhrentechnik) hat, so wird selbstverständlich die Röhre bevorzugt.
Uuuuahhh, m.n. du hast mich auf der Zielinie überholt ;-)
P.S. schrieb: > Wenn man bei Google nach "PL011 uart rs485" findet man u.a. das: > https://lore.kernel.org/linux-arm-kernel/20200107072831.GB1014453@kroah.com/T/ Hier noch die Diskussion, wie man das verwendet: https://forums.raspberrypi.com/viewtopic.php?t=319618 Damit wird dies komplett im Kernel Treiber hantiert und die Applikation muss sich nicht mehr darum kümmern. Michael
Michael D. schrieb: > P.S. schrieb: >> Wenn man bei Google nach "PL011 uart rs485" findet man u.a. das: >> https://lore.kernel.org/linux-arm-kernel/20200107072831.GB1014453@kroah.com/T/ > > Hier noch die Diskussion, wie man das verwendet: > https://forums.raspberrypi.com/viewtopic.php?t=319618 > > Damit wird dies komplett im Kernel Treiber hantiert und die Applikation > muss sich nicht mehr darum kümmern. > > Michael Ich denke du verwechselst ›Raspberry Pi‹ mit ›Raspberry Pi Pico‹. Letzterer ist ein Board mit einem einfachen Controller RP2040 aber ohne Linux.
Norbert schrieb: > Ich denke du verwechselst ›Raspberry Pi‹ mit ›Raspberry Pi Pico‹. > Letzterer ist ein Board mit einem einfachen Controller RP2040 aber ohne > Linux. Beide verwenden den PL011 UART. Der Code im Linux-Kernel kann also in diesem Fall hilfreich sein.
Olaf schrieb: >> Es gibt zwar ein BUSY Bit, aber keinen Interrupt dazu. > > Wirklich? Das waere aber echt traurig wenn die das vergessen haetten. Dieses BUSY-Bit entspricht dem THRE* im LSR der guten alten 8250, und die hat dafür ebensowenig einen Interrupt, wie auch das unmittelbare Vorbild der PL011 den nicht hat, die 16550. Bessere UARTs können von sich aus die RS485-Sender/Empfänger-Umschaltung ansteuern, so z.B. die (mittlerweile nicht mehr produzierten) UARTs von Oxford Semiconductor, oder die UARTs in vielen USB-Seriell-Bridges. So etwas bei einem für Embedded-Anwendungen gedachten µC zu übersehen ist unverständlich. *) transmitter holding register empty und line status register
DerEgon schrieb: > So etwas bei einem für Embedded-Anwendungen gedachten µC zu übersehen > ist unverständlich. Es ist verständlich, denn RS485 ist nicht der heiße Scheiß von morgen, sondern der Oldie von vorgestern. Und wenn man da einfach einen Standard-UART mit eingebaut hat, bastelt da keiner mehr dran rum. Viel zu teuer, wenn denn überhaupt möglich. Es gibt einen Workaround, so what. Den Erfolg des RP2040 tut das nicht verhindern.
:
Bearbeitet durch User
Falk B. schrieb: > Es ist verständlich, denn RS485 ist nicht der heiße Scheiß von morgen, > sondern der Oldie von vorgestern. Aha. Und was ist in Deinen professionell erfahrenen Augen der heiße Scheiß von morgen?
https://www.amazon.de/SODIAL-USB-zu-USB-RS485-485-Konverter-Adapter-Unterstuetzung-Win7-Vista-Linux/dp/B00K67XKVI Diese USB <-> RS485 Adapter schalten die Richtung automatisch um und werden von Linux out-of-the-box unterstützt.
Steve schrieb: > https://www.amazon.de/SODIAL-USB-zu-USB-RS485-485-Konverter-Adapter-Unterstuetzung-Win7-Vista-Linux/dp/B00K67XKVI > > Diese USB <-> RS485 Adapter schalten die Richtung automatisch um und > werden von Linux out-of-the-box unterstützt. Schön, nur daß der RP2040 weder Linux noch USB nutzt ;-)
Steve schrieb: > https://www.amazon.de/SODIAL-USB-zu-USB-RS485-485-Konverter-Adapter-Unterstuetzung-Win7-Vista-Linux/dp/B00K67XKVI > > Diese USB <-> RS485 Adapter schalten die Richtung automatisch um und > werden von Linux out-of-the-box unterstützt. Manchmal, nur manchmal, also wenn man einen Thread von Anfang an liest, nicht nur ansieht, nein wirklich liest, dann gewinnt man plötzlich - wie aus dem Nichts - völlig neue Erkenntnisse.
> Es ist verständlich, denn RS485 ist nicht der heiße Scheiß von morgen, > sondern der Oldie von vorgestern. Aehem...ich glaube du hast keine Ahnung was derzeit so verkauft und installiert wird. :-) Wobei ich sogar glaube das es RS485 Driver gibt die das automatisch koennen. Leider faellt mir die Nummer gerade nicht ein. Allerdings sollte man sich nicht nur auf RS485 versteifen, ein IRQ wenn ein Byte wirklich draussen ist und nicht erst im letzten Schieberegister hab ich auch schon bei ganz anderen Anwendungen gebraucht. Naja, ich hatte auch schon einen Controller von Renesas in den Fingern der hat den IRQ ausgeloesst wenn das letzte Bit halb draussen war. Das hat dann oft funktioniert, bloss leider bei manchen Mondphasen, Temperaturen und Kabellaengen nicht. War ein super Spass... Olaf
Mein Senf: Unbedingt in Hardware machen (also PIO). Die Softwareloesung kann man zwar auf dem uC (aber nicht auf einem RPi unter Linux) mit einem Timer erledigen, jedoch da gibt es genuegend Stolperfallen, gerade wenn es um schnelle Taktraten und Modbus-Timings geht. Aus diesem Grund nehmen wir fuer Industrieanwendungen ausschliesslich Controller (respektive FPGA) deren UART RS485-Protokolle in der Hardware beherrschen.
DerEgon schrieb: > So etwas bei einem für Embedded-Anwendungen gedachten µC zu übersehen > ist unverständlich. Das hat, denke ich mal, einfach mit dem Preis zu tun. Die PL011 IP ist wahrscheinlich viel billiger als eine modernere UART IP mit RS485, LIN, etc.
Olaf schrieb: > Traurig ist es nur wenn die das wirklich in ihrem Verilog-Core vergessen > haben. Zeigt mir mal wieder das der RP2040 eher von Programmierern als > von Hardwaremenschen entwickelt wurde. Das glaube ich nicht. Erfahrenen Programmierern ist schließlich sehr wohl bewußt, wie wichtig dieser Interrupt sein wird, sobald eine UART in einer Halbduplex-Situation läuft. Es werden also keine Programmierer gewesen sein, sondern Informatiker. Und zwar welche, denen niemand gesagt hat, dass Halbduplex für eine UART zwar nicht der Normalfall, aber durchaus breit verwendet ist. Sprich: aalglatte Rotärsche, frisch von der Uni oder sogar noch dort. Die haben das getan, was sie gelernt haben, nämlich Standards gelesen. Das erklärt auch die vielen Interrupts für Modems, die heute fast kein Schwein mehr interessieren, die aber halt in den einschlägigen Standards stehen...
Vielen Dank für eure Beiträge! Das habe ich mir schon so gedacht :-(, kein passender Interrupt. Ich finde es auch seltsam, dass es etliche Interrupts für Sachen wie RTS und CTS gibt, die sogut wie keiner mehr braucht, aber ein Interrupt auf's BUSY Bit fehlt. Bisher ist mir noch kein uC unter gekommen, der keinen solchen IRQ hatte, da bin ich jetzt schon etwas überrascht. Ich werde mich dann wohl etwas mit dem PIO Modul beschäftigen... So richtig elegant finde ich es zwar nicht, aber es wird nichts Anderes übrig bleiben. Ich werde von meinen Fortschitten berichten. Es ist natürlich absolut nachvollziehbar, dass die Raspberry PI Entwickler den von ARM bereitgestellten IP-Core nehmen. Wenn da jemand was vergessen hat, waren des die Entwickler bei ARM. Ich würde spekulieren, dass der IP bei der Corelizenz schon dabei ist und nicht extra kostet. Normalerweise sind die ARM IPs auch recht OK, der Fokus von ARM liegt aber tatsächlich oft nicht auf embedded Anwendungen und das merkt man an anderen Stellen auch. Ich habe beruflich viel mit speziellen Microcontrollern im Automobielbereich zu tun und wir sind immer froh, wenn ein Hersteller die ARM IPs nimmt. Wenn ein Hersteller versucht IPs selbst zu entwickeln braucht es meistens mehrere Halbleiterrevisionen, bis alles läuft...
c-hater schrieb: > Sprich: aalglatte Rotärsche, frisch von der Uni oder sogar noch dort. Das ist sie wieder, die Wildsau im Garten. Friedrich K. schrieb: > Ich werde mich dann wohl etwas mit dem PIO Modul beschäftigen... > So richtig elegant finde ich es zwar nicht, aber es wird nichts Anderes > übrig bleiben. Für Deine RS485 Übertragung lass die Finger von der PIO. Da wäre es noch einfacher, eine UART per Software zu bauen. PIO braucht man für einige Fälle. Versuch mal, eine ns-genaue Zeitmessung zu machen. Aber das wirst Du an anderer Stelle noch selber merken ;-)
m.n. schrieb: > Für Deine RS485 Übertragung lass die Finger von der PIO. Da wäre es noch > einfacher, eine UART per Software zu bauen. Er muss doch nur über PIO senden, empfangen kann er auf dem ganz normalen Wege. Und einen 10bit Wert (8Bit eingebettet in Start/Stop) in einen FIFO zu schreiben, scheint mir nicht die schwierigste Aufgabe zu sein. Das PIO Programm wartet auf FIFO, aktiviert den Transceiver, schiebt 10 Bits raus und deaktiviert den Transceiver. Ganz ohne CPU Aktivität. Und wenn's zig kByte sind, gerne auch der DMA. Und das Timing wird für MHz schnelle Übertragung bestens ausreichen.
Norbert schrieb: > Und einen 10bit Wert (8Bit eingebettet in Start/Stop) in einen FIFO zu > schreiben, scheint mir nicht die schwierigste Aufgabe zu sein. Er hat doch eine freie UART, die auch locker per DMA abspielen kann. Wozu die Sache unnötig verkomplimenzieren. Bloß weil es ginge, ist für mich kein Grund. OT Aber da wir uns gerade so nett unterhalten: Hast Du einen Erfahrungswert, bis zu welcher Taktfrequenz der XIP-Cache beim Übertakten brauchbar ist? Gerne würde ich noch 300 MHz nutzen; anderfalls kommt das Programm ins interne RAM. Der Hersteller warnt mit verkürzter Lebenszeit, was dann auch allerorts nachgeplappert wird, aber anstatt 50 Jahren Laufzeit wäre ich auch mit 20 Jahren Dauerlauf zufrieden ;-) /OT
m.n. schrieb: > Norbert schrieb: >> Und einen 10bit Wert (8Bit eingebettet in Start/Stop) in einen FIFO zu >> schreiben, scheint mir nicht die schwierigste Aufgabe zu sein. > > Er hat doch eine freie UART, die auch locker per DMA abspielen kann. > Wozu die Sache unnötig verkomplimenzieren. > Bloß weil es ginge, ist für mich kein Grund. Nein, da hast du Recht. Aber er muss ja auch einen Transceiver passend zu Beginn des Startbits ein- und zum Ende des Stoppbits ausschalten, mit keinem Mechanismus ginge das noch präziser als mittels PIO. > OT > Aber da wir uns gerade so nett unterhalten: Hast Du einen > Erfahrungswert, bis zu welcher Taktfrequenz der XIP-Cache beim > Übertakten brauchbar ist? > Gerne würde ich noch 300 MHz nutzen; anderfalls kommt das Programm ins > interne RAM. > Der Hersteller warnt mit verkürzter Lebenszeit, was dann auch allerorts > nachgeplappert wird, aber anstatt 50 Jahren Laufzeit wäre ich auch mit > 20 Jahren Dauerlauf zufrieden ;-) > /OT 272MHz stabil auf beiden Kernen, 273MHz auf Einem und bei 274MHz reichen bei mir ein paar °C um das Ding auf die Bretter zu werfen. Die Ein-Kern/Zwei-Kern Frequenzen sind jedoch gewiss in den Messungenauigkeiten zu sehen. Ich las allerdings das manche über 400MHz rausgequetscht haben, mit geändertem Flash-Timing. Da ich bis jetzt jedoch noch keine Notwendigkeit sah in diese Sphären vorzudringen, kann ich nichts Weiteres dazu sagen. Ach ja, Lebensdauer. Sehe ich ähnlich. Meist habe ich das Ding mit normaler Frequenz laufen und nur wenn's interessant wird schalte ich temporär auf »Ach du meine Güte« Modus.
Friedrich K. schrieb: > Für eine saubere Kommunikation via RS485 muss der "output enable" des > Trasceivers richtig angesteuert werden. Es gibt Transceiver, die das selber können: https://www.maximintegrated.com/en/products/interface/transceivers/MAX13410E.html fchk
> Gerne würde ich noch 300 MHz nutzen; anderfalls kommt das Programm ins > interne RAM. 200Mhz geht bei mir problemlos, aber 250Mhz traten ersten Ausfaelle auf. Interessanterweise vor allem beim Debuggen, soll heissen mein J-Link Ultra hat sich nicht mehr richtig verbunden. Olaf
fchk schrieb: > Es gibt Transceiver, die das selber können: Das nützt doch nichts! Der RP2040 muß doch auch wissen, was noch eigene Daten auf der Leitung sind und was als Antwort kommt. Dazu muß abgewartet werden, bis TxD komplett fertig ist. Norbert schrieb: > Ich las allerdings das manche über 400MHz rausgequetscht haben, mit > geändertem Flash-Timing. XIP_SSI->BAUDR steht bei mir auf 6. Das sollte reichen. Zudem VSEL ist von 1,1 auf 1,3 V hochgeschraubt.
m.n. schrieb: > XIP_SSI->BAUDR steht bei mir auf 6. Das sollte reichen. Zudem VSEL ist > von 1,1 auf 1,3 V hochgeschraubt. Mir scheint du meinst es wirklich Ernst. ;-) Hab' gerade nochmals laufen lassen, jetzt bei den niedrigeren Zimmertemperaturen läuft er geschmeidig bis:
1 | 391 µs : 270.000 MHz |
2 | Skipping: 271 MHz |
3 | 490 µs : 272.000 MHz |
4 | 359 µs : 273.000 MHz |
5 | Skipping: 274 MHz |
6 | Skipping: 275 MHz |
7 | 281 µs : 276.000 MHz |
8 | Skipping: 277 MHz |
9 | Skipping: 278 MHz |
10 | 374 µs : 279.000 MHz |
11 | 453 µs : 280.000 MHz |
12 | Skipping: 281 MHz |
13 | … |
Dann klopft der Watchdog-Timer zärtlich an. Bei höherer VSEL übrigens:
1 | # 12: 288MHz |
2 | # 13: 294MHz |
3 | # 14: 300MHz |
4 | # 15: 304MHz |
Norbert schrieb: > Mir scheint du meinst es wirklich Ernst. ;-) Kann ich Dich animieren, ein Programm von mir zu testen? http://mino-elektronik.de/progs/RP2040/pico_fmeter-3.uf2 An Pin4 ein Rechtecksignal anschließen (an Pin9 zum Beispiel liegen 100 kHz an) und sehen ob die LED auf dem Boarf (GPIO25) mit ca. 3 Hz blinkt. Da läuft das Pico-Board mit 150 MHz. Das muß problemlos laufen. Mit Pin20 an GND (z.B. Pin18) erneut starten und sehen, ob die LED immer noch blinkt. Damit sind es dann 300 MHz.
Für eine vernünftige Steuerung des RS485 output enable Signals sehe ich momentan folgende Möglichkeiten: - Arduino Methode (busy wait auf BUSY Bit) - Vorteile: Einfache Implementierung - Nachteile: Prozessor ist in der Zeit blockiert - Transceiver mit automatischer Richtungsumschaltung - Vorteile: Funktioniert ohne spezielle Implementierung - Nachteile: Sehr teuer Schlecht verfügbar - Timer IRQ wenn das Byte raus ist - Vorteile: Funktioniet Interrupt getrieben - Nachteile: Timer Ressource belegt - PIO als Timer missbrauchen - Vorteile: Funktioniet Interrupt getrieben - Nachteile: PIO Ressource belegt - UART in PIO nachbauen - Vorteile: Funktioniet Interrupt getrieben HW UART bleibt für andere Anwendung frei - Nachteile: PIO Ressource belegt Ich habe mir das PIO Modul mal etwas genauer angeschaut, das ist schon ein cooles Teil. Mit PIO kann man viele Sachen viel besser umsetzen, die bisher mit Bit-Banging gmacht werden müssen. Es gibt auch eine umfangreiche Sammlung an Beispielen, die schon sehr vieles abdecken. Ich werde mich noch weiter damit beschäftigen. Wenn es möglich ist TX und RX für eine UART in einem PIO unter zu bringen, werde ich das vermutlich so machen.
:
Bearbeitet durch User
> - Arduino Methode (busy wait auf BUSY Bit) > - Vorteile: Einfache Implementierung > - Nachteile: Prozessor ist in der Zeit blockiert Der Nachteil wird aber etwas entschaerft weil man zwei Cores hat. .-) Man muss halt Projectbezogen entscheiden welche Loesung gerade am besten ins Konzept passt. Olaf
Friedrich K. schrieb: > - Timer IRQ wenn das Byte raus ist > - Nachteile: Timer Ressource belegt > > - PIO als Timer missbrauchen > - Nachteile: PIO Ressource belegt > > - UART in PIO nachbauen > - Nachteile: PIO Ressource belegt DMA hast Du vergessen. Man kann natürlich jede Lösung als Bedrohung ansehen. Und ich dachte, Du wärest schon längst fertig. Olaf schrieb: > Der Nachteil wird aber etwas entschaerft weil man zwei Cores hat. .-) Hast Du im Netz mal eine Anwendung gesehen, wo dies zwingend notwendig war? Dann war das vermutlich ein Arduino-Programm, wo exaktes delay_ms() gebraucht wurde ;-)
> Hast Du im Netz mal eine Anwendung gesehen, wo dies zwingend notwendig > war? Ja, siehst du! Wenn du einen zweiten Core hast, aber ihn fuer nix brauchst dann koennte er sich ja hier persoenlich um das RS485 Problem kuemmern. Das Dingen ist ja nun mal da. Ansonsten hab ich hier genau diese Frage auch schon mal aufgeworfen: .-) Beitrag "RP2040 / Pi Pico nutzen" Ist doch voll deprimierend wenn man was tolles mit dem RP2040 baut und der zweite Core wird garnicht genutzt. Gerade bei der aktuellen MCU Knappheit! Das ist total unoekologisch! :-D Olaf
Olaf schrieb: > Ist doch voll deprimierend wenn man was tolles mit dem RP2040 baut > und der zweite Core wird garnicht genutzt. Bei Gelegenheit werde ich ihn nutzen, um im Hintergrund Messung und Auswertung mit maximaler Geschwindigkeit zu machen. Derzeit läuft das Programm mit Interrupts im 100 kHz-Bereich und muß noch zeitlichen Platz lassen für Display und Bedienung. Derzeit behelfe ich mir ja damit, den einen Kern doppelt so schnell zu takten, was aber nicht bedeuten muß, den 2. Kern nicht auch mit doppelter Geschwindigkeit laufen zu lassen ;-)
Friedrich K. schrieb: > Das habe ich mir schon so gedacht :-(, kein passender Interrupt. Mir ist dazu noch etwas eingefallen: Da die UART ja im Halbduplex laufen soll, liegt während des Sendens der Empfänger der UART ja ohnehin brach. Es liegt also nichts näher, als den zu benutzen, um das Ende der eigenen Übertragung per Interupt mitzubekommen. Der Nachteil wäre natürlich die verdoppelte Interrupt-Last und ein leicht erhöhter Schaltungsaufwand zur Entkopplung der beiden TX. Der Vorteil wäre halt, dass keine zusätzlichen Hardwareresourcen verbraucht werden, sondern nur das, was in dem Moment sowieso ungenutzt in der Gegend rumliegt.
Brauchbare RS485-Implementierungen nutzen sowieso das Sendeecho, um Leitungsstörungen zu erkennen. Die UART hier ist ein Derivat des 16550 mit Sende- und Empfangsfifos, d.h. die Interruptlast lässt sich durch sinnvolles Konfigurieren der Triggerschwellen in einem überschaubaren Rahmen halten. Man mus sich halt Gedanken machen um die Größe der übertragenen/empfangenen Datenpakete machen, die Triggerschwellen sollten dazu passen bzw. sinnvoll kleiner sein.
Read the schematics! schrieb: > Die UART hier ist ein Derivat des 16550 mit Sende- und Empfangsfifos, > d.h. die Interruptlast lässt sich durch sinnvolles Konfigurieren der > Triggerschwellen in einem überschaubaren Rahmen halten. Stimmt. Im Extremfall wäre es sogar möglich, tatsächlich nur einen "TXC"-Interrupt zu haben. Nämlich dann, wenn die zu sendenden Datenpakete 32Byte oder weniger umfassen.
c-hater schrieb: > Friedrich K. schrieb: > >> Das habe ich mir schon so gedacht :-(, kein passender Interrupt. > > Mir ist dazu noch etwas eingefallen: > > Da die UART ja im Halbduplex laufen soll, liegt während des Sendens der > Empfänger der UART ja ohnehin brach. Es liegt also nichts näher, als den > zu benutzen, um das Ende der eigenen Übertragung per Interupt > mitzubekommen. > > Der Nachteil wäre natürlich die verdoppelte Interrupt-Last und ein > leicht erhöhter Schaltungsaufwand zur Entkopplung der beiden TX. > Der Vorteil wäre halt, dass keine zusätzlichen Hardwareresourcen > verbraucht werden, sondern nur das, was in dem Moment sowieso ungenutzt > in der Gegend rumliegt. Stimmt, das ist noch eine gute Idee. Die Interruptlast sollte eigentlich nicht doppelt so hoch sein, da ich ja dann nur auf den RXC Interrupt reagieren muss. Der Nachteil ist, dass ich einen Mechanismus brauche damit umzugehen, falls der RXC Interrupt aus irgendwelchen Gründen nicht kommt. Sollte man aber sowieso haben.
Steve schrieb: > Diese USB <-> RS485 Adapter schalten die Richtung automatisch um und > werden von Linux out-of-the-box unterstützt. Norbert schrieb: > Manchmal, nur manchmal, > also wenn man einen Thread von Anfang an liest, > nicht nur ansieht, nein wirklich liest, > dann gewinnt man plötzlich - wie aus dem Nichts - völlig neue > Erkenntnisse. Zum Beispiel: Falk B. schrieb: > Schön, nur daß der RP2040 weder Linux noch USB nutzt Ja, ich war im falschen Zug.
Für flexible Peripherie ist das PIO doch gemacht. https://www.youtube.com/watch?v=yYnQYF_Xa8g https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf Chapter 3. PIO UART(s) zum Senden: https://github.com/raspberrypi/pico-examples/tree/master/pio/uart_tx https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_uart_tx.py Es fehlt "nur" die Umschaltung und/oder der Interrupt.
Simulant schrieb: > Für flexible Peripherie ist das PIO doch gemacht. > > https://www.youtube.com/watch?v=yYnQYF_Xa8g > https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf Chapter > 3. PIO > > UART(s) zum Senden: > https://github.com/raspberrypi/pico-examples/tree/master/pio/uart_tx > https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_uart_tx.py > > Es fehlt "nur" die Umschaltung und/oder der Interrupt. Ja genau, das wäre die Möglichkeit die UART im PIO nachzubauen. Ich habe mich jetzt aber dafür entschieden, die gesendeten Bytes einfach wieder zu empfangen und so den benötigten Interrupt zu bekommen. Ich musste leider feststellen, dass die UART beim Empfangen auch nicht so der Hammer ist. Als Gegenstelle habe ich einen ATTiny414. Wenn der die Bytes so schnell wie er kann per Interrupt rausschickt, ist das dem rp2040 zu schnell. Nach dem Stopp-Bit bleibt der Bus dann kein komplettes Bit mehr High bis schon das Start-Bit kommt und das scheint die PL011 UART nicht zu mögen. Ich konnte das durch ein kleines Delay im ATTiny lösen aber naja.
Friedrich K. schrieb: > Als Gegenstelle habe ich einen ATTiny414. Wenn der > die Bytes so schnell wie er kann per Interrupt rausschickt, ist das dem > rp2040 zu schnell. Willst Du uns veräpplen? Friedrich K. schrieb: > Ich habe beruflich viel mit speziellen Microcontrollern im > Automobielbereich zu tun Oder klär mich auf, was "Automobiel" ist.
Steve schrieb: > m.n. schrieb: >> Oder klär mich auf, was "Automobiel" ist. > > Ein Fahrzeug für Bielefeld. Ach so, Bielefeld gibt es ja nicht.
Friedrich K. schrieb: > Ich musste leider feststellen, dass die UART beim Empfangen auch nicht > so der Hammer ist. Als Gegenstelle habe ich einen ATTiny414. Wenn der > die Bytes so schnell wie er kann per Interrupt rausschickt, ist das dem > rp2040 zu schnell. Na das muss dann ja wirklich schnell sein! Ich habe hier siebenstellige Baudraten laufen und mit denen funktioniert es problemlos und in rauen Mengen. Allerdings habe ich noch nicht im Tera-Baud Bereich gearbeitet.
m.n. schrieb: > Friedrich K. schrieb: >> Als Gegenstelle habe ich einen ATTiny414. Wenn der >> die Bytes so schnell wie er kann per Interrupt rausschickt, ist das dem >> rp2040 zu schnell. > > Willst Du uns veräpplen? Nein, die Daten werden dann verfälscht. Ursache ist, dass die UART wohl mindestens ein Bit Pause vor dem Start-Bit erwartet. Zum Rest deines Beitrags: Spars dir einfach, sowas interessiert niemanden.
Friedrich K. schrieb: > Nein, die Daten werden dann verfälscht. Ursache ist, dass die UART wohl > mindestens ein Bit Pause vor dem Start-Bit erwartet. Wir anderen nennen das gerne Stopp-Bit. Und es hat sich bewährt ein solches zu nutzen.
Norbert schrieb: > Friedrich K. schrieb: >> Ich musste leider feststellen, dass die UART beim Empfangen auch nicht >> so der Hammer ist. Als Gegenstelle habe ich einen ATTiny414. Wenn der >> die Bytes so schnell wie er kann per Interrupt rausschickt, ist das dem >> rp2040 zu schnell. > > Na das muss dann ja wirklich schnell sein! Ich habe hier siebenstellige > Baudraten laufen und mit denen funktioniert es problemlos und in rauen > Mengen. Allerdings habe ich noch nicht im Tera-Baud Bereich gearbeitet. Es kommt nicht auf die Datenrate an. Das Problem ist, dass der Attiny etwas wenig Platz zwischen den Bytes lässt. Gleichzeitig ist die rp2040 UART da wohl etwas empfindlich. Kleines Delay im Attiny eingefügt, jetzt läuft es.
Norbert schrieb: > Friedrich K. schrieb: >> Nein, die Daten werden dann verfälscht. Ursache ist, dass die UART wohl >> mindestens ein Bit Pause vor dem Start-Bit erwartet. > > Wir anderen nennen das gerne Stopp-Bit. Und es hat sich bewährt ein > solches zu nutzen. Das Stopp-Bit ist komplett da. Das Problem tritt auch nicht unbedingt beim ersten Byte auf, sondern in meinem Fall erst nach so 4-5. Wenn ich zwischen zwei Bytes (inkl. Start und Stopp Bit) eine Bitzeit Pause lasse läuft alles problemlos.
Noch was: Ich habe hier ein Prolific pl2303 an TX0/RX0 hängen. Das Ding kann aber nur maximal 4MBaud, darum habe ich beim RP2040 noch nichts Höheres testen können (oder wollen weil sinnlos). Bis 4MBaud können sich PC und Controller schmerzfrei 256Byte Pakete (00…ff) zuwerfen.
Friedrich K. schrieb: > Es kommt nicht auf die Datenrate an. Das Problem ist, dass der Attiny > etwas wenig Platz zwischen den Bytes lässt. Gleichzeitig ist die rp2040 > UART da wohl etwas empfindlich. Tschuldige das ich mal etwas direkter werde: Das ist Unsinn. Und zwar von ›Es‹ bis zu ›empfindlich‹. Es gibt kein ›ein wenig Platz‹ zwischen gesendeten Bytes, genauso wenig irgendwelche Empfindlichkeiten. Das Netz würde geradezu Überlaufen vor Meldungen wenn dem so wäre.
Norbert schrieb: > Friedrich K. schrieb: >> Es kommt nicht auf die Datenrate an. Das Problem ist, dass der Attiny >> etwas wenig Platz zwischen den Bytes lässt. Gleichzeitig ist die rp2040 >> UART da wohl etwas empfindlich. > > Tschuldige das ich mal etwas direkter werde: Das ist Unsinn. Und zwar > von ›Es‹ bis zu ›empfindlich‹. > > Es gibt kein ›ein wenig Platz‹ zwischen gesendeten Bytes, genauso wenig > irgendwelche Empfindlichkeiten. > Das Netz würde geradezu Überlaufen vor Meldungen wenn dem so wäre. Ich habe mal zwei Bilder angehängt, eines, das den Fehler zeigt und eines bei dem es dann funktioniert. Der Unterschied ist die Länge der Pause nach dem Stopp-Bit bis zum Anfang des Start-Bits.
Erwartungsgemäß nichts wichtiges abzulesen. Prüfe mal ob du WIRKLICH 115200bd generierst. Von hier sieht's nicht so aus.
Friedrich K. schrieb: > Nein, die Daten werden dann verfälscht. Ursache ist, dass die UART wohl > mindestens ein Bit Pause vor dem Start-Bit erwartet. > Zum Rest deines Beitrags: Spars dir einfach, sowas interessiert > niemanden. Gut, dann sage ich es deutlicher. Deine Fehlerberichte zeugen von dilettantischer Vorgehensweise. Das interessiert schon, wenn man Dir ernsthaft antworten wollte. Hättest Du gleich Deine RS485 Gegenstelle mit ATiny414 benannt, wäre Dein Unvermögen, gezielt eine einfache Lösung zu finden, sofort aufgefallen. @Norbert: 440 MHz ohne besondere Kühlung o.ä., wenn man den Code im RAM laufen läßt. Alle Probleme mit XIP sind dann wie weggeblasen ;-)
Norbert schrieb: > Erwartungsgemäß nichts wichtiges abzulesen. > Prüfe mal ob du WIRKLICH 115200bd generierst. > Von hier sieht's nicht so aus. Der Attiny läuft mit dem internen Oszillator, von da her ist nicht zu erwarten, dass die Frequenz WIRKLICH genau stimmt. In der realen Welt muss man eben auch mit solchen Sachen arbeiten und kann sich nicht immer aussuchen, was man einsetzt. Das Problem taucht auch bei niedrigeren Baudraten genau so auf. Das Problem verschwindet, wenn der Sender zwischen den Bytes eine Bitzeit wartet. Sollte es nur an einer zu weit abweichen Baudrate liegen, würde die Pause keinen Unterschied machen. Ich denke, das Problem ist eine Kombination aus beidem. Ich spekuliere mal, dass die UART die fallende Flanke des Start-Bits bei zu kurzer Pause erst später erkennt. Dadurch werden Abweichungen in der Baudrate viel relevanter, da jetzt nicht mehr in der Mitte des Bits gesampelt wird. Der Effekt mit dem zu späten Erkennen des Start-Bits würde sich dann auch noch über mehrere Bytes akkumulieren (beim vorherigen Byte war der Empfänger schon zu spät dran, deshalb erkennt er das Start-Bit vom nächsten Byte noch später). Nach ein paar Bytes ist der Empfänger dann so weit daneben, dass Daten falsch interpretiert werden. Die Theorie würde das von mir beobachtete Verhalten erklären. Die Lösung des Problems ist dann einfach, der Sender muss mindestens eine Bitzeit zwischen Stopp-Bit und Start-Bit lassen. Könnte in der ein oder anderen Spezifikation auch so drin stehen. Beim Attiny kann man z.B. zweit Stopp-Bits senden lassen, dann passt es immer.
Friedrich K. schrieb: > Es kommt nicht auf die Datenrate an. Das Problem ist, dass der Attiny > etwas wenig Platz zwischen den Bytes lässt Wie viel Platz willst du denn da haben? Normalerweise ist da genau ein Stop Bit vorgesehen. In deinen Bildern sehe ich sogar deutlich mehr. Am Attiny liegt es ganz sicher nicht, der ist nicht Schuld. > Das Problem tritt auch nicht unbedingt beim ersten Byte auf, sondern > in meinem Fall erst nach so 4-5. > Wenn ich zwischen zwei Bytes (inkl. Start und Stopp Bit) eine > Bitzeit Pause lasse läuft alles problemlos. Ich glaube dir das jetzt mal, würde aber empfehlen, das nicht mit deinem Workaround zu umgehen sondern die wahre Problemursache zu beheben. Friedrich K. schrieb: > Ich spekuliere mal, dass die UART die fallende Flanke des Start-Bits bei > zu kurzer Pause erst später erkennt. Guter Ansatz. Das wiederum könnte durch schlechte Signalpegel oder zu flache Flanken ausgelöst werden. Kommt öfter vor, vor allem wenn Leute diese 1-Transitor Pegelwandler verwenden, die eigentlich für I²C gedacht sind. Du hast in Beitrag "Re: Raspberry pi Pico rp2040 RS485 Implementierung" zwei Bilder vom Logic Analyzer gezeigt. Wenn du mal ein ähnliches Bild mit einem Oszilloskop erstellen kannst, wo man den Spannungsverlauf von einem Byte sehen kann, kommen wir der Sache vielleicht näher.
Steve schrieb: > > Guter Ansatz. Das wiederum könnte durch schlechte Signalpegel oder zu > flache Flanken ausgelöst werden. Kommt öfter vor, vor allem wenn Leute > diese 1-Transitor Pegelwandler verwenden, die eigentlich für I²C gedacht > sind. > > Du hast in Beitrag "Re: Raspberry pi Pico rp2040 RS485 Implementierung" zwei > Bilder vom Logic Analyzer gezeigt. Wenn du mal ein ähnliches Bild mit > einem Oszilloskop erstellen kannst, wo man den Spannungsverlauf von > einem Byte sehen kann, kommen wir der Sache vielleicht näher. Schlechte Signalpegel würde ich eher nicht erwarten. Ein SP3485EN ist direkt an den rp2040 angeschlossen. Im Moment ist das zwar eine Fädelkonstruktion, bei den Geschwindigkeiten sollte das aber kein Problem sein. Im Saleae hab ich mal das Signal auch analog aufgezeichnet (10 MSample/s). Sieht aus meiner Sicht gut aus. Der Grund, warum ich mich überhaupt noch mit dem Thema beschäftige ist, dass ich rausfinden will, was die wirkliche Ursache ist. Bisher habe ich mich noch nicht ein 2. Mal durch die ARM Doku gewühlt, evtl. lässt sich da ein Hinweis darauf finden, ob meine Theorie richtig ist. Manchmal liest man sowas erst raus, wenn man schon weiß wie es funktioniert...
Friedrich K. schrieb: > UART_analog.png Sieht gut aus, Schlechte Signalpegel sind das wohl nicht. > Der Grund, warum ich mich überhaupt noch mit dem Thema beschäftige ist, > dass ich rausfinden will, was die wirkliche Ursache ist. Finde ich gut
Friedrich K. schrieb: > Der Attiny läuft mit dem internen Oszillator, von da her ist nicht zu > erwarten, dass die Frequenz WIRKLICH genau stimmt. In der realen Welt > muss man eben auch mit solchen Sachen arbeiten und kann sich nicht immer > aussuchen, was man einsetzt. Das Problem taucht auch bei niedrigeren > Baudraten genau so auf. Jetzt mal ehrlich, wie oft muss hier eigentlich noch erklärt werden das mit hochgradig ungenauen internen Oszillatoren bestenfalls LEDs zum Blinken gebracht werden aber KEINESFALLS UART Kommunikation. Das ganze Setup ist dermaßen Übel und sinn-befreit das es einem die Sprache verschlägt. Drop Mic.
Friedrich K. schrieb: > Der Grund, warum ich mich überhaupt noch mit dem Thema beschäftige ist, > dass ich rausfinden will, was die wirkliche Ursache ist. Wenn ich das richtig ablese, dann beginnt das Startbit bei 67us und das letzte Datenbit endet bei 145us. Das ergibt folgende Bitrate: 1 / ((145us - 67us) / (1+8)) = 115384 bps Das sind 0.16% mehr als die 115200 bps und ist damit ziemlich gut. Die Mess- bzw. Ablesegenauigkeit aus der Grafik ist allerdings deutlich größer, daher kann das auch abweichen. Für solche Messungen solltest du mehrmals hintereinander ein großes U (entspricht 0x55) schicken, das kann man am besten auswerten, da sieht man jedes Bit einzeln. Michael
:
Bearbeitet durch User
Ich habe gerade kein 414 Datenblatt, aber zur ersten Abschätzung reicht wohl auch ein 441. Internal 8MHz Oscillator: Bei absolut stabiler Spannung und absolut stabiler Temperatur: ±2% Hinzu kommen im echten Leben noch die Abweichung gemäß der Kurven bzgl. Frequenzabweichung pro K und Frequenzabweichung pro V. Und die sind beide nicht unerheblich. Aber weiterhin frohes Mikrosekunden schätzen.
Norbert schrieb: > Aber weiterhin frohes Mikrosekunden schätzen. Du hast natürlich recht, dass dies nicht in allen Fällen funktionieren wird und man sich nicht darauf verlassen kann und kein Produkt darauf aufbauen sollte. Wenn es aber um eine konkrete Messung geht und darum warum dies nicht funktioniert und diese Messung sagt, dass die Parameter innerhalb der Spec liegen, dann würde ich diese Fehlerquelle mal als Ursache runterpriorisieren. Ich würde jetzt erwarten, dass der Fehler auf der Empfängerseite liegt. Je nachdem mit welcher Formel man die Teiler für 115200 Baud berechnet treten da schonmal Fehler von 6% auf. Wenn die Fehler von Sender und Empfänger sich dann noch addieren geht nichts mehr. Um das auszuschließen benötigt es vernünftige Messungen von beiden Seiten. Da man den Empfänger nicht direkt messen kann muss man hier eben auch Daten senden die man dann messen kann. Die Baudrate für Senden und Empfangen ist wohl hoffentlich identisch. @Friedrich: kannst du bitte mal eine Messung machen in welcher der Pico 2040 Daten schickt? Am besten 2x direkt hintereinander ohne Pause ein U schicken ("UU" = 0x55, 0x55). Michael
:
Bearbeitet durch User
Friedrich K. schrieb: > Ich musste leider feststellen, dass die UART beim Empfangen auch nicht > so der Hammer ist Kannst du mal den Code für die Initialisierung des UART bei Raspi Pico zeigen? Verwendest du die Arduino IDE für die Programmierung oder den Arduino Core in VS Code oder was anderes? Bei Arduino sollte das aussehen:
1 | Serial1.setFIFOSize(128); |
2 | Serial1.begin(115200); |
Verwendest du einen anderen Port (Softwareserial)? Initialisiert du die FIFO Größe? Michael
:
Bearbeitet durch User
Norbert schrieb: > Ich habe gerade kein 414 Datenblatt, aber zur ersten Abschätzung reicht > wohl auch ein 441. Vorsicht! Niemals die DBs der Klassiker als Referenz für die "Neuen" verwenden. Das führt in's Verderben. Im konkreten Fall allerdings passt es doch recht gut. +-2% Abweichung, wenn die Factory-Kalibrierungs benutzt wird, das ist dasselbe wie bei dem Klassiker. > Bei absolut stabiler Spannung und absolut stabiler Temperatur > Hinzu kommen im echten Leben noch die Abweichung gemäß der Kurven bzgl. > Frequenzabweichung pro K und Frequenzabweichung pro V. > Und die sind beide nicht unerheblich. Genau. Und übrigens ist das Problem der Taktabweichung und ihrer Auswirkung bezüglich der Wortabgrenzung leider ein kumulierendes. Selbst wenn der Sender nur minimal schneller ist als der Empfänger, wird bei "dicht" gesendeten Daten irgendwann der Empfänger aus dem Tritt kommen. Dieses Problem ist so alt wie das Konzept der UARTs überhaupt und deswegen gibt es dagegen auch schon in allen einschlägigen Standards das passende Gegenkonzept: Der Sender sendet 1,5 oder 2 Stopbits. Ob und wann das nötig wird, hängt schlicht von der Anzahl der "dicht" gesendeten Datenworte und der maximalen Taktabweichung zwischen Sender und Empfänger ab. Man kann das tatsächlich ausrechnen. Nur scheint Friedrich K. dazu nicht in der Lage zu sein...
Norbert schrieb: >> Der Attiny läuft mit dem internen Oszillator > Das Problem taucht auch bei niedrigeren Baudraten genau so auf. Wenn der Oszillator 10% falsch läuft, dann ist die Übertragung bei 115200 ebenso 10% falsch wie auch bei 300 Baud. Bei niedrigen Baudraten ist die Taktfrequenz nur deswegen nicht ganz so kritisch, weil die verzottelten Signalflanken mehr Abstand zu den Abtast-Zeitpunkten haben. Aber bei 10% Abweichung würde das auch nichts mehr nützen. Norbert schrieb: > Internal 8MHz Oscillator: > Bei absolut stabiler Spannung und absolut stabiler Temperatur: ±2% Das ist deutlich besser, als die älteren ATtinies spezifiziert sind.
c-hater schrieb: > Nur scheint Friedrich K. dazu nicht in der Lage zu sein... Und deswegen nochmal direkter an Friedrich K.: mach doch den Tiny einfach mal einen Kalibrierungsschritt für den internen Oszillator langsamer... Du wirst sehen: das ändert schon vieles, wenn nicht sogar alles... Wenn du das Problem erstmal wirklich begriffen hast, kommst du auch nicht mehr in die Versuchung, es der UART des RP2040 anzulasten. Die macht nur das, was auch alle anderen UARTs machen und hat dementsprechend exakt dieselben Probleme, die auch alle anderen UARTs bei der entsprechenden Taktabweichung haben...
c-hater schrieb: > Und übrigens ist das Problem der Taktabweichung und ihrer Auswirkung > bezüglich der Wortabgrenzung leider ein kumulierendes. Selbst wenn der > Sender nur minimal schneller ist als der Empfänger, wird bei "dicht" > gesendeten Daten irgendwann der Empfänger aus dem Tritt kommen. Ähm … nicht ganz. (Zumindest nicht immer) Beim mega32u4 und vielen AVRs die ich kenne (das mag bei Anderen anders sein) ist es so, das bei der Flanke des Startbits die Synchronisation stattfindet. Dann findet immer an den drei mittleren Positionen im Bit ein ›sampling‹ statt. 2aus3 gewinnt. Das geht so bis zum Stopp-Bit. Auch bei diesem findet gleichermaßen das ›sampling‹ statt. Aber: _»A new high to low transition indicating the start bit of a new frame can come right after the last of the bits used for majority voting.«_ Damit kann der Sender sogar geringfügig schneller sein, da für 10Bit nur 9 + 10/16 Bit gebraucht werden. Die RP2040 Dokumentation ist an der Stelle zwar deutlich schlechter, aber auch dort werden die mittleren drei Messungen eines 16Schritt Zyklus gemessen. Das wiederum suggeriert, das die Stopp-Bit Verarbeitung auch dort nach 9 + 10/16 Bit fertig ist.
Norbert schrieb: > Aber: _»A new high to low transition indicating the start bit of a new > frame can come right after the last of the bits used for majority > voting.«_ > > Damit kann der Sender sogar geringfügig schneller sein Also das lese ich anders. Das semantische Problem ist hier: "last of the bits". Was genau ist damit gemeint? Ich würde sagen: alle, insbesondere inclusive des "mandatory" Stop-Bits. Und damit ergibt sich exakt das Verhalten, was auch alle anderen UARTs haben, die ich kenne. Und tatsächlich ist meine Erfahrung zwischen zwei (jeweils quartzgetakteten) klassischen AVRs genau diese: in eine Richtung läuft es unbegrenzt, in die andere gibt's in recht regelmäßigen Abständen einen Schluckauf. Misst man die jeweiligen Muttertakte, ergibt sich zweifelsfrei, dass die unproblematische Richtung (erwartungsgemaß) genau die ist, bei der der Sender die geringere Taktfrequenz hat.
c-hater schrieb: > Und damit ergibt sich exakt das Verhalten, was auch alle anderen UARTs > haben, die ich kenne. Das scheinen merkwürdige UARTs zu sein. Typisch ist, daß das Ende eines Zeichen in der Mitte des Stoppbits erkannt wird. Ob nun weitere Stoppsbits oder Pausen kommen, ist egal. Danach wartet der Empfänger auf das nächste Startbit und synchronisiert auf die Mitte des Startbits. Anders könnte die asynchrone Kommunikation überhaupt nicht funktionieren!
c-hater schrieb: > Norbert schrieb: >> Aber: _»A new high to low transition indicating the start bit of a new >> frame can come right after the last of the bits used for majority >> voting.«_ > Also das lese ich anders. Das semantische Problem ist hier: "last of the > bits". Was genau ist damit gemeint? > Ich würde sagen: alle, insbesondere inclusive des "mandatory" Stop-Bits. Das ist korrekt, aber nur für die ersten 10/16 des Stopp-Bits. Würde klarer wenn Atmel ›measurement or sample positions‹ geschrieben hätte. Ein Bit wird in sechzehn Messpunkte aufgeteilt. Die mittleren drei Messpunkte werden für 2aus3 verwendet. Das heißt nach 10 von 16 Messpunkten des ersten Stopp-Bits ist der Frame (Start-Bit 8Daten-Bits 1 oder 1.5 oder 2 Stopp-Bits) abgearbeitet.
c-hater schrieb: > Dieses > Problem ist so alt wie das Konzept der UARTs überhaupt und deswegen gibt > es dagegen auch schon in allen einschlägigen Standards das passende > Gegenkonzept: Der Sender sendet 1,5 oder 2 Stopbits. In Friedrichs geht_nicht.png sind die erkennbaren Stopbits plus die kurze Pause bis zum nächsten Startbit schon deutlich länger als die Datenbits, effektiv sind es etwa 1,3 bis etwas über 1,4 Stopbits. Sollte das nicht bei kleinen Abweichungen in der Taktfrequenz (in beiden Richtungen) ausreichen?
m.n. schrieb: > Das scheinen merkwürdige UARTs zu sein. Nein, ganz normale mit Majoritäts-Logik. Aus vielen verscheidenen Architekturen... > Typisch ist, daß das Ende eines Zeichen in der Mitte des Stoppbits > erkannt wird. Das kann nicht sein. Bestenfalls ist möglich: "kurz nach der Mitte". Das gibt die Majoritätslogik so vor (jedenfalls für jeden, der logisch denken kann). Und wie lang "kurz" ist, gibt der Takt vor, mit der das UART-Teil betrieben wird. Im Extremfall ist das halt das nominale Ende des Stopbits. > Anders könnte die asynchrone Kommunikation überhaupt nicht > funktionieren! Sicher. Und genau deswegen gibt es ja auch die Sache mit 1,5 oder 2 Stopbits für den Sender. Wäre es anders, bräuchte man diese Sache überhaupt niemals...
c-hater schrieb: > Sicher. Und genau deswegen gibt es ja auch die Sache mit 1,5 oder 2 > Stopbits für den Sender. Wäre es anders, bräuchte man diese Sache > überhaupt niemals... Das ist aber eher ein Relikt aus der Zeit als UARTs noch alle 100.000 Zeichen einen Ölwechsel brauchten und die Takterzeugung mittels eines Metronoms statt fand. ;-)
Norbert schrieb: > Ein Bit wird in sechzehn Messpunkte aufgeteilt. Nicht unbedingt. Bei AVRs werden für doppelte Baudrate nur 8 "Messpunkte" verwendet. Bei Software UARTs reicht empfangsseitig auch eine 4er-Teilung, um die Interrupts zu reduzieren. c-hater schrieb: >> Typisch ist, daß das Ende eines Zeichen in der Mitte des Stoppbits >> erkannt wird. > > Das kann nicht sein. Bestenfalls ist möglich: "kurz nach der Mitte". Hast Du Dir heute Erbsen gekauft und willst Sie jetzt zählen? Wo ist denn "kurz nach der Mitte" bei einem Datenbit, was mit verrundeten Flanken empfangen wird? c-hater schrieb: > Und tatsächlich ist meine Erfahrung zwischen zwei (jeweils > quartzgetakteten) klassischen AVRs genau diese: in eine Richtung läuft > es unbegrenzt, in die andere gibt's in recht regelmäßigen Abständen > einen Schluckauf. Quarzstabil und "Schluckauf"? Aber auch nur bei Dir.
Norbert schrieb: > Ein Bit wird in sechzehn Messpunkte aufgeteilt. Nein. Es wird in 7 Messpunkte aufgeteilt, außer im X2-Mode, da wird es in nur 3 Messpunkte aufgeteilt. > Die mittleren drei > Messpunkte werden für 2aus3 verwendet. Nein. Es wird immer die Majorität verwendet. Nur im X2-Modus also die Mehrheit aus 3, sonst die Mehrheit aus 7. Und noch zu berücksichtigen: Die benutzten Samples sind um einen UART-Takt nach hinten verschoben gegenüber dem nominalen Bitanfang.
m.n. schrieb: > Quarzstabil und "Schluckauf"? Aber auch nur bei Dir. Du kannst das gerne jederzeit nachexerzieren, wenn du mir nicht glaubst.
Norbert schrieb: > Das ist aber eher ein Relikt aus der Zeit als UARTs noch alle 100.000 > Zeichen einen Ölwechsel brauchten und die Takterzeugung mittels eines > Metronoms statt fand. ;-) Nein, das war eine pragmatische Lösung für ein Problem, was von Anfang an bestand und auf Grund der unveränderten Physik unseres Universums bis heute auch unverändert weiter besteht.
c-hater schrieb: > Norbert schrieb: > >> Ein Bit wird in sechzehn Messpunkte aufgeteilt. > > Nein. Es wird in 7 Messpunkte aufgeteilt, außer im X2-Mode, da wird es > in nur 3 Messpunkte aufgeteilt. Tja, da liegst du falsch. (Oder Atmel weiß nicht wie sie es selbst gemacht oder beschrieben haben) Im Normalmodus sind es 16 Segmente, im X2 Modus 8 Segmente. >> Die mittleren drei >> Messpunkte werden für 2aus3 verwendet. > > Nein. Es wird immer die Majorität verwendet. Was denkst du bedeutet 2aus3? Aber ich bin jetzt raus, hier wird's zu Erbsenzählerisch und einige versuchen nur noch verzweifelt irgendwelche Ungenauigkeiten in den Formulierungen zu finden. Typisches Forenverhalten hier!
Norbert schrieb: > Aber ich bin jetzt raus, Du hast ja völlig recht. Ab und zu muß man aber doch widersprechen, damit ein unbedarfter Leser das nicht noch glaubt. @c-hater: Denk mal drüber nach, warum für die benötigte Baudrate in der Regel ein 16 x höherer Takt benötigt wird. Gut, auch das wirst Du bestreiten ;-)
m.n. schrieb: > Norbert schrieb: >> Aber ich bin jetzt raus, > > Du hast ja völlig recht. Ab und zu muß man aber doch widersprechen, > damit ein unbedarfter Leser das nicht noch glaubt. Stimmt, darum bin ich auch so fürchterlich inkonsequent. ;-) Außerdem regnet es, also:
1 | Blocknum # 1 OK @ 1000000 bd (+0.00%) |
2 | Blocknum # 1 OK @ 998004 bd (-0.20%) |
3 | Blocknum # 1 OK @ 996016 bd (-0.40%) |
4 | Blocknum # 1 OK @ 994036 bd (-0.60%) |
5 | Blocknum # 1 OK @ 992064 bd (-0.79%) |
6 | Blocknum # 1 OK @ 990099 bd (-0.99%) |
7 | Blocknum # 1 OK @ 988142 bd (-1.19%) |
8 | Blocknum # 1 OK @ 986193 bd (-1.38%) |
9 | Blocknum # 1 OK @ 984252 bd (-1.57%) |
10 | Blocknum # 1 OK @ 982318 bd (-1.77%) |
11 | Blocknum # 1 OK @ 980392 bd (-1.96%) |
12 | Blocknum # 1 OK @ 978474 bd (-2.15%) |
13 | Blocknum # 1 ERROR @ 976562 bd (-2.34%) |
14 | |
15 | Blocknum # 1 OK @ 1000000 bd (+0.00%) |
16 | Blocknum # 1 OK @ 1002004 bd (+0.20%) |
17 | Blocknum # 1 OK @ 1004016 bd (+0.40%) |
18 | Blocknum # 1 OK @ 1006036 bd (+0.60%) |
19 | Blocknum # 1 OK @ 1008064 bd (+0.81%) |
20 | Blocknum # 1 OK @ 1010101 bd (+1.01%) |
21 | Blocknum # 1 OK @ 1012146 bd (+1.21%) |
22 | Blocknum # 1 OK @ 1014199 bd (+1.42%) |
23 | Blocknum # 1 OK @ 1016260 bd (+1.63%) |
24 | Blocknum # 1 OK @ 1018330 bd (+1.83%) |
25 | Blocknum # 1 OK @ 1020408 bd (+2.04%) |
26 | Blocknum # 1 OK @ 1022495 bd (+2.25%) |
27 | Blocknum # 1 OK @ 1024590 bd (+2.46%) |
28 | Blocknum # 1 OK @ 1026694 bd (+2.67%) |
29 | Blocknum # 1 OK @ 1028807 bd (+2.88%) |
30 | Blocknum # 1 OK @ 1030928 bd (+3.09%) |
31 | Blocknum # 1 OK @ 1033058 bd (+3.31%) |
32 | Blocknum # 1 OK @ 1035197 bd (+3.52%) |
33 | Blocknum # 1 OK @ 1037344 bd (+3.73%) |
34 | Blocknum # 1 OK @ 1039501 bd (+3.95%) |
35 | Blocknum # 1 OK @ 1041667 bd (+4.17%) |
36 | Blocknum # 1 ERROR @ 1043841 bd (+4.38%) |
Das ist was der RP2040 bei 1Megabaud an Abweichung verträgt. Der RP befruchtet sich hier selbst mit Datenblöcken à 16384 Byte. UART1 Rx: 1Megabaud fest UART0 Tx: variabel laut Tabelle. Den 88 Zeilen Python Code poste ich besser nicht, da fühlen sich die C und Assembler Programmierer gleich wieder angegriffen. ;-) (Obwohl man die Validierung auch in Thumb hätte schreiben können)
Norbert schrieb: > UART1 Rx: 1Megabaud fest > UART0 Tx: variabel laut Tabelle. Na bitte, kein Schluckauf ;-) Du könntest UART1 (RX) auch noch auf zwei Stoppbits einstellen, TX aber nur ein Stoppbit senden lassen. Da RX im Grunde nur 1/2 Stoppbit als Endkennung braucht, wird das so auch funktionieren. Das Datenblatt weist zudem darauf hin. Norbert schrieb: >> 440MHz > > Völlig vergessen. > Gratulation! Das ist ja geradezu obszön schnell… Na ja, das ist nicht mein Verdienst, ich probiere eben nur die Grenzen aus. Auch möchte ich die "wissenschaftlichen" Beschreibungen im Netz nicht noch ergänzen, wo womöglich noch mit flüssigem Stickstoff laboriert wird, um den Controller nicht glühen zu lassen. In der Praxis zeigt sich, daß Programme über XIP ausgeführt schon ab 200 MHz merkwürdiges Verhalten zeigen - trotz hinreichender Wartezeiten und max. Kernspannung. Mit der Ausführung aus dem internen RAM laufen in meinem Fall RAM, SIO, PIO, PWM-Timer, DMA und UART völlig unauffällig. Die zusätzliche Stromaufnahme bei maximaler Übertaktung liegt vielleicht bei 10 mA auf der 5 V Versorgung. Da tritt keine große Erwärmung auf. Ich habe das nicht weiter gemessen. Das Teil ist affenschnell! Vielleicht sind XIP oder auch USB der begrenzende Faktor, weshalb offiziell max. 133 MHz angegeben werden. Sobald man das externe QSPI-EEPROM als Datenspeicher nutzen möchte/muß, sollte man sich das Programm sowieso ins RAM packen.
Michael D. schrieb: > Ich würde jetzt erwarten, dass der Fehler auf der Empfängerseite liegt. Ich auch. Aber ich vermute eher keinen Hardware-Fehler. > Je nachdem mit welcher Formel man die Teiler für 115200 Baud berechnet > treten da schonmal Fehler von 6% auf. Wenn die Fehler von Sender und > Empfänger sich dann noch addieren geht nichts mehr. Im Datenblatt der RP2040 sind im Abschnitt 4.2.7.1. Baud Rate Calculation passende Teiler für 125MHz Systemtakt und 115200 Baud angegeben. Ergbnis sind etwas über 115207 Baud und somit etwas über 0.006% Abweichung. Dazu kommt natürlich noch der Ferhler des Systemtaktes. > Um das auszuschließen benötigt es vernünftige Messungen von beiden > Seiten. Da man den Empfänger nicht direkt messen kann muss man hier eben > auch Daten senden die man dann messen kann. Die Baudrate für Senden und > Empfangen ist wohl hoffentlich identisch. Für eine vernünftige Messung fehlt mit das passende Equipment, ich habe nur eine einfache gemacht: mit einem kleinen Micropython Skript auf einem Raspberry Pi Pico habe ich eine Folge aus 11 Bytes ausgegeben und mit einem USB-Oszilloskop die Länge von 2, 8 und 100 Bits gemessen, jeweils von fallender Flanke zu fallender Flanke. 115207 Baud können stimmen, genau sagen kann ich es nicht da die Zeitbasis meines Picoscope 5242D mit ±50 ppm inititial ±5 ppm Drift/Jahr spezifiziert ist. Wenn man den Systemtakt mit machine.freq() setzt scheint Micropython den UART auf die 48MHz aus der zweiten PLL umzuschalten, selbst dann, wenn man den Systemtakt auf 125MHz setzt. Das war mir vorher schon mal bei SPI aufgefallen, da waren ohne machine.freq() 62,5 MHz möglich, mit aber nur 24MHZ.
1 | import time |
2 | from machine import UART, Pin |
3 | #machine.freq(125000000) |
4 | uart1 = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5)) |
5 | |
6 | while True: |
7 | uart1.write(bytes([0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55])) |
8 | time.sleep(0.1) |
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.