Hallo, ich habe gerade den ISR Artikel gelesen und dort steht, man sollte die ISR eher kurz halten und dort nur Flags setzen. Wie ist das denn, wenn ich einen Timer laufen habe, der setzt eine Flag für die main. In der ISR wird die aktuelle Ausgangsgröße gemessen und in der main daraus mit der Führungsgröße die Regelabweichung und damit die Stellgröße berechnet. Jetzt wird aber auch alle ~500 ms die Uart bemüht, die ~90ms benötigt. Kommt also schon relativ häufig vor. Die Timer bzw Abtastfrequenz beträgt 800us. Das bedeutet, es gehen, wenn die Uart gerade sendet 113 ISR Zyklen verloren, in denen zwar die Ausgangsgröße geloggt und die Flag gesetzt, aber eigentlich nicht geregelt wird. Daher die Frage: "Darf" ich die Regelung in die ISR verlagern? Priorität hat die Regelung, die Logging Geschichte (mit UART) ist Beiwerk, aber zu Analysezwecke durchaus wichtig... Danke für eure Hilfe!
Jan K. schrieb: > "Darf" ich die Regelung in die ISR verlagern? Kommt darauf an, wie lang deine Regelung rechnet. Wenn du aber bisher mit 800µs zwischen den Messwerten ausgekommen bist, kann das nicht zu lange gewesen sein => pack die Regelung in die ISR. "Möglichst kurze ISR" bedeutet ja nicht, dass nur "Flag setzen" darin erlaubt wäre.
Die Regelung rechnet etwa 80us. Eine andere Möglichkeit wäre vllt die UART Ausgabe per DMA zu machen. Was ist vernünftiger und gibt es noch andere Möglichkeiten?
Jan K. schrieb: > Eine andere Möglichkeit wäre vllt die UART Ausgabe per DMA zu machen. Ich mache so etwas Interrupt-getrieben mit Ringpuffer. Gruß Oliver
Dein erster Gedanke sollte sein: Wie wichtig ist es mir, dass (in deinem Fall) die Regelgleichung auch tatsächlich möglichst gleichbleibend regelmässig ausgeführt wird. Da das bei einem Regler meistens eine absolute Notwendigkeit ist, solltest du sogar die Reglerauswertung in die ISR stecken, solange du dadurch das restliche Programm nicht in Zeitnot bringst. Es hilft dir nichts, wenn du die Daumenregel "In einer ISR nur Flags setzen" zu wörtlich nimmst und dann einen wahnsinnig komplizierten Überbau im Hauptprogramm brauchst, der sicherstellen soll, dass an jeder einzelnen Stelle (zb bei der Ausgabe eines Strings) kurz zwischendruch mal eben bei Bedarf die Reglergleichung einmal abgearbeitet wird. ISR sollen das tun, was notwendig ist. Nicht mehr. Aber auch nicht weniger. In deiner Anwendung hat die Regelmässigkeit der Reglerauswertung absolute Priorität vor allem anderen. Daher: Ab in die ISR damit. Wenn die UART Ausgabe mal kurz für ein Zeichen stockt (weil zwischendurch einmal der PID läuft), interessiert das kein Schwein. Durch UART-BUffer kriegt das wahrscheinlich noch nicht einmal irgendwer mit.
Jan K. schrieb: > die Uart bemüht, die ~90ms benötigt. Warum braucht das Senden eines oder ein paar Byte 90ms? Das ind ja je nach µC (der nicht angegeben ist) mehrere 100000 Taktzyklen! Wartest du etwa bis alles gesendet worden ist? Das wäre sehr ungeschickt. Normalerweise macht man sich eine Sendefunktion die in etwa folgendermassen aussieht SendeByte() ist die UART frei dann schreibe das Byte in das Senderegister und starte Senden else schreibe das Byte in den Sendepuffer Jede UART hat eine ISR die aufgerufen wird wenn ein Byte gesendet wurde in der steht dann: ist noch ein Byte im Sendepuffer wenn ja dann schreibe das Byte in das Senderegister Sende So dauert ein Senden nur höchstens ein paar hundert Taktzyklen, der Rest läuft asynchron
Erst einmal vielen Dank für die Antworten. Werde einige Fragen versuchen zu beantworten: kurz zur Aufklärung: es handelt sich um einen STM32F100 @ 24 Mhz Oliver J. schrieb: > Ich mache so etwas Interrupt-getrieben mit Ringpuffer. Mache ich auch. Dieser Buffer wird dann, wenn er voll ist geschickt. Das führt zur nächsten Frage : UR-Schmitt schrieb: > Wartest du etwa bis alles gesendet worden ist? > Das wäre sehr ungeschickt. Ja. :/ Es sind 1042 Bytes. Die Uart läuft mit 115200 Baud. Tatsächlich arbeite ich in einer Funktion den kompletten UART Puffer per Schleife ab und warte jeweils, bis die TXE und TC Bit gesetzt sind. UR-Schmitt schrieb: > Normalerweise macht man sich eine Sendefunktion die in etwa > folgendermassen aussieht > > SendeByte() > ist die UART frei > dann schreibe das Byte in das Senderegister und starte Senden > else > schreibe das Byte in den Sendepuffer > > Jede UART hat eine ISR die aufgerufen wird wenn ein Byte gesendet wurde > in der steht dann: > > ist noch ein Byte im Sendepuffer > wenn ja dann schreibe das Byte in das Senderegister > Sende > > So dauert ein Senden nur höchstens ein paar hundert Taktzyklen, der Rest > läuft asynchron Verdammt, das ist mir echt noch nicht eingefallen, aber scheint sinnig ;) Denke ich wollte so wenig Interrupts wie möglich machen und den Puffer lieber an einem Stück versenden. @ Karl Heinz: auch dir vielen Dank für die Antwort. Dass die Abtastung und vor allem Regelung oberste Priorität hat ist korrekt. Daher darf ja das Programm auf keinen Fall so bleiben wie es ist ;) Habe gerade mit dem Scope nochmal nachgemessen: ISR so wie sie jetzt ist (nur in den Ringpuffer schreiben) : 2.8us ISR puffern + berechnen : 13.6us ISR puffern + berechnen + pid berechnen + pwm : 37.2us Scheint also nicht wirklich zeitkritisch zu sein das ganze, obwohl es recht viel Code ist. Denke ich werd's dann wirklich in die ISR packen, die Geschichte mit den Uart Interrupts gucke ich mir aber trotzdem an. Oder lieber direkt mit dem DMA arbeiten? Immerhin gibt es ihn ja ;) Vielen vielen Dank!
Jan K. schrieb: > Mache ich auch. Dieser Buffer wird dann, wenn er voll ist geschickt. Hä? > Ja. :/ > Es sind 1042 Bytes. Die Uart läuft mit 115200 Baud. Tatsächlich arbeite > ich in einer Funktion den kompletten UART Puffer per Schleife ab und > warte jeweils, bis die TXE und TC Bit gesetzt sind. UNgeschickt. Eine normale UART kann einen Interrupt auslösen, wenn sie das nächste Zeichen wegschicken kann. In dieser Interrupt Routine wird die UART mit dem nächsten Zeichen aus der Sende-FIFO gefüttert. Mehr nicht. Wenn die UART dieses Zeichen dann draussen hat, meldet sie sich sowieso dann wieder mit einem neuen Interrupt: "Hey, ich brauch was zu tun!". Und dann fütterst du ihr das nächste Zeichen (sofern noch eines im Buffer ist). Der Trick besteht jetzt darin, dass diese UART-ISR trivial einfach ist. Ein paar Taktzyklen und die UART ist wieder gefüttert. Während die UART dann ihren Teil macht, kann dein Programm sich wieder anderen Aufgaben widmen (anstatt blödsinnig auf das Fertig von der UART zu warten) Wenn du µC programmierst, musst du agierenb wie eine Hasufrau, die auch 5 Sachen 'gleichzeitig' macht, indem sie zwischen den einzelnen Aufgaben hin und herflitzt. Wassser auf den Herd, Herd einschalten Ab zur Waschmaschine, Wäsche sortieren Zwischendurch mal schnell zum Postkastn, Post auf den Tisch Staubsauger rausholen Wäsche in die Waschmaschine, Maschine einschalten Kurz beim Herd vorbeischauen, ob das Wasser schon kocht Ersten Brief öffnen, Rechnung beiseitelegen Wasser kocht, also Nudeln rein .... In keinem Fall bleibt sie daneben stehen und wartet darauf, dass etwas fertig wird. Wenn es etwas zu warten gibt, dann wird eben in der Zwischenzeit etwas anderes gemacht.
Jo, ungeschickt. Hatte Ur-Schmitt ja schon angedeutet ;) Werde die Interrupts einbauen und die Berechnung in die ISR verlegen bei den Zeiten, oder?
Jan K. schrieb: > Jo, ungeschickt. Hatte Ur-Schmitt ja schon angedeutet ;) > > Werde die Interrupts einbauen und die Berechnung in die ISR verlegen bei > den Zeiten, oder? Für einen Ringpuffer und die Funktionen zum Senden gibts bestimmt massenweise Code im I-Net und auch im Forum. Würde mich wundern wenn es hier nicht C Code geben würde zwar für einen kleineren Puffer und für 8 Bitter aber in C lässt sich das ja anpassen. Nur um das Prinzip zu verstehen.
Ich habe bereits einen Ringpuffer implementiert in den letzten Tagen. Sogar einen mit zwei Lesezeigern, damit ich aus der main die in der Timer ISR empfangenen Werte verarbeiten kann. Aber das liegt ja jetzt wieder in der ISR -> ein Lesezeiger und ein Puffer weniger -> Speicher + Aufwand gespart, sehr schön :) Wie Karl Heinz oben sagte: Ich habe das Hauptprogramm ziemlich aufgebläht, weil ich die ISR so kurz wie möglich halten wollte. Die ISR für die UART sollte machbar sein. Danke euch!
Karl Heinz Buchegger schrieb: > Wäsche in die Waschmaschine, Maschine einschalten > Kurz beim Herd vorbeischauen, ob das Wasser schon kocht > Ersten Brief öffnen, Rechnung beiseitelegen > Wasser kocht, also Nudeln rein > .... > > In keinem Fall bleibt sie daneben stehen und wartet darauf, dass etwas > fertig wird. Wenn es etwas zu warten gibt, dann wird eben in der > Zwischenzeit etwas anderes gemacht. Aber wehe die Freundin ruft an... Dann gibts kalt weil die Nudel kaputtgekocht sind :-) Also Jan, den "Freundin ruft an" Interrupt unbedingt gesperrt lassen.
Karl Heinz Buchegger schrieb: > Wenn du µC programmierst, musst du agierenb wie eine Hasufrau, die auch > 5 Sachen 'gleichzeitig' macht, indem sie zwischen den einzelnen Aufgaben > hin und herflitzt. > Wassser auf den Herd, Herd einschalten > Ab zur Waschmaschine, Wäsche sortieren > Zwischendurch mal schnell zum Postkastn, Post auf den Tisch > Staubsauger rausholen > Wäsche in die Waschmaschine, Maschine einschalten > Kurz beim Herd vorbeischauen, ob das Wasser schon kocht > Ersten Brief öffnen, Rechnung beiseitelegen > Wasser kocht, also Nudeln rein > .... > > In keinem Fall bleibt sie daneben stehen und wartet darauf, dass etwas > fertig wird. Wenn es etwas zu warten gibt, dann wird eben in der > Zwischenzeit etwas anderes gemacht. hahah :D Alles klar merke ich mir ;) UR-Schmitt schrieb: > Aber wehe die Freundin ruft an... > Dann gibts kalt weil die Nudel kaputtgekocht sind :-) > > Also Jan, den "Freundin ruft an" Interrupt unbedingt gesperrt lassen. mit Vergnügen.
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.