Quadrocopter PID und berechnung von Pitch, Yaw und Roll.

Hey Forum.
Und zwar versuche ich gerade einen Quadrocopter zu bauen und den Code dafür zu schreiben.
Nun der Quadrocopter ist schon komplett fertig und das einzige was fehlt ist der Code.
Jetzt habe ich schon seit einer Woche verschiedene PID's und andere Berechnungen ausprobiert, jedoch gibt es dabei ein Problem.
Nämlich wenn der Quadrocopter sich ausbalancieren soll steuert er ja einen Motor, den in der sich der Quadrocopter zu neigen droht, schneller und den gegenüberliegenden langsamer. Jetzt ist es so, wenn dies passiert gleicht der Motor das kippen aus, aber zu stark und dadurch lenkt der gegenüberliegende Motor auch wieder dagegen usw., bis der ganze Quadrocopter auf dem Rücken liegt.
Also gleicht er sich nicht aus sondern macht etwas unkontrolliertes.
Was ist mein Problem ?
Danke schon mal :slight_smile:

Die Regelung übersteuert.

@Rabenauge

Und wie löse ich das ?

Hi

Bei einem PID Regler zuerst mal den P-Anteil der Regelung runter stellen.

Grüsse
Peter

@someone83
Danke für den Tipp ich probier es sofort mal aus :slight_smile:
Außerdem ich hatte schon mal einen Wert von 0.5 ausprobiert und hatte dasselbe Problem wie bei einem Wert von 1.

Was für einen PID würdest du den empfehlen ?

Gruß
Moritz

Ein PID Regler ist immer ein PID Regler du hast drei Variable die du einstellen kannst. Es wird dir keiner gute Werte nennen können weil es immer vom Problem abhängt.

Außerdem ich hatte schon mal einen Wert von 0.5 ausprobiert und hatte dasselbe Problem wie bei einem Wert von 1.

Wenn du keinen Schnellkurs Regelungstechnik machen willst, bis du über "Einstellregeln" und "Ziegler-Nichols" stolperst,
musst du mit /10 statt mit /2 rumexperimentieren anfangen. Immerhin bist du vermutlich in die richtige Richtung los :wink:

Der P Wert ist nicht umsonst ein float. 0.01 oder 100.0 können beides sinnvolle Werte für Kp sein, das hängt ganz davon ab, wie die Regelabweichung gemessen wird und was der Regler-Ausgang bewirkt.

Die einfachsten Regelungen steuern allerdings z.B. eine Heizung und keine Quadcopter.
Kann ein teures Hobby werden, wenn du es mit experimentieren hinkriegen willst :~

@michael_x

Ich hab diesen PID genommen Improving the Beginner’s PID – Introduction « Project Blog.
Wie hängt da der Wert von P ab, durch die Regelabweichung und dem Regler-Ausgang ?
Oder wie findet man das raus, außer durch ausprobieren ?

Gruß
Moritz.

Es gibt auch eine fertige PID Library:
http://playground.arduino.cc/Code/PIDLibrary

Hier ist mehr zum Regler Tuning:
http://www.rn-wissen.de/index.php/Regelungstechnik#Dimensionierung_des_Reglers

Einstellung erfolgt in der Tat empirisch und man orientiert sich dabei am Schwingverhalten und betreibt den Regler an der Grenze zur Stabilität (was nicht für alle Regelstrecken geeignet ist!!). Aber mit Zielger/Nichols und Chien/Hrones/Reswick gibt es zwei Methoden wie man da vorgeht:

Grob stellt man erst mal den P-Wert so ein, dass er schwingt und gibt dann entsprechend I und D hinzu.

Danke Serenifly die links sind super :slight_smile:
Also habe ich jetzt mal nen neuen Code geschrieben

#include <PIDCont.h>
#include <Wire.h>
#include "Kalman.h"
#include <Servo.h>

PIDCont PIDroll;

#define ROLL_PID_KP  1
#define ROLL_PID_KI  0.1
#define ROLL_PID_KD  0
#define ROLL_PID_MIN  -50.0
#define ROLL_PID_MAX  50.0

Servo motors[4];
#define MOTOR_FRONT 1
#define MOTOR_RIGHT 0
#define MOTOR_LEFT 3
#define MOTOR_REAR 2

/* IMU Data */
int16_t accX, accY, accZ;
int16_t tempRaw;
int16_t gyroX, gyroY, gyroZ;
uint32_t timer;
uint8_t i2cData[14]; // Buffer for I2C data

double accXangle, accYangle; // Angle calculate using the accelerometer
double temp; // Temperature
double gyroXangle, gyroYangle; // Angle calculate using the gyro
double kalAngleX, kalAngleY; // Calculate the angle using a Kalman filter
Kalman kalmanX; // Create the Kalman instances
Kalman kalmanY;

void setup(){
  Serial.begin(9600);
  Wire.begin();
  TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz

  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once
  while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode

  while (i2cRead(0x75, i2cData, 1));
  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
    Serial.print(F("Error reading sensor"));
    while (1);
  }

  delay(100); // Wait for sensor to stabilize

  /* Set kalman and gyro starting angle */
  while (i2cRead(0x3B, i2cData, 6));
  accX = ((i2cData[0] << 8) | i2cData[1]);
  accY = ((i2cData[2] << 8) | i2cData[3]);
  accZ = ((i2cData[4] << 8) | i2cData[5]);
  // atan2 outputs the value of -? to ? (radians) - see http://en.wikipedia.org/wiki/Atan2
  // We then convert it to 0 to 2? and then from radians to degrees
  accYangle = (atan2(accX, accZ) + PI) * RAD_TO_DEG;
  accXangle = (atan2(accY, accZ) + PI) * RAD_TO_DEG;

  kalmanX.setAngle(accXangle); // Set starting angle
  kalmanY.setAngle(accYangle);
  gyroXangle = accXangle;
  gyroYangle = accYangle;

  timer = micros();
  
  
  
  
  
    //                          Kp,        Ki,         Kd           Lval         Hval
  PIDroll.ChangeParameters(ROLL_PID_KP,ROLL_PID_KI,ROLL_PID_KD,ROLL_PID_MIN,ROLL_PID_MAX);
  
  
  motors[MOTOR_FRONT].attach(10, 15, 55);
  motors[MOTOR_RIGHT].attach(3, 15, 55);
  motors[MOTOR_LEFT].attach(11, 15, 55);
  motors[MOTOR_REAR].attach(9, 15, 55);
  setSpeed(MOTOR_FRONT, 0);
  setSpeed(MOTOR_LEFT, 0);
  setSpeed(MOTOR_RIGHT, 0);
  setSpeed(MOTOR_REAR, 0);
  delay(2000);
  
}

void loop(){
  
  while (i2cRead(0x3B, i2cData, 14));
  accX = ((i2cData[0] << 8) | i2cData[1]);
  accY = ((i2cData[2] << 8) | i2cData[3]);
  accZ = ((i2cData[4] << 8) | i2cData[5]);
  tempRaw = ((i2cData[6] << 8) | i2cData[7]);
  gyroX = ((i2cData[8] << 8) | i2cData[9]);
  gyroY = ((i2cData[10] << 8) | i2cData[11]);
  gyroZ = ((i2cData[12] << 8) | i2cData[13]);
  
  accXangle = (atan2(accY, accZ) + PI) * RAD_TO_DEG;
  accYangle = (atan2(accX, accZ) + PI) * RAD_TO_DEG;
  
  double gyroXrate = (double)gyroX / 131.0;
  double gyroYrate = -((double)gyroY / 131.0);
  
  
  kalAngleY = kalmanY.getAngle(accYangle, gyroYrate, (double)(micros() - timer) / 1000000);
  timer = micros();
  
  
  int PIDroll_val= (int)PIDroll.Compute((float)179.5-kalAngleY);
  
  
  
  int m0_val=(30+PIDroll_val);
  int m1_val=(30-PIDroll_val);
  
  setSpeed(MOTOR_FRONT, m0_val);
  setSpeed(MOTOR_REAR, m1_val);
  
  Serial.println(m0_val);
}


void setSpeed(int motor, int speed)
{
  int fakeAngle = map(speed, 0, 100, 0, 180);
  motors[motor].write(fakeAngle);
}

Doch jetzt gehen die Motoren nicht mehr. Es kommen drei Bieps und dann noch mal Biep Biep, da der Motor jetzt scharf ist und danach ist stille und es passiert nichts mehr. Weiß da jemand warum das nicht mehr geht, weil Gestern funktionirte alles noch einwandfrei :frowning:

Also es gibt ein paar Updates und zwar scheitert die richtige Einstellung für die PID-Werte bei mir total, weil egal welche Werte ich einsetze von 0.001 bis 0.1 für P treten Schwingneigungen auf, die schnell oszilieren.
Bei einem Wert von 0.09 klappt es ganz gut, aber es wird erst bei einem Wert, der 45º Neigung entspricht gegengelenkt, also viel zu spät.
Ich weiß nicht woran es liegen mag, dass es total in die Hose geht.
Habt ihr vielleicht eine Ahnung ?
Gruß Moritz.

Meiner Meinung nach wird ein reiner P-Regler immer schwingen.
Drum benutzt man den ja auch nicht alleine.
Übrigens kommen meist (was man so hört) bei P schon Werte >1 rein- würds einfach mal versuchen.
Hilfreich ist Danis Tipp: einfach mal nen paar Potis rantüdeln und die so ins Programm einbinden, dass man P und I mal direkt verstellen kann. Wenn man die grade eingestellten Werte dann noch in irgendeiner Form ausgibt (Display, serielle Konsole) hat man schnell nen Bereich gefunden, in dem es prinzipiell schonmal klappt.
Der Rest ist dann Feintuning.
Und ja: es ist knifflig.

@Rabenauge
Danke für den Tipp.
Also ich hatte schon Werte für alle 3 Regler, aber es war trotzdem schlecht :confused:
Ich werde dann mal die Potis dran machen und schauen ob es klappt und hier im Forum noch mal Bericht erstatten.

Stell I und D erstmal auf Null.
Dann stellst du P alleine so lange rauf, bis die Sache deutlich schwingt.
In der Wikipedia gibts da dann einige Varianten, wie man grob die anderen Werte errechnen kann, oder du nimmst ne Faustregel:
Wenn P übersteuert, den Wert ungefähr halbieren, dann I so lange hochstellen, bis es wieder schwingt. Dann I ein bisschen zurücknehmen und ein klein wenig D hinzufügen.
Wirkliche Werte kann ich dir da nicht geben, beim Segway bin ich derzeit ungefähr bei P=20, I=150, D= 0.2...aber mit jeder Änderung am Aufbau wird das wieder anders.
Geh nicht von aus, dass diese Werte dir passen.

Also es gibt wieder Neuigkeiten und zwar bekomme ich das mit den richtigen Werten für PID immer noch nicht hin. Also stellt sich mir die Frage kann es nicht auch am Code oder dem Gyro/Accelerometer liegen ?
Wisst ihr da vielleicht was ?

Gruß
Moritz.

Am PID-Regler kann man so einiges tunen, aber an der Hardware auch.
Hast du den Sensor geometrisch mittig verbaut?
Wenn nicht: tu das mal, die Dinger messen nämlich auch Beschleunigungen, und je weiter weg vom Zentrum er ist, umso stärker wird die- und dann auch der Output von dem Ding. Kann gut sein, muss es aber nicht.
Des weiteren kann man mit der Samplingrate des PID einiges bewirken.

Also der Sensor liegt so, dass wenn der Quadrocopter in der Waage ist 180° auf X und Y ausspuckt und er liegt natürlich auch im Geometrischen Mittelpunkt. Des weiteren wie änder ich denn die Samplingrate mit der Arduino PID Lib, so wie bei Blink without delay ?

http://playground.arduino.cc//Code/PIDLibrarySetSampleTime

Damit kann man am Verhalten so einiges ändern.
Hängt natürlich auch davon ab, wie das System an sich reagiert usw.
Auch die 0utputLimits beeinflussen die Sache, da sind also schon etliche Rädchen, an denen man drehen kann.

Leider verrätst du aber nicht, wo das Problem genau liegt-"funktioniert nicht richtig.." ist ein Fall für die Glaskugel.

Das Problem versuche ich ja zu finden weil ich es selbst nicht kenne :confused:

Dann hast du folgendes Problem:

Du kannst ein Problem nicht beschreiben, willst es aber lösen. Das klappt nicht, wenn du nicht weisst, wo du ansetzen musst. Grade beim Multicopter hat man ein ziemlich komplexes System, da wird man mit rumprobieren wohl kaum zum Ziel kommen (oder man hat sehr, sehr, sehr viel Zeit).

Wenn du Hilfe willst musst du uns schon ein paar Infos geben.