- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Main loop mit Hardware PWM "synchronisieren" (atxmega32a4) - oder anderer Ansatz...?

  1. #1
    Erfahrener Benutzer Roboter Genie Avatar von Willa
    Registriert seit
    26.10.2006
    Ort
    Bremen
    Alter
    43
    Beiträge
    1.273

    Frage Main loop mit Hardware PWM "synchronisieren" (atxmega32a4) - oder anderer Ansatz...?

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo,
    ich bin momentan dabei meinen "Shrediquette" Multicopter Code etwas aufzuräumen. Ich möchte gerne meinen Main Loop mit der Hardware PWM synchronisieren. Ich erkläre mal wie mein Code momentan noch aufgebaut ist, und was ich daran ändern möchte:


    • Im Moment habe ich einen main loop der frei läuft (mit ca. 800-900Hz). Dieser Loop fragt z.B. die Sensoren und die Fernsteuerung ab, macht ein paar PID Berechnungen und am Ende kommen immer neue Sollwerte für die Motoren heraus
    • Im Hintergrund läuft die ganze Zeit das Hardware PWM mit 500 Hz. Dieses benutzt die letzten Werte aus dem Main Loop und sendet sie per PWM die Motoren. Die Motorregler (zugekauft) haben eine Firmware die einen High Puls zwischen 125 und 250 µs verarbeiten, das nennt sich "OneShot125")


    Das ist natürlich nicht optimal... Am besten wäre wohl, wenn alles mit 500 Hz laufen würde: Die ganzen Berechnungen aus dem Main Loop werden ausgeführt, und sofort danach gehen die Pins für die Motorregler auf High und bleiben dort (je nach Sollwert) für 125 bis 250 µs. Am allerbesten wäre es natürlich wenn die Pins schon 125 µs vor dem Ende der Berechnungen auf High gehen.

    Hat jemand von euch vielleicht eine Idee wie so etwas normalerweise realisiert wird...? Ich habe noch einen 16bit Timer über... Könnte ich den mit 500 Hz laufen lassen und damit die Berechnungen im Main Loop starten? Dann am Ende der Berechnungen das PWM "resetten" (geht das überhaupt?), welches dann den entsprechen Puls erzeugt...?

    Ich würde mich über eure Anregungen und Denkanstöße freuen!
    Viele Grüße, William
    -> http://william.thielicke.org/

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    Hi,
    Ich steuere die Berechnungen/Tasks in der Main über einen Timer:
    Im Timer wird festgelegt zu welcher Zeit welcher Taskflag gesetzt wird.
    zB
    if (tasktimer==TASKPID1) {taskflag=PID1_flag;}
    if (tasktimer==TASKPID2) {taskflag=PID2_flag;}

    in der Main gibt es dann folgende if Anweisungen:
    if (taskflag== PID1_flag) {taskflag=taskflagclear;....
    if (taskflag== PID2_flag) {taskflag=taskflagclear;....

    Sensoren werden laufend in der Main loop abgefragt.

    Wobei die PID Regler bei mir mittlerweile im Timer Interrupt laufen, aber zu genauen Zeiten und zeitlich versetzt wie gezeigt mit tasktimer geregelt, hat sich für die Drehzahlregelung als beste Lösung erwiesen. Und das bei nur 4 und 8hz...
    Positionsberechnung oder Datentransfer über Bluetooth bleibt im Main.

    Ich verwende das um einen zeitlich genauen Ablauf zu erhalten. Zuvor konnte es passieren dass zufällig mehrere lange Berechnungen gleichzeitig anfielen und dann langsamer/nicht auf die Sensoren reagiert wurde. Jetzt gibt es genaue Zeitfenster, die Laufzeit der einzelnen Berechnungen hatte ich zuvor im Simulator ermittelt, und so wurde das ganze System leistungsfähiger.

    Vielleicht ist die Hardware PWM nicht sinnvoll und steuerst den Pin gleich über den PID Timer mit?

    LG!
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    31
    Beiträge
    1.578
    Hi Willla,

    den Mainloop würde ich nem Flag laufen lassen, welches in ner 500Hz Timer-Routine gesetzt und dann direkt im Mainloop wieder zurückgesetzt wird.
    Deine zweite Aufgabe stelle ich mir nicht so easy vor, aber ne erste Idee hätte ich:
    Die einzelnen Motorwerte der Größe nach sortieren und dann die Differenzen untereinander bestimmen, mit diesen Werten dann den Timer vorladen und in der Routine den entsprechenden Pin wieder auf Low setzen.
    Müsste man mal probieren, wieviel Overhead das wirklich erzeugt, aber es gibt sicher noch bessere Lösungen

    Gruß
    Chris

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    @Willa

    Ich würde da nichts synchronisieren sondern alles im Interrupt erledigen. Wenn ich dich richtig verstanden habe, werden deine PWM Signale mit 500 Hz (alle 2ms) in Hardware erzeugt. Da wird sich doch wohl ein Interrupt erzeugen lassen, entweder mit dem Überlauf des PWM-Timers oder mit einem der Matches. In diesem Interrupt wird alles erledigt, was mit der Motorsteuerung zu tun hat. Es ist damit immer synchron zu den Motoren. In deiner Main-Loop kannst du dann machen, was du willst. Das kann dann auch beliebig lange dauern.
    Zitat Zitat von damfino Beitrag anzeigen
    Wobei die PID Regler bei mir mittlerweile im Timer Interrupt laufen, aber zu genauen Zeiten und zeitlich versetzt wie gezeigt mit tasktimer geregelt, hat sich für die Drehzahlregelung als beste Lösung erwiesen. Und das bei nur 4 und 8hz...
    Positionsberechnung oder Datentransfer über Bluetooth bleibt im Main.

    Ich verwende das um einen zeitlich genauen Ablauf zu erhalten. Zuvor konnte es passieren dass zufällig mehrere lange Berechnungen gleichzeitig anfielen und dann langsamer/nicht auf die Sensoren reagiert wurde. Jetzt gibt es genaue Zeitfenster, die Laufzeit der einzelnen Berechnungen hatte ich zuvor im Simulator ermittelt, und so wurde das ganze System leistungsfähiger.
    Ich mach das nicht im Simulator, ich setze einen Pin für die Dauer des Interrupthandlers und messe mit Scope oder LA die Zeit. Da kann man dann auch ganz schnell sehen, was einzelne Operationen für Zeit kosten.

    Alles, was nicht ganz so schnell aber trotzdem synchron sein muß, verteile ich auf mehrere Interrupte. Dazu zähle ich im Interrupt eine Variable hoch. Bei jedem Zählerstand wird eine bestimmte Funktion ausgeführt, sind alle durch, wird der Zähler auf Null gesetzt.

    Bei einem solchen System kann es sein, daß mehr Zeit im Interrupthandler als in der Mainloop verbracht wird. Das ist auch OK, dort wird ja auch die meiste Arbeit geleistet. Insgesamt braucht man in einem solchen System nur einen Timer, der wird bei dir durch die HW-PWM schon da sein, und einen Interrupthandler. Das macht alles recht übersichtlich, konkurierende Interrupte kommen nicht vor. Man muß in der Mainloop auch nicht aufpassen, daß man irgendein gesetztes Flag verpasst, weil man mal zu langsam ist.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  5. #5
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    So schlimm ist das mit dem Synchronisieren der Main loop mit dem Interrupt nicht. Man warte halt in der Main loop einmal auf das Flag und löscht es dann gleich wider - da muss schon viel dazwischen kommen (mehr als doppelte Laufzeit für die Schleife) dass man da was verpasst. Wenn man mal etwas länger braucht wird das auch wieder aufgeholt - bei Interrupts bekommt man da schon eher Probleme, weil ggf. der 2. Interrupt ausgeführt wird bevor der 1. fertig ist. Den Nachteil den man mit viel Code in der ISR hat, ist dass man dann mit anderen ISRs eingeschränkt ist. Man kann zwar im Prinzip geschachtelte Interrupts zulassen, aber bei Bascom verbraucht das recht viel Speicher (RAM).

    Einen einmaligen Puls mit definierter Länge erzeugt man am besten per PWM Signal - nach dem Puls kann dann im Interrupt das PWM Signal wieder deaktiviert werden. Zumindest mit einem 16 Bit timer hat man da relativ viel Zeit für.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Besserwessi Beitrag anzeigen
    So schlimm ist das mit dem Synchronisieren der Main loop mit dem Interrupt nicht. Man warte halt in der Main loop einmal auf das Flag und löscht es dann gleich wider - da muss schon viel dazwischen kommen (mehr als doppelte Laufzeit für die Schleife) dass man da was verpasst. Wenn man mal etwas länger braucht wird das auch wieder aufgeholt
    Das gilt natürlich genauso für die ISR. Nur wartet die nicht auf das Flag, das Interrupt-Flag startet sie direkt.
    - bei Interrupts bekommt man da schon eher Probleme, weil ggf. der 2. Interrupt ausgeführt wird bevor der 1. fertig ist
    Solange man geschachtelte Interrupts nicht zuläßt, wird das nicht passieren.

    Die Restriktion, daß die Berechnung der Regelung (im Mittel) schneller sein muß, als der Regler tickt, gilt immer. Sonst ist der Prozessor zu langsam.
    Den Nachteil den man mit viel Code in der ISR hat, ist dass man dann mit anderen ISRs eingeschränkt ist.
    Das ist keine Einschränkung, die anderen ISRs müssen in Summe grundsätzlich so kurz sein, daß der Regler immer noch schnell genug ist, sonst s.o. Und sind sie das, ist in den Pausen zwischen dem Regler-Interrupt genug Zeit für sie. Wobei ich bevorzuge, wenn der Hauptinterrupt wie hier schnell (edit: hier gemeint häufig) läuft, die Interruptflags direkt aus dem ISR-Kontext abzufragen und die Abarbeitung gleich mit zu erledigen. Da hat man dann das Timing komplett unter Kontrolle und spart sich den Interrupthandler Overhead.

    Die Nachteile, in der Mainloop ein in der ISR gesetztes Flag zu pollen, überwiegen denk ich. Wenn man schon pollt, sollte man das Hardwareflagbit direkt pollen und sich die ganze ISR, die das Flag setzt, mit ihrem Overhead sparen. Der generelle Nachteil ist, daß ich beim Programmieren nicht nur die Regelung, sondern auch die Mainloop timen muß. Im Fall des TO darf sie auf keinen Fall länger als 2ms sein. Ein print, eine Displayausgabe oder ähnliches ist da nicht drin. Oder ich muß anfangen das nachzuprogrammieren, was mir die Interruptlösung umsonst liefert: das Aufteilen der Mainloop in kleine Stücken, zwischen denen ich immer wieder das Flag polle.

    MfG Klebwax
    Geändert von Klebwax (04.05.2015 um 18:17 Uhr)
    Strom fließt auch durch krumme Drähte !

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Eine ISR nur zum setzen einen Flags ist überflüssig - das ist schon mal richtig. Mit der Synchronisation der Hauptschleife hat man worst case schon mehr als 2 ms Zeit - man hat in Prinzip bis zu 2 ms Zeit, um die man mit der Ausführung auch mal hinterher hinken kann. Das darf nicht aber natürlich nicht aufsummieren, und die Regelung kommt dann ggf. auch eine Periode zu spät. Bei der ISR Lösung mit verschachtelten Interrupts wird es bereits nach einmal mehr als 2 ms kritisch.

    Den ganzen Code der in der Hauptschleife rund 1ms braucht allerdings in eine ISR zu schieben ist keine so gute Idee, vor allem wenn man nicht erlaubt den Interrupt noch unterbrachen zu lassen. Die Antwortzeit für andere Interrupts leidet dann doch schon erheblich und macht die fast unbrauchbar.

    Wenn es geht würde ich auch eher die Regelung und alles das Synchron mit dem PWM Signal laufen muss in ISRs legen. Normal sollte das auch nicht so lange dauern, wenn man es effektiv programmiert. Die Hauptschleife muss dann ggf. nicht mehr auf das PWM Signal warten und kann langsame Dinge machen. Eine Display-ausgabe wird man im Flug eher nicht brauchen.

    Wenn es zeitkritisch wird, hätte man ggf. noch die Möglichkeit von Bascom auf GCC umzusteigen - das wird oft einiges schneller.

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Besserwessi Beitrag anzeigen
    Wenn es geht würde ich auch eher die Regelung und alles das Synchron mit dem PWM Signal laufen muss in ISRs legen. Normal sollte das auch nicht so lange dauern, wenn man es effektiv programmiert. Die Hauptschleife muss dann ggf. nicht mehr auf das PWM Signal warten und kann langsame Dinge machen. Eine Display-ausgabe wird man im Flug eher nicht brauchen.
    Ich denke es geht darum, sich einen Freiraum zu schaffen. Alles zeitkritische in die ISR, und man hat volle Freiheit in der Mainloop. Wenn die ISR erstmal fertig debugged ist, hat man ein stabiles System und kann experimentieren.

    Ein Display könnte auch an Bluetooth oder WLAN hängen, und das braucht nicht schneller zu sein, als ein Mensch es ablesen kann (egal, wie schnell der Regler läuft).

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  9. #9
    Erfahrener Benutzer Roboter Genie Avatar von Willa
    Registriert seit
    26.10.2006
    Ort
    Bremen
    Alter
    43
    Beiträge
    1.273
    Hi,
    danke für eure zahlreichen Beiträge & Vorschläge! Da werde ich mich gleich mal durcharbeiten. Bei meiner Regelung ist das Hauptziel nicht die Synchronität, sondern der minimale Zeitversatz zwischen Sensoren auslesen / Rechnen / PWM ausgeben. Wobei das natürlich auch zusammenhängt. Ich versuche mich mal einfach heranzutasten das Ganze überhaupt richtig zu verstehen... Denn im Moment verstehe ich noch alles maximal halb. Ist folgendes richtig?


    Mein PWM Timer ist so konfiguriert:
    Code:
    Config Tcd0 = Pwm , Prescale = 1 , Comparea = Enabled , Compareb = Enabled , Comparec = Enabled , Compared = Enabled , Event_source = Off , Event_action = Off , Event_delay = Disabled , Resolution = 16
    Der µC läuft mit dem internen 32 MHz Takt.

    TcD0_cnt ist der aktuelle Wert vom PWM Timer. Dieser läuft immer wieder von 0 auf 65535. Wenn TcD0_cnt den Wert null erreicht gehen alle PWM Pins auf High. Sobald TcD0_cnt einen bestimmten Wert erreicht (eingestellt per Tcd0_cca, Tcd0_ccb, Tcd0_ccc und Tcd0_ccd) geht der entsprechende Pin auf Low.

    Ich muss die Berechnungen der Regelung starten kurz bevor TcD0_cnt sein Maximum erreicht. Angenommen die Berechnungen dauern 1 ms, dann muss ich die Berechnungen bei TcD0_cnt = 33535 starten. Wenn TcD0_cnt den Wert 65535 erreicht hat sind meine Berechnungen fertig (32000 Ticks bzw. 1 ms später). Bei TcD0_cnt = 65535 bzw. 0 gehen die PWM Pins hoch und bleiben dort bis die errechneten Werte (Tcd0_cca bis Tcd0_ccd sind immer zwischen 4000 und 8000 = 125 bis 250 µs) erreicht wurden.

    Mir wurde immer gepredigt, dass man so wenig Code wie möglich im IRQ laufen lassen soll... Es gibt ja auch noch einen zweiten Interrupt vom RC Empfänger der sehr präzise sein muss. Für mich klingt es am einfachsten in der Main Loop den Wert von TcD0_cnt abzufragen und die Berechnungen zu starten sobald dieser größer als 33535 ist.
    z.B. so:
    Code:
    if TcD0_cnt < 33535 then
       RechnenDarfGestartetWerden = 1
    end if
    if TcD0_cnt > 33535 AND RechnenDarfGestartetWerden = 1 then
       RechnenDarfGestartetWerden = 0
       RechneAllesAus
    end if
    Lasst mich raten: So geht es nicht. Wäre ja auch zu schön. Ich probiere es jetzt trotzdem aus und berichte was passiert.

    - - - Aktualisiert - - -

    Lasst mich raten: So geht es nicht. Wäre ja auch zu schön. Ich probiere es jetzt trotzdem aus und berichte was passiert.
    Hmmm... Also ich habe das so mal eingebaut, und Schwuuupps, mein Code läuft mit genau 500 Hz. Ich habe kein Oszi hier, deswegen kann ich nicht gucken ob der Code wirklich das tut was er soll (außerdem weiß ich auch nicht wie lange meine Berechnungen denn wirklich brauchen). Aber ich denke mal rein theoretisch sollte das doch gehen... Ist dieser Ansatz programmiertechnisch sehr schlimm, oder kann ich das so machen?

    - - - Aktualisiert - - -

    Noch ein kurzer (evtl. schwachsinniger) Gedanke: Angenommen, ich verwende den Code so wie vorgeschlagen. Dann wäre es cool, wenn der Zeitpunkt zu dem die Berechnungen gestartet werden sich automatisch optimal einstellt. Ich kann mit einer groben Schätzung starten, und dann verschiebt sich der Start (z.B. um 0.1 ms) nach vorne falls eine Berechnung mal nicht fertig wurde. Ansonsten wird der Start Zeitpunkt immer ganz langsam nach hinten verschoben (z.B. jeden Durchgang um 0.001 ms). So pendelt der Startzeitpunkt um den optimalen Wert herum, egal was ich noch alles so an Berechnungen einbaue.
    Geändert von Willa (06.05.2015 um 22:15 Uhr) Grund: im zweiten if ein argument vergessen...
    Viele Grüße, William
    -> http://william.thielicke.org/

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Willa Beitrag anzeigen
    Hi,
    danke für eure zahlreichen Beiträge & Vorschläge! Da werde ich mich gleich mal durcharbeiten. Bei meiner Regelung ist das Hauptziel nicht die Synchronität, sondern der minimale Zeitversatz zwischen Sensoren auslesen / Rechnen / PWM ausgeben.
    Der minimale Zeitversatz ist erreicht, wenn die Berechnung synchron zur PWM ist. Ich spring jetzt mal

    Dann wäre es cool, wenn der Zeitpunkt zu dem die Berechnungen gestartet werden sich automatisch optimal einstellt.
    Der Zeitpunkt ist unerheblich, der Wert nachdem sich der Motor richtet, kann nur alle 2ms geändert werden. Feiner löst dein System nicht auf. Und wann du die Berechnung startest ist auch egal, sie muß nur zum nächsten 2ms Takt fertig sein.

    Mir wurde immer gepredigt, dass man so wenig Code wie möglich im IRQ laufen lassen soll... Es gibt ja auch noch einen zweiten Interrupt vom RC Empfänger der sehr präzise sein muss. Für mich klingt es am einfachsten in der Main Loop den Wert von TcD0_cnt abzufragen und die Berechnungen zu starten sobald dieser größer als 33535 ist.
    Mit Predigten ist das so eine Sache. Da wird versucht, einen komplexen Sachverhalt in einen möglichst kurzen Satz zu quetschen. Ich würd das mal so sagen: man sollte nicht mehr Code als nötig im Interrupthandler laufen lassen. Ich kenne Systeme und hab auch schon welche gebaut, die nur im Interrupthandler laufen. Auch das passt zu "nicht mehr als nötig", mehr war eben nicht nötig. Solche Systeme sind leichter deterministisch hinzubekommen und bewegen sich in Richtung Echtzeitsystem. Und ein Regler (z.B. Drehzahl, Geschwindigkeit, Lage etc) ist ein Echtzeitsystem.

    Hmmm... Also ich habe das so mal eingebaut, und Schwuuupps, mein Code läuft mit genau 500 Hz. Ich habe kein Oszi hier, deswegen kann ich nicht gucken ob der Code wirklich das tut was er soll (außerdem weiß ich auch nicht wie lange meine Berechnungen denn wirklich brauchen). Aber ich denke mal rein theoretisch sollte das doch gehen... Ist dieser Ansatz programmiertechnisch sehr schlimm, oder kann ich das so machen?
    Wenn es um Predigten geht, kann etwas "schlimm" sein. In der Technik gibt es nur unklug oder ungeschickt. Wenn man weiß, was man tut, kann man alles machen.

    Dein Regler, deine Mainloop lief bisher mit 900Hz, wenn ich das recht in Erinnerung habe. Ihn auf 500Hz runterzubremsen ist leicht, wie du siehst. (Ich wechsel jetzt mal in die Zeitebene) Deine Rechnung dauert etwa 1ms, Ergebnisse werden alle 2ms benötigt, also alles im grünen Bereich. Machst du jetzt in der Mainloop etwas, das möglicherweise nichts mit dem Regler zu tun hat, aber länger als 1ms dauert, ist dein System geplatzt, und du verpasst die nächste PWM Phase.(@Besserwessi: einmal gehts noch gut)

    Das sind meine Bedenken zu deinem Ansatz, ich hab oben schon einiges dazu gesagt. Aber laß dich von mir nicht irre machen, ein oder zwei mal hab ich auch schon Mist programmiert.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. "RS232-Kabel" oder "USB-ISP-Kabel" zum Programmieren des RN-Control 1.4
    Von Soeren7 im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 14
    Letzter Beitrag: 25.07.2012, 15:54
  2. Antworten: 2
    Letzter Beitrag: 15.06.2011, 22:18
  3. Anderer Sensor für "Alarmanlage"
    Von pacman im Forum Sensoren / Sensorik
    Antworten: 0
    Letzter Beitrag: 20.03.2011, 15:05
  4. Hardware-PWM-Signal "umleiten"
    Von chris@franke im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 3
    Letzter Beitrag: 28.01.2010, 17:24
  5. mit PDA-WLAN "roboter" oder ähnliches steuern
    Von Felixx87 im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 31.12.2004, 08:29

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test