Forum: Mikrocontroller und Digitale Elektronik Interrupt-/Timing- Verhalten bei Flugsteuerrung


von Marcel B. (cable545)


Lesenswert?

Hallo,

ich arbeite zur Zeit an einer Flugsteuerung für einen Quadrocopter. Ich 
bin jetzt soweit, dass ich die Lageermittlung, also roll, pitch und yaw, 
sowie die Aufbereitung des Summensignals des Empfängers für die 
Lageregelung fertig hab.

Die Lageermittlung wird per Interrupt alle 10ms durchgeführt. Das heißt 
Sensoren(Gyro, Accelerometer, Magnetometer) auslesen sowie Berechnung 
der entsprechenden Euler Winkel. Die ganze Aktion dauert ca. 3,1 ms.

Die Ermittlung der Steuerwerte aus dem Summensignal wird ebenfalls per 
Interrupt gesteuert. Nach jeder fallenden Flanke am IO Port wird ein 
Timer auf null gesetzt und der alte Zählwert gespeichert. Dabei ist ein 
gültiger Steuerimpuls zwischen 1 und 2ms lang. Ich nutze gerade vier 
Kanäle und habe dementsprechend 4 gültige Impulse und einen entprechend 
längeren, welchen ich zum synchronisieren nutze.

Nun zu meinem Problem:
Da beide Teile ja Interrupt gesteuert sind, kommt es häufig vor, dass 
sich diese auch mal in die Quere kommen.
Die Lageermittlung muss per Interrupt gesteuert werden, da ich ja das 
Gyro Signal aufintegriere. Ich könnte den Interrupthandler natürlich auf 
das Lesen der Sensoren beschränken und die eigentliche Berechnung in die 
Main packen. Jedoch spare ich mir dadurch nur ca. 1,1 ms.

Ich hab momentan die Lageermittlung höher priorisiert als das Ermitteln 
der Steuerwerte. Allerdings wird dadurch das Auslesen des Summensignals 
öfter mal unterbrochen(Nested Interrupts) und dadurch die Zählerwerte 
versaut.

Ich drehe mich also irgendwie im Kreis und wollte nun mal fragen wie das 
Timing der einzelnen "Jobs" in einer Flugsteuerung sonst so gehandhabt 
wird?

Eine Idee war es, die Steuerwerte der Zähler nicht per Interrupt zu 
speichern sondern die Zählerwerte per DMA zu speichern. Aber die 
Nachbereitung der gespeicherten Werte kommt mir äußerst kompliziert vor.

von Karl H. (kbuchegg)


Lesenswert?

Marcel B. schrieb:

> Die Ermittlung der Steuerwerte aus dem Summensignal wird ebenfalls per
> Interrupt gesteuert. Nach jeder fallenden Flanke am IO Port wird ein
> Timer auf null gesetzt und der alte Zählwert gespeichert.

Hat dein (unbekannter µC) keine Capture Fähigkeit am Timer?

Wenn dem so wäre, dann würde der Timer ganz von alleine beim 
Fernsteuerpuls den gerade aktuellen Timerwert speichern und einen 
Interrupt anmelden. Die Abarbeitung des Interrrupts kann dann auch ein 
bisschen warten, denn der kritische Timerwert wurde ja bereits von der 
Hardware gesichert. Du musst den Timer auch nicht 0 setzen. Denn eine 
Subtraktion des aktuellen Wertes vom vorhergehenden Wert liefert dir 
ebenfalls die Information, wieviele Timerticks vergangen sind.

> Die Lageermittlung muss per Interrupt gesteuert werden, da ich ja das
> Gyro Signal aufintegriere. Ich könnte den Interrupthandler natürlich auf
> das Lesen der Sensoren beschränken und die eigentliche Berechnung in die
> Main packen. Jedoch spare ich mir dadurch nur ca. 1,1 ms.

Du musst auch nicht alle Sensoren in einem Aufwasch auslesen. Wenn du 
das 3 teilst (1. ISR-Aufruf Gyro, 2.ter ISR Aufruf Accell, 3. ISR Aufruf 
Magnetometer), dann kannst du zwar die ISR Aufrufe schneller machen, 
aber: du gibst zwischendurch immer wieder Rechenzeit frei, in der ein 
eventuelle Input Capture vom Fernsteuerungs-'Timer' behandelt werden 
kann.

Generell ist das Geheimnis bei 'gleichzeitiger' Bearbeitung von mehreren 
Dingen, nie zu viel Zeit an einer einzigen Sache zu verweilen. Du musst 
nicht die Sensoren in einem Rutsch auslesen. Wenn du nach 10ms einen 
kompletten Satz an Messwerten beisammen hast, dann reicht das doch.

von CaptainAlbern (Gast)


Lesenswert?

Um das PPM-Signal auszuwerten ist unbedingt ein Interrupt notwendig, da 
du die Zeit exakt bestimmen musst. Alles andere kann asynchron davon 
erfolgen, also ohne Interrupt. Damit erledigen sich viele Probleme und 
Gedanken daran.

Meine Erfahrung: Lageerfassung und Regelung alle:
20ms -> es fliegt, aber nicht gut
10ms -> es fliegt gut
5ms -> es fliegt gut und ist sogar recht unempfindlich gegen liederlich 
eingestellte Reglerparameter

Acc und Gyro kannst du alle 5ms abfragen und auswerten. Mag ist nicht so 
dringend. Für die Integration der Eulerwinkel kannst du die Zeit 
zwischen zwei Aufrufen messen und multiplizieren. Lageerfassung, 
Regelung und Steuersignalausgabe sollten immer der Reihe nach und nicht 
asynchron zu einander erfolgen. Die Erfassung der Steuersignale von der 
Fernbedienung hingegen kann asynchron dazu sein. So schnell regelt man 
ja nicht per Hand, <20ms Offset reichen gut.
Mit einem 16MHz 8Bit Controller lassen sich 5ms Zyklus erreichen, auch 
wenn man mehrere Aufgaben (z.B. Datenlogging) zu tun hat.

Zu beachten ist auch, dass die Motorregler auch mit entsprechender 
Frequenz angesteuert werden können. Wenn sie nur die klassischen 50Hz 
verarbeiten, nützt eine schnellerer Regelung natürlich nichts.

von Marcel B. (cable545)


Lesenswert?

Ich nutze einen MKL46Z256 von Freescale mit Arm Cortex M0+ Kern.
Die kritischen Werte werden per Capture Funktion im Timer gesichert. 
Jedoch muss ich den "gefangenen" Wert im Register auch entsprechend 
zügig speichern, also den Interrupt bearbeiten, damit mir im 
ungünstigsten Fall 1 ms später nicht ein Wert für den nächsten Kanal 
verloren geht.

@Karl Heinz
Aber generell verstehe ich, was du meinst. Ich werde die Interrupt 
Routine für die Bearbeitung der Sensorwerte mal ein bißchen aufdröseln. 
Mal sehen wie sich das ganze verhält.

von CaptainAlbern (Gast)


Lesenswert?

noch kurz ein paar Tipps zum Thema Timing in der Flugsteuerung:

Wie gesagt, verwende ich nur für das PPM-Einlesen einen Interrupt. Alles 
andere rechne ich in einer Schleife. Fast alle Teilfunktionen haben eine 
konstate Laufzeit. Die Schleife ist bei mir 20ms lang und schnelle 
Teilfunktionen werden 2x oder 4x pro Durchlauf aufgerufen.

Nicht konstant ist die Auswertung der GPS-Messages, die seltener kommen 
(alle 100ms). Die Auswerung habe ich so programmiert, dass sie bei 
Zeitknappheit abbricht und im nächten 5ms-Slot weiterrechnet.

Das einzige, was wirklich manchmal länger blockiert ist das Datenlogging 
auf SD-Karte. Dazu verwende ich eine Library und kann daher das 
Verhalten nur hinnehmen. Der Drucksensor ist derjenige, der es am 
übelsten nimmt, wenn er deutlich verspätet ausgelesen wird. Daher 
plausibilisiere ich den Wert und verwerfe einzelne Samples im Zweifel.

Auch zum Generieren von PPM- und PWM-Signalen und für die Serielle 
Schnittstelle benutze ich die eingebauten Libraries. Daher kann ich 
nicht sagen, inwiefern die auch Interrupts verwenden. Auf jeden Fall 
stören sie nicht. Die Auswertung des Fernsteuereingangs ist sehr exakt 
(besser, als man den Finger still halten kann).

von Karl H. (kbuchegg)


Lesenswert?

Marcel B. schrieb:
> Ich nutze einen MKL46Z256 von Freescale mit Arm Cortex M0+ Kern.
> Die kritischen Werte werden per Capture Funktion im Timer gesichert.
> Jedoch muss ich den "gefangenen" Wert im Register auch entsprechend
> zügig speichern, also den Interrupt bearbeiten, damit mir im
> ungünstigsten Fall 1 ms später nicht ein Wert für den nächsten Kanal
> verloren geht.

Eben.
Und genau da kommt das Aufteilen der Sensorabfragen ins Spiel. Wenn alle 
Sensorgruppen zusammen 2ms Zeit verbraten, jede einzelne Gruppe aber nur 
0.7ms, dann hast du deine Forderung, dass du spätestens 1ms nach 
Auftreten den Capture Wert abholen kannst ja locker erfüllt.

von Marcel B. (cable545)


Lesenswert?

Ich habe es nun so umgesetzt, wie von CaptainAlbern vorgeschlagen. Der 
einzige Interrupt ist nun der, welcher das Summensignal vom Empfänger 
bearbeitet, bzw. die einzelnen Bestandteile der Kanäle abspeichert. Das 
Auslesen der Sensoren über I2C wird in der main() gemacht.

Ich hätte es gerne umgesetzt, wie von Karl Heinz beschrieben. Denn diese 
Lösung wäre zwar nicht unbedingt die einfachere, aber dafür die 
transparentere Lösung, was die Übersicht der einzelnen Timings angeht, 
gewesen. Aber aus welchen Gründen auch immer dauerte das Auslesen über 
I2C für einen Sensor dann doch mal annähernd 1ms und somit gab es 
Situationen in denen der andere Interrupt blockiert wurde.

Ich werde mir das aber bei Gelegenheit nochmal genauer anschauen. Ich 
danke euch für den netten Support!!!

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
Noch kein Account? Hier anmelden.