4.0 KiB
11. Aufgabe 7 - Integration
11.1. Aufgabenteil 1
In dieser Aufgabe sollen die zuvor erstellten Programmodule zusammengesetzt werden. Es soll ein balancierender Roboter entstehen. Erstellen Sie auf Basis des in Aufgabe 6 genutzten Taskset-Simulators ein Taskset, dass ihre Tasks periodisch ausführt. Denken Sie daran ihre Init-Funktionen einzutragen. Nachfolgend werden die Anforderungen an die bisherigen Programme aufgelistet:
11.1.1. PID
Eingänge:
- Aktueller Winkel der IMU
- Sample Time
Funktion
- PID Wert erstellen
Ausgänge
- PID Wert zwischen -1000 und 1000
Hinweis: Der PID Regler mittelt für die ersten 10 Sekunden nach Start den Nullpunkt zur Kalibrierung
11.1.2. IMU
Funktion
- IMU initialisieren
- Werte über I2C auslesen
Ausgänge
- IMU Winkel
11.1.3. Motortreiber
Eingänge
- PID Wert
Funktion
- Ansteuern der Richtung der Motoren für vorwärts und rückwärts
- Regeln der Frequenz der Steps: Frequenz: min. 800us/step, max 100us/step
11.2 Aufgabenteil 2
Sie finden sich nun in einem Szenario der Wirtschaft: Ihr Vorgesetzter schränkt ihre Ressourcen auf dem genutzten Steuergerät ein, weil diese anderweitig genutzt werden. Verändern Sie dazu in der Datei gt_tasks.c das Struct GT_AllTasks wie folgt und fügen Sie die Zeile
{50, 0, 0, {3, 5}};
Quellcode 11.1: Ergänzung Task Timing Struct
hinzu. Außerdem sollen Sie in dem Struct GT_Tasks die Zeile
{ GT_TASK_DEF, GT_ACT_INT, 4, 29, NULL, NULL, NULL, GT_RUNABLE_NULL,
GT_INTERNAL_NULL, (void *)>_AllTasks[4]},
Quellcode 11.2: Ergänzung Task Struct
hinzufügen. Achten Sie darauf die Konstante GT_NUM_OF_TASKS anzupassen. Ihre Aufgabe ist es nun, die Funktionalität des Roboters wiederherzustellen. Untersuchen Sie dafür, wo im Programm CPU Zeit eingespart werden kann.
Um die in diesem Bereich genutzte CPU-Zeit zu reduzieren bietet es sich an die Kommunikation mit der inertialen Messeinheit zu verändern. Die Hardwareeinheit des Xynq- 7000 macht es möglich nach jeder abgeschlossenen Kommunikation einen Interrupt auszulösen. Wir können die Kontrolle somit während des Senden an andere Tasks abgeben. Orientieren Sie sich für das Erstellen und Verknüpfen des Interrupts an dem des Timers. Suchen Sie nach geeigneten Funktionen vergleichbar zu denen, die bei der Einrichtung des Timer-Interrupts genutzt wurden. Grundsätzlich sollten Sie wie folgt vorgehen:
- Erstellen Sie einen Interrupt und suchen Sie die korrekte Interrupt-ID heraus, geben Sie als Interrupt-Handler MasterInterruptHandler an.
- Die I2C Instanz hat einen Statushandler der angegeben werden kann, er bietet sich an um die Semaphore zu pushen
- Die Funktionen XIicPs_MasterSendPolled und XIicPs_MasterRcvPolled haben passende Gegenstücke zur Nutzung mit Interrupts der I2C Hardware. Nach dem Aufrufen der Funktion muss auf die Fertigstellung gewartet werden. Dies wird über den Semaphore realisiert.
Zunächst muss eine Interrupt-Service-Routine (ISR) erstellt und im Setup dem Iic-StatusHandler übergeben werden.
Erstellen Sie zudem ein globales Semaphor. Nutzen Sie hierfür die Funktion
OS_SemCreate(...);
Tipp: Überlegen Sie sich was ein sinnvoller initial-Wert für das Semaphor in diesen Anwendungsfall ist.
Wir erstellen einen Interrupt welcher ausgelöst wird, wenn die I2C Kommunikation abgeschlossen ist. Die Interrupt ID ist XPS_I2C1_INT_ID. Dazu können die folgenden Methoden genutzt werden.
UCOS_IntVectSet(...);
UCOS_IntSrcEn(...);
Zuletzt müssen Sie noch die I2C Kommunikation überarbeiten. Während der Übertragung soll dem System nun erlaubt werden andere Tasks zu schedulen. Überlegen Sie hierfür wann das von Ihnen erstelle Semaphor dafür Ressourcen freigeben und wann wieder blockieren soll.
Hierfür können folgende Methoden genutzt werden:
OSSemPend(...);
OSSemPost(...);
**Hinweis:** Sie müssen zudem die Funktionen
XIicPs_MasterSendPolled(...);
// und
XIicPs_MasterRecvPolled(...);
durch folgende Funktionen ersetzen:
XIicPs_MasterSend(...);
XIicPs_MasterRecv(...);