This is an old revision of the document!


Umrechnung vom Intervall [-1,1] auf [-799,799] Die Umrechnung braucht nicht linear zu sein! Die Motoren drehen schliesslich erst ab ca. Power 500 void setFloatPower(float links, float rechts) {

// TODO: bessere Umrechnung (z.B. [0,1]->[500,799] und [-1,0]->[-799,-500])
int l = links*799;
int r = rechts*799;
robot.motors.setPowers(l,r);

}

Funktion, die den Werte zwischen -1.0 und 1.0 beschränkt z.B. ist clip(4.2)=1.0, clip(-0.42)=-0.42 und clip(-42)=-1.0 float clip(float f) {

if (f>1.0) {
  return 1.0;
} else if (f<-1.0) {
  return -1.0;
} 
return f;

}

Parameter P,I,D TODO: bessere Werte finden float pid[] = {1.0, 0.0, 0.0};

void lineFollow() {

// Diese Werte zuerst experimentell bestimmen!
int weiss = 600;  // Messwert auf dem weissen Klebeband
int schwarz = 80;  // Messwert auf dem schwarzen Klebeband

// Sollwert für die Motoren (in [-1,1]), hängt auch vom Unterprogram setFloatPower ab!
// D.h. wie schnell sollen diese drehen, wenn man genau auf der Linie fährt.
float soll = 0.5;
// Zeitpunkt letzter Messung
long lastus = micros(); // Systemzeit in Microsekunden
// Wert letzter Messung
float lastv = 0.0;
// Wahr/falsch Variable für ersten Durchgang
bool first = true;
// Summe der Abweichungen
float summe = 0.0;
// Wiederholen
while (true) {
  // Werte messen (liefert Ganzzahl in [0,1023]
  int wert = ir.measure();
  // Auf Intervall [-1,1] umrechnen, v ist damit auch die Abweichung vom Sollwert 0.0
  float v = 0.0; // TODO: hier Formel aus wert, weiss und schwarz
  float zeit = (micros()-lastus)/10000000.0;   // Zeitdifferenz in Sekunden
  lastus = micros(); // Zeit merken
  float diff = (lastv-v)/zeit;  // Änderung pro Zeit
  lastv = v;   // Messwert merken
  summe = summe + v*zeit;     // Summe der Abweichung, gewichtet mit der Zeit
  if (first) {
    diff = 0.0;  // Differenz macht beim ersten Mal keinen Sinn
  }
  float korrektur = pid[0]*v + pid[1]*summe + pid[2]*diff;
  float links=clip(soll+korrektur);
  float rechts=clip(soll-korrektur);
  setFloatPower(links, rechts);
  if (robot.buttons.get()!=0) { // Button gedrückt (nicht Null)?
    break; // Wiederholung abbrechen
  }
  first = false;  // Ist nicht mehr das erste Mal
}
robot.motors.setPowers(0,0); // Motoren Power 0 (drehen sich aber noch ca. 5 Ticks weiter!)
robot.buttons.waitClear();  // Warten bis Dfingerabdäröschti

}

PID-Konstanten über das Menü anpassen. Achtung, die Konstanten werden bei einem Reset gelöscht. Gute Konstanten im Code oben eintragen! void adjust_pid() {

// Titel beim Anpassen
char *msg[] = {"Set proportional", "Set integral", "Set differential"};
while (true) {
  int choice = robot.menu.choice("1 setP", "2 setI", "3 setD", "4 abort");
  if (choice==4) {
    break;
  }
  // Anpassen mit Menufunktion, choice ist 1, 2 oder 3. Anpassungsschritt proportional zur Grösse des Parameters
  pid[choice-1] = robot.menu.adjustFloat(msg[choice-1], pid[choice-1], abs(pid[choice-1])/20.0+0.001);
}

}

  • lehrkraefte/blc/robotics/pid.1499325824.txt.gz
  • Last modified: 2017/07/06 09:23
  • by Simon Knaus