-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Problem mit PID-Regler

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2007
    Beiträge
    7

    Problem mit PID-Regler

    Anzeige

    Hi,

    Ich habe für ein Linienfolger Programm einen PID Regler verwendet (von http://www.henkessoft.de/Roboter/ASURO.htm), dieser Funktionierte auch wunderbar und war viel schneller und Präziser als ein einfacher P-Regler.

    Code:
    /*******************************************************************************
    *
    * Description: Asuro Linienverfolgung mit PID-Regler
    * Autor: Waste   26.8.05,  Verändert durch: ehenkes 26.05.2007
    *
    *****************************************************************************/
    
    #include "asuro.h"
    #include <stdlib.h>
    
    #define SPEED        80
    #define SPEEDMAX    200
    #define SPEEDMIN     30
    #define IMAX      16000
    #define IMAXALARM 15000
    
    unsigned char speed, j;
    int speedLeft,speedRight;
    unsigned int lineData[2];
    int x, xalt, kp, kd, ki, yp, yd, yi, drest=0, y, y2, isum=0, ADOffset;
    
    void FollowLine (void)
    {
       unsigned char leftDir = FWD, rightDir = FWD;
      
       LineData(lineData);
       x = (lineData[LEFT] - lineData[RIGHT]) - ADOffset;
      
       yp = x*kp;                          // P-Anteil
      
       isum += x;
       if (isum >  IMAX) isum =  IMAX;  
       if (isum < -IMAX) isum = -IMAX;
       yi = isum / 625 * ki;               //I-Anteil
      
       yd = (x - xalt) * kd;               // D-Anteil 
       yd += drest;                       
       if (yd > 255)
       {
           drest = yd - 255;   
       }
       else if (yd < -255)
       {
           drest = yd + 255;
       }
       else
       {
           drest = 0;
       }
      
       if (isum > IMAXALARM)        BackLED(OFF,ON);  
       else if (isum < -IMAXALARM)  BackLED(ON,OFF);
       else BackLED(OFF,OFF);
      
       y = yp + yi + yd;                 // PID
       y2 = y / 2;                        
       xalt = x;                        
      
       speedLeft = speedRight = speed;
       MotorDir(FWD,FWD);
      
       if ( y > 0)
       {                    
          StatusLED(GREEN);
          speedLeft = speed + y2;        
          if (speedLeft > SPEEDMAX)
          {
             speedLeft = SPEEDMAX;       
             y2 = speedLeft - speed;     
          }
          y = y - y2;
          speedRight = speed - y;        
          if (speedRight < SPEEDMIN)
          {
             speedRight = SPEEDMIN;
          }
       }
      
       if ( y < 0)
       {                    
          StatusLED(RED);
          speedRight = speed - y2;       
          if (speedRight > SPEEDMAX)
          {
             speedRight = SPEEDMAX;      
             y2 = speed - speedRight;    
          }
          y = y - y2;
          speedLeft = speed + y;         
          if (speedLeft < SPEEDMIN)
          {
             speedLeft = SPEEDMIN;
          }
       }
       leftDir = rightDir = FWD;
       if (speedLeft  < SPEEDMIN + 5)  leftDir  = BREAK;
       if (speedRight < SPEEDMIN + 5)  rightDir = BREAK;
       MotorDir(leftDir,rightDir);
       MotorSpeed(abs(speedLeft),abs(speedRight));
    }
    
    int main(void)
    {
       Init();
       FrontLED(ON);
       for (j = 0; j < 255; j++) LineData(lineData);
       LineData(lineData);
       ADOffset = lineData[LEFT] - lineData[RIGHT]; // Helligkeitsunterschied links und rechts    
      
       MotorDir(FWD,FWD);
       StatusLED(GREEN);
    
       speed = SPEED;
       speedLeft  = speed;
       speedRight = speed; 
      
       kp = 10; ki = 4; kd = 70;      // Regler Parameter kd enthält bereits Division durch dt
       /*   10(!)    4(!)    70(!)   */ /*<=== gute Ausgangswerte*/  
      
       while(1)
       {
          FollowLine();
       }
       return 0;
    }

    Um aber flexibler zu sein habe ich meinen Asuro ein wenig umgebaut:

    ----------------------------------------------
    |_|''''''''''''''''''''''''''''''|_|'''''''''''''' '''''''''''''''|_|
    (schematische Ansicht von vorne; linker Fototransistor, FrontLED, rechter Fototransistor)

    Den Code habe ich nun folgendermassen angepasst:

    Code:
    #include "asuro.h"
    #include <stdlib.h>
    
    #define SPEED       240
    #define SPEEDMAX    255
    #define SPEEDMIN     80
    #define IMAX      16000
    #define IMAXALARM 15000
    
    unsigned char speed, j;
    int speedLeft,speedRight;
    unsigned int lineData[2];
    int x, xalt, kp, kd, ki, yp, yd, yi, drest=0, y, y2, isum=0, ADOffset;
    
    void FollowLine (void)
    {
       unsigned char leftDir = FWD, rightDir = FWD;
      
       LineData(lineData);
       x = (lineData[LEFT] - lineData[RIGHT]) - ADOffset;
      
       yp = x*kp;                          // P-Anteil
      
       isum += x;
       if (isum >  IMAX) isum =  IMAX;  
       if (isum < -IMAX) isum = -IMAX;
       yi = isum / 625 * ki;               //I-Anteil
      
       yd = (x - xalt) * kd;               // D-Anteil 
       yd += drest;                       
       if (yd > 255)
       {
           drest = yd - 255;   
       }
       else if (yd < -255)
       {
           drest = yd + 255;
       }
       else
       {
           drest = 0;
       }
      
       if (isum > IMAXALARM)        BackLED(OFF,ON);  
       else if (isum < -IMAXALARM)  BackLED(ON,OFF);
       else BackLED(OFF,OFF);
      
       y = yp + yi + yd;			// PID
       y2 = y / 2;                        
       xalt = x;                        
      
       speedLeft = speedRight = speed;
       MotorDir(RWD,RWD);
      
       if ( y < 0)
       {                    
          StatusLED(GREEN);
          speedLeft = speed + y2;        
          if (speedLeft > SPEEDMAX)
          {
             speedLeft = SPEEDMAX;       
             y2 = speedLeft - speed;     
          }
          y = y - y2;
          if (speedRight < SPEEDMIN)
          {
             speedRight = SPEEDMIN;
          }
       }
      
       if ( y > 0)
       {                    
          StatusLED(RED);
          speedRight = speed - y2;       
          if (speedRight > SPEEDMAX)
          {
             speedRight = SPEEDMAX;      
             y2 = speed - speedRight;    
          }
          y = y - y2;
          speedLeft = speed + y;         
          if (speedLeft < SPEEDMIN)
          {
             speedLeft = SPEEDMIN;
          }
       }
       leftDir = rightDir = RWD;
       if (speedLeft  < SPEEDMIN + 5)  leftDir  = BREAK;
       if (speedRight < SPEEDMIN + 5)  rightDir = BREAK;
       MotorDir(leftDir,rightDir);
       MotorSpeed(abs(speedLeft),abs(speedRight));
    }
    
    int main(void)
    {
       Init();
       FrontLED(ON);
       for (j = 0; j < 255; j++) 
       {
    	   LineData(lineData);
       }
       LineData(lineData);
       ADOffset = lineData[LEFT] - lineData[RIGHT]; // Helligkeitsunterschied links und rechts    
      
       MotorDir(RWD,RWD);
       StatusLED(GREEN);
    
       speed = SPEED;
       speedLeft  = speed;
       speedRight = speed; 
      
       kp = 10; ki = 4; kd = 70;      // Regler Parameter kd enthält bereits Division durch dt
       
      
       while(1)
       {
          FollowLine();
       }
       return 0;
    }
    Als wichtigste Änderung habe ich die Umkehrung der > und < Operatoren betrachtet.

    Nun fährt der Asuro aber nur noch sehr langsam der Linie nach...
    Kann mir jemand einen Tipp geben, wie ich die Geschwindigkeit wieder steigern kann?

    Gruss,
    Matt

    Edit:
    Bilder hinzugefügt
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken asuro-schraeg.jpg   asuro-unten.jpg   asuro-seite.jpg   asuro-front.jpg  

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo mattsarz
    willkommen im Forum.

    Sag mal wie breit ist denn deine Linie, auf der du fährst?
    Bzw: Was hat dich bewogen die Sensoren so weit auseinander zu legen?

    Zu deinem Umbau im Programm (< > getauscht):
    Interessant. Ich vermute, dass du auf einer weißen Linie auf sonst schwarzem Grund fährst. Aber warum der Asuro deshalb nun langsamer sein soll, ist mir dann auch ein Rätzel.
    Sind sonst noch Änderungen im Programm? Ich finde nur die 2 Stellen:
    "if ( y > 0)" in FollowLine().
    Lieber Asuro programieren als arbeiten gehen.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2007
    Beiträge
    7
    Hi Sternthaler,

    danke für deine Antwort!
    Ich benütze schwarzes Tesaband für die Linie (3,5 cm breit). Das Tesaband passt ziemlich genau zwischen die Sensoren. Somit fährt der Asuro geradeaus, wenn er weiss, weiss "sieht".
    Diesen Umbau habe ich vollzogen um die linienfolge allgemein gültiger zu machen... Denn bei einer 90° kurve merkt der Asuro nun selbst, in welche Richtung er fahren soll.

    Die grösser als zeichen sind bis jetzt wirklich die einzigen Veränderungen im Programm... ich hoffe du kannst mir evt. sagen, was ich sonst noch ändern müsste.

    MfG,
    Matt

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    Nun fährt der Asuro aber nur noch sehr langsam der Linie nach...
    Kann mir jemand einen Tipp geben, wie ich die Geschwindigkeit wieder steigern kann?
    Ich kenne das Programm nicht und verstehe auch kein C.


    Bei einem PID Regler würde ich aber mal vermuten, dass du bei einem Umbau auch die Regelung oder mindestens die Faktoren kp, kd und ki auf deinen Umbau anpassen musst.

    Durch deine sehr breite Linie und die anders angeordneten Sensoren dürfte deine Regelung es mit anderen Abweichungen vom Sollwert zu tun bekommen als im Originalaufbau.
    Da die Geschwindigkeit mit der auf eine Abweichung reagiert wird und die Geschwindigkeit mit der dein Roboter vorwärts kommt voneinander abhängen dürften sich falsche Parameter der Regelung auch auf die Fahrtgeschwindigkeit auswirken.

  5. #5
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Jena
    Alter
    31
    Beiträge
    3.912
    .... warum sollte der asuro bei schmalen linien nicht wissen in welche richtung er fahren muss? wenn unter einem sensor schwarz wird, muss er in die richtung drehen. das ist bei schmalen linien genauso wie bei hellen...
    kleinschreibung ist cool!

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo mattsarz
    mmmhhh, im Moment kann ich mit der Farbe der Linie nicht so richtig folgen. (Ist nun mein Regler kaputt?)
    Das letzte Bild von dir hat bei meinem Monitor fast genau ein 1:1-Verhältnis mit dem Asuro in meiner Hand. Da sind dann aber die Liniensensoren auf dem Bild ca. 7 cm entfernt. Dein Tesaband hat 3,5 cm.
    Mach doch mal bitte ein Bild mit dem Asuro auf der Linie.

    Um aber mal eine Gegenprobe, so auf die schnelle, zu machen.
    Dreh doch mal die < > wieder im Programm um. Fährt der Asuro dann wieder schneller? Und vor allem: Bleibt er auf der Linie?
    Sonst bin ich erst einmal sprachlos.

    Oder ist die Geschwindigkeitsänderung erst mit dem Hardwareumbau gekommen? Dann hat recycle ja schon einen Hinweis auf die PID-Reglerparameter gegeben.

    Erst einmal Gute Nacht.
    Lieber Asuro programieren als arbeiten gehen.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2007
    Beiträge
    7
    Das mit den Reglerwerten habe ich schon zur genüge ausgetestet.. Ich frage mich nur, ob ich nicht etwas vergessen habe. Ich habe schon wie ein verrückter gesucht, bin aber noch nicht fündig geworden.
    Anbei liefere ich euch noch ein paar bilder mit, mit denen ihr hoffentlich meine situation nachvollziehen könnt.

    Durch meinen Umbau ist der Spielraum der breite des Tesafilms grösser, da sich die Fototransistoren nun nicht mehr auf, sondern neben dem Klebeband befinden..
    Die von mir beschriebene Situation (die 90 grad kurve), seht ihr auf meinen Bildern; dieses Problem ist durch den Umbau gelöst worden.
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken mini-dsc04368.jpg   mini-dsc04367.jpg  

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    Ich würde als erstes mal ausprobieren, ob es überhaupt an der Regelung liegt. Erreicht der Asuro denn noch die volle Geschwindigkeit, wenn du ihn ohne Regeung einfach geradaus fahren lässt?

    Wenn ja, würde ich das Programm mal so umschreiben, dass die wichtigen Werte der Regelung aufs Terminal ausgegeben werden, während du den Asuro ein bischen über der Linie bewegst.
    Dann müsstest du an den Ausgabewerten wenigstens ungefähr sehen können, wo es klemmt.

  9. #9
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Jena
    Alter
    31
    Beiträge
    3.912
    hmm aber ich verstehe das problem immer noch nicht... was ist der unterschied zur schmalen linie? bei der sieht der asuro doch genauso ob er links oder rechts muss...
    kleinschreibung ist cool!

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2007
    Beiträge
    7
    Ohne Regelung erreicht er volle Geschwindigkeit...

    @damaltor: Ich bin Praktikant an einer Hochschule, hier bin ich im OK der RobOlympics (www.robolympics.ch). Da die Regeln für die Wettbewerbe genau bestimmt sind, ist auch die breite des Klebbands beim Linienfolger vorgegeben.
    Ich teste den ASURO nun als Preis.. Daher sollte er auch Teilnahmefähig sein, da die Gewinner nächstes Jahr mit ihm antreten könnten.

    So viel erst mal dazu

    MfG,
    Matt

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •