Onboard Software

Inhaltsverzeichnis[Anzeigen]

Regelung

Sowohl Höhen- als auch unsere Richtungsregelung werden mittels PID-Regler gesteuert.

Die Höhenregelung wandelt per PID-Regler die gemittelten Höhenwerte des Ultraschallsensors und die empfangene Sollhöhe in Schubwerte für den Höhenmotor um. Die Parameter des PID-Reglers sind 5, 0.6 und 13, jeweils für den proportionalen, integralen und differentiellen Anteil. Diese Parametergrößen hat das Team experimentell ermittelt. Die Höhenregelung soll die gewünschte Sollhöhe möglichst schnell erreichen, jedoch dabei nicht zu weit überschwingen.

Zur Richtungsbestimmung hatte das Team geplant, ein Doppel-IPS System zu implementieren, das zwei Punkte der Gondel bestimmt, um daraus eine Position und eine Richtung zu erhalten. Dies hat dann auf Grund von mangelnder Zeit und Arbeit nicht geklappt. Stattdessen haben wir die Inertial Measurement Unit, das IMU-Board, genutzt. Nach dem Ansprechen des Boardes auf der Adresse 0x69 konnten wir, mit Hilfe des Codes auf der Sparkfun-Webseite (mpu6050_raw.ino), die Rohdaten auslesen. Nach ein wenig Recherche erwies sich die Breakout-Version des Codes (mpu6050_breakout.ino) als hilfreich. Dadurch wurde ein Kompass implementiert, der die in der Raumfahrt üblichen yaw, pitch und roll Koordinaten mit Hilfe von Quaternionen, Tilt Compensation und dem DCM Algorithmus von Mahony sehr zuverlässig ausgibt. Um eine korrekte Ausrichtung der Gondel zu erhalten, mussten die Offset-Werte der IMU ermittelt und entsprechend miteinbezogen werden. Die Richtungswerte werden dann mit der von der Bodenstation erhaltenen Sollrichtung mittels PID-Regler geregelt und in Schubgrößen umgewandelt.

Da die Ausgangswerte der Regler direkt als byte-Größe für die Motorensteuerung übernommen wurden, ergab es sich als vorteilhaft, die Ausgangsgrenzen des Reglers zu berücksichtigen. Mit zu großen Outputs hat der Motor zu schnell seinen maximalen Schub erreicht, dies führte zu heftigen Überschwingungen in der Höhenregelung. Um die Richtung möglichst ohne Schwingungen zu halten, musste der Proportionalanteil ein wenig erhöht werden, um bei einer kleinen Abweichung gleich gegenzusteuern.

Zunächst müssen die beiden PID-Regler in der Software angelegt werden:

//PID-Regler für Höhenregelung
PID hoehePID(&istH, &geschwindigkeitH, &sollH, 5, 0.6, 13, DIRECT);

//PID-Regler für Richtungsregelung
PID richtungsPID(&phiFusion, &geschwindigkeit_r, &sollPhi, 5, 0.6, 13, DIRECT);

Danach werden die beiden PID-Regler initialisiert, indem im setup() folgende Funktion aufgerufen wird:

void init_PID() {
  //init PID-Regler für Höhenregelung
  hoehePID.SetOutputLimits(-80, 160);       //Outputlimits für den Regler
  hoehePID.SetMode(AUTOMATIC);             //aktiviert PID-Regler
  hoehePID.SetSampleTime(200);              //Sample Time des PID für die Höhenregelung
  
  //init PID-Regler für Richtungsregelung
  richtungsPID.SetOutputLimits(-70, 70);     //Outputlimits für den Regler
  richtungsPID.SetMode(AUTOMATIC);         //aktiviert PID-Regler
  richtungsPID.SetSampleTime(200);          //Sample Time des PID für die Richtungsregelung
}

In der loop() werden die beiden Regler durch folgende Befehle immer wieder aufgerufen. Die Library stellt sicher, dass die Regler dann immer im vorgegebenen Intervall (hier alle 200ms) abgearbeitet werden und die neuen Werte für den Output berechnen.

hoehePID.Compute();      //ausführen der Höhenregelung
richtungsPID.Compute();  //ausführen der Richtungsregelung

 

NRF

Um eine Funkverbindung mit dem PC zu erhalten, wird ein NRF24-Funkmodul verwendet. Über diese Kommunikationsverbindung werden dann die Koordinaten von der Basisstation an den Ballon übertragen. Für Tests können damit auch manuelle Steuerungen übernommen werden. Zusätzlich können vom Ballon verschiedene Statuswerte an den PC  übertragen werden. Die Gesamtlänge der Nachricht beträgt 12 byte, die beliebig belegt werden können. Die ersten zwei bytes wurden von uns als Kontrollbytes definiert, über sie wird entschieden, ob die Nachricht tatsächlich der Gondel adressiert ist.

 

#include <Mirf.h>

void NRF() {
  
  if(Mirf.dataReady()) {
    Mirf.getData(receiving);
 
    //NRF Receive Variablen
    int receive_distanz=0;
    int receive_sollPhi=0;
    int receive_phi = 0;
    
    receive_distanz = receiving[2];    // receive high byte
    receive_distanz = receive_distanz << 8;      // shift high byte to be high 8 bits
    receive_distanz |= receiving[3];   // receive low byte as lower 8 bits
    receive_sollPhi = receiving[4];    // receive high byte
    receive_sollPhi = receive_sollPhi << 8;      // shift high byte to be high 8 bits
    receive_sollPhi |= receiving[5];   // receive low byte as lower 8 bits
    sollH = receiving[6];    //Uebernehmen der neuen Sollhoehe
    receive_phi = receiving[8];        // receive high byte
    receive_phi = receive_phi << 8;            // shift high byte to be high 8 bits
    receive_phi |= receiving[9];       // receive low byte as lower 8 bits
      
    sollPhi = receive_sollPhi;
    phiIPS = receive_phi;
  }
  
  sending[2] = IPS;
  sending[3] = istH;
  sending[4] = sollH;
  sending[5] = geschwindigkeit_r;
  sending[6] = yaw;
  sending[7] = sollPhi;

  Mirf.send(sending);
  while(Mirf.isSending()){
  }
}

 

Abwurf

Abgeworfen wird das Paket bei unserer Gondel mittels Durchbrennen eines Drahtes über einen MOS Feldeffekttransistor. Den Abwurfbefehl wird auf einem Bit in der Funkverbindung übertragen, der dann den Ausgang des Arduinos, wo der MOSFET geschaltet ist, auf HIGH setzt. Dies erfolgt in dem Moment, in dem sich der Ballon anfängt, sich von der Abwurfstelle fortzubewegen. 

#define out_Abwurf 1


 //Abwurf ausführen, wenn Wegpunkt mit Abwurf erreicht
    if(receiving[7] == 1) digitalWrite(out_Abwurf,HIGH);  //Pin für Abwurf auf High setzen um Paket abzuwerfen
    else if(receiving[7] == 50) sollH = 0;                //"deaktiviert" Hoehenregelung
    else if(receiving[7] == 0) digitalWrite(out_Abwurf,LOW);  //Pin für Abwurf auf Low setzen
 
Motoransteuerung

Diese Funktion dient als Ansteuerfunktion der drei Motoren:

 

//Motoransteuerung für alle drei Motoren
void motor(byte motor, boolean direction, byte speed) { //speed from 0 to 255
  if (motor == motor_R) {
    if (direction == 0) digitalWrite(out_R_IN,HIGH);
    else digitalWrite(out_R_IN,LOW);
    analogWrite(out_R_PWM,speed);
    }
  if (motor == motor_L) {
    if (direction == 0) digitalWrite(out_L_IN,HIGH);
    else digitalWrite(out_L_IN,LOW);
    analogWrite(out_L_PWM,speed);
  }
  if (motor == motor_H) {
    if (direction == 0) digitalWrite(out_H_IN,HIGH);
    else digitalWrite(out_H_IN,LOW);
    analogWrite(out_H_PWM,speed);
  }
}

 

Höhenmotor-Wertezuweisung:

//neue Werte für den Höhenmotor übergeben
    if(geschwindigkeitH > 0) motor(motor_H, 0, geschwindigkeitH);
    else motor(motor_H, 1, 0-geschwindigkeitH);
 

Wertezuweisungen für den rechten und linken Motor:

if (distanz>50) schub=40;
else if (distanz>30) schub=30;
else if (distanz>5) schub=20;
else schub=0;

if(geschwindigkeit_r > 0) {
motor(motor_R, 0, geschwindigkeit_r+schub);
if(geschwindigkeit_r < schub) motor(motor_L, 0, schub-geschwindigkeit_r);
else motor(motor_L, 1, geschwindigkeit_r-schub);
}
else {
if((0-geschwindigkeit_r) < schub) motor(motor_R, 0, schub+geschwindigkeit_r);
else motor(motor_R, 1, 0-geschwindigkeit_r-schub);
motor(motor_L, 0, schub-geschwindigkeit_r);
}
Anhänge:
Zugriff auf URL (https://github.com/Daedalus-TUM/PP_flying_circus)PP_flying_circus[ ]%2014-%07-%07 %1:%Jul%+02:00