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.
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.
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.
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.
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).
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.