Softwaredesign für Motorsteuerungen

Ich muss einen PID-Regler für einen Differentialantriebsroboter entwerfen.

  • Die Hardwareplatine besteht aus einem AVR atmega168, der mit 16 MHz läuft.
  • Angetrieben von zwei 24-V-Rollermotoren mit 256 CPR-Encodern
  • Die Motoren drehen ungefähr mit etwa 4700 U / min und haben ein Übersetzungsverhältnis von 51,56: 1

Bisher kann ich die Encoderrichtung und die Tickzahl ablesen. Aber ich habe keine Ahnung, wie ich das in Geschwindigkeit umwandeln kann. Und schließlich ein PID-Regler. Ich möchte auch in der Lage sein, den Roboter in einem bestimmten Winkel zu drehen. Kann mir bitte jemand beim Einstieg helfen?

Derzeit habe ich Probleme, eine geeignete Timer-Berechnung dafür herauszufinden.

gut .. Sie können die Position differenzieren, um Geschwindigkeit zu erhalten. Wenn Sie den Winkel beispielsweise 50 Mal pro Sekunde messen, wissen Sie, wie weit er in 1/50 Sekunde gedreht wird, also wären 50 Mal Grad (oder welche Winkeleinheit Sie auch immer verwenden) pro Sekunde.
Änderung der Anzahl/Winkel im Laufe der Zeit?
Sind die Encoder vor oder hinter den Getrieben? (Vermutlich früher, aber ...)
Bitte teilen Sie die Fragen in einzelne spezifische Fragen auf
Für einen PID-Controller: Vielleicht möchten Sie diese beiden Blog-Einträge lesen, die ich geschrieben habe: embeddedrelated.com/showarticle/121.php

Antworten (3)

Danke an alle für die nützlichen Kommentare.

Ich habe erreicht, was ich wollte, indem ich einen einfachen Geschwindigkeits-PID-Regler implementiert habe.

Durch zwei Interrupts (für jeden Encoder) habe ich berechnet, wie viele Encoder-Ticks in einem bestimmten Zeitintervall akkumuliert wurden. Das von mir verwendete Intervall betrug 10 ms und dies wurde durch die Verwendung der Timer-Vergleichsfunktion auf Timer1 der AVR-MCU erreicht. Encoder-Ticks wurden berechnet, indem die Differenz der vorherigen Encoder-Ticks und der aktuellen Ticks genommen wurde. Diese wurde dann als Geschwindigkeits-PV des PID-Reglers verwendet. Die Abtastrate des PID-Reglers wurde ebenfalls mit 10 ms durchgeführt. Nur um die Dinge einfach zu halten.

Ich habe eine einfache MATLAB-GUI geschrieben, um SP, PV der Sprungantwort des PID-Reglers grafisch darzustellen. So habe ich den PID-Regler manuell eingestellt. Es ist vielleicht nicht der beste Weg, aber sicherlich der einfachste Weg, den ich mir vorstellen kann, um den Controller abzustimmen.

Ich werde dies bei Gelegenheit in meinem Blog-Post dokumentieren und einen Link dazu in diesen Post setzen, damit es für jeden hilfreich ist.

Deine Frage ist etwas zweideutig. Fragen Sie, wie Sie einen Timer auf dem Mikrocontroller verwenden, oder fragen Sie, wie Sie die Winkelgeschwindigkeit anhand der Zählung eines Encoders und der von einem Timer angegebenen verstrichenen Zeit berechnen?

Der atmega168 sollte mindestens zwei Timer haben. Wenn mein Gedächtnis mich richtig bedient, gibt es zwei 8-Bit-Timer und einen 16-Bit-Timer. Dies sind im Mikro integrierte Peripheriegeräte, die im Hintergrund laufen können, sodass die CPU Ihres Mikros andere Aufgaben erledigen kann.

Eine Möglichkeit, dies zu tun, ist: (a) Initialisieren und starten Sie den Timer und setzen Sie den Encoderzähler zurück (b) Schreiben Sie eine Interrupt Service Routine (ISR), die aufgerufen wird, wenn der Timer endet, den Timer neu startet und die Winkelgeschwindigkeit berechnet. (c) Schreiben einer weiteren ISR, die durch den Codierer-Ausgangs-Tick getriggert wird und die einen globalen Tick-Zähler inkrementiert. (d) in der Timer-ISR wissen Sie die verstrichene Zeit seit dem letzten Aufruf, seit Sie den Timer initialisiert haben, haben Sie dies angegeben. Sie haben die Anzahl der Encoder-Ticks seit dem letzten Timer-ISR-Aufruf. Daher können Sie die Ticks pro Zeiteinheit berechnen. Sie sollten aus den mechanischen Details Ihres Roboters die Anzahl der Ticks pro Einheitswinkel der Raddrehung kennen, daher sollten Sie in der Lage sein, die Winkelgeschwindigkeit des Rads zu berechnen.

Dadurch erhalten Sie die durchschnittliche Winkelgeschwindigkeit innerhalb der Timer-Periode. Passen Sie die Zeitdauer des Timers so an, dass sie für Ihre Anwendung gut funktioniert.

Dies ist nur eine Möglichkeit, dies zu tun. Ich kann mir andere vorstellen. Ich habe jedoch festgestellt, dass dieser Algorithmus für mich zuvor gut funktioniert hat.

Dies wird bei zwei Motoren ziemlich schwierig, da Sie zwei Encoderkanäle pro Motor beobachten müssen. Nicht unmöglich, aber viel wirklich sorgfältiges Codieren, um sicherzustellen, dass Sie keine Übergänge von beiden Kanälen des Encoders an beiden Motoren verpassen (dh Sie müssen auf Ereignisse auf 4 Dinge achten, und obwohl es eine Korrelation zwischen den Kanälen gibt, gibt es keine zwischen den Motoren). Es besteht die Versuchung, jedem Motor einen eigenen Mikrocontroller zu geben oder einen Quadraturzähler-Chip zu verwenden, um die Rückkopplung zu erfassen (oder in einem billigen CPLD einen eigenen zu bauen).

Da Sie in der Lage sein möchten, präzise Winkel zu drehen, vermutlich durch unterschiedliche Drehung der beiden Räder, würde ich in Betracht ziehen, ein Paar Positionsregler anstelle eines Geschwindigkeitsreglers herzustellen, von denen jeder seinen Motor drehen würde, um die erzielten Zählungen mit den Zählungen auszugleichen in einem gewünschten Positionsregister. Um die Dinge zu vereinfachen, könnte Ihre primäre Befehlsschnittstelle eine vorzeichenbehaftete Zahl (mit mindestens 16 Bit, aber wahrscheinlich 24 oder sogar 32) sein, die zu der gewünschten Position hinzugefügt wird, die jeder Controller sucht.

Auf einer höheren Ebene hätten Sie dann einen Bewegungsplaner, der dies periodisch verwendet, um die gewünschten Positionen zu aktualisieren. Wenn Sie sich mit einer festen Geschwindigkeit bewegen, geben Sie einfach alle m Millisekunden einen Befehl für weitere n Schritte aus, wenn Sie beschleunigen oder verlangsamen, werfen Sie weniger ein. Zum Drehen schickt man dem einen eine positive Zahl und dem anderen eine weniger positive (oder vor Ort negative) Zahl. Konzeptionell ist dies dasselbe, unabhängig davon, ob Sie zwischen logischen Blöcken in einem Programm auf einem Prozessor kommunizieren oder Slave-Prozessoren befehlen.