- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Motor Positionsregelung mit Encoder

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    08.03.2010
    Beiträge
    66

    Motor Positionsregelung mit Encoder

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    ich habe einen Modellbaumotor mit Regler, an dem ein Encoder (360 incremente) angeschlossen ist.
    Das lesen der incremente klappt soweit, ich erfasse von beiden Spuren je steigende und fallende Flanke, so das ich je Umdrehung auf 1440 impulse komme.
    Die werden entweder positiv oder negativ erfasst.

    Ich habe eine einfache Routine erstellt, welche es ermöglicht eine bestimmte Strecke abzufahren. z.B. 400mm.
    Wenn das erreicht ist, stoppt der Motor. Soweit klappt das.

    Jetzt hätte ich gern, das wenn das Fahrzeug auf einer schrägen steht, oder von mir verschoben wird, die letzte Position versucht zu halten.

    1. Geht das überhaupt mit einem gewöhnlichen Rc-Regler, oder ist der schon zu träge?
    2. Ich bekomme keinen vernünftigen Code hin der das sauber schafft. Ich habe immer das Problem das sich der Regelkreis "aufschaukelt".
    Das ist nur verständlich, da das Fahrzeug zum Reaktionszeitpunkt schon über das Ziel hinaus geschossen ist und dann immer heftiger gegensteuern muss um zum gewünschten Punkt zurückzukommen.

    Wer kann mir da ein bisschen helfen?

    Hier mal mein Haltemodus:
    Ich habe es versucht halbwegs gut zu kommentieren.




    Code:
    if (holdmodus){
      full_cycl=15000;  //Zykluszeit verringern, um schneller zu reagieren
    if (!proc){    //Wenn gerade KEIN PWM-Signal generiert wird
      
    //Reaktion wenn das Fahrzeug sich außerhalb der Sollposition befindet
    if (negativeDir){   //Wenn die Zielposition negativ ist
      if (position_k>holdpos-50)  switch_len--; 
      if (position_k<holdpos+50)  switch_len++;
      }
      else  //Wenn die Zielposition positiv istist
      {
      if (position_k>holdpos-50)  switch_len++; 
      if (position_k<holdpos+50)  switch_len--;
      }
    
     //Begrenzung der maximalen Geschwindigkeit beim regeln
    //1500 ist neutral=kein Gas
     if (switch_len>1550) switch_len=1550;
     if (switch_len<1450) switch_len=1450;
    
      //Reaktion wenn das Fahrzeug sich innerhalb eines zulässigen Fensters um die Sollposition herum befindet
      if ((position_k>holdpos-50)  &&  (position_k<holdpos+50)) {   //wenn mitte erreicht
    
         //WEnn ich in diesem Bereich das gas ganz wegnehme (switch_len=MV) , schaukelt er sich nicht auf, 
         //aber auf einer Schrägen fährt er dann immer ein stück runter und dann wieder hoch :-(
    
         if (ticks_real==0){ //wenn eine bewegung stattfindet, dann gas langsam wegnehmen  
                                  //-> ticks_real wird bei feststellen einer bewegung auf 0 gesetzt, sonst zählt es hoch 
                                  //(Das hat nix mit den geberincrementen zu tun)
         if (switch_len>MV)  switch_len= switch_len-((abs(switch_len)-abs(MV))/2);  
         if (switch_len<MV)  switch_len= switch_len+((abs(switch_len)-abs(MV))/2); 
         }
    
      }
    }
    }
     
        
    }

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    Hast Du schon mal was von PID-Reglern gehört? Die sind relativ einfach in einem Controller umzusetzen.
    Das hilft allerdings bei Deinem Schrägenproblem nur bedingt , weil:

    "Ohne Abweichung keine Regelung!"

    Vielleicht wäre für das Schrägenproblem denkbar, über einen 3-Ach-Accelerometer die Schräglage zu messen und damit einen zweiten PID-Regler zuzuschalten (Die Dinger kann man kaskadieren, also das Ergebnis mehrerer Regler je nach Anwendungsfall miteinander multiplizieren oder addieren.)

    Mal ein Beispiel für eine PID-Implementierung

    PID.h
    Code:
    #ifndef INCL_PID_H
    	#define INCL_PID_H
    
        #include <avr/io.h> 
        #include <stdint.h>
    
        #define PID_SIZEOFFSET 19 // Offset in uint8_t array for data start
    
        typedef struct
        {
            uint8_t Depth;  //0
            double KP;      //1
            double KI;      //5
            double KD;      //9
            double Sum;     //13
            uint8_t Index;  //17
            double Buffer[];//18
        }PID_t;
    
    
        extern void InitPIDStruct(uint8_t arr[], uint16_t size);
        extern void PIDCalculate(PID_t* pid, double diff, double* result);
    
    
    #endif
    So ein PID-Regler benötigt drei Konstanten, die an das System anzupassen sind: KP(roportional), KI(ntegral), und KD(ifferential).
    Proportional: Je größer die aktuelle Abweichung, desto größer die Gegensteuerung
    Integral: Je "stabiler" (länger anhaltend) die Abweichung, desto größer die Gegensteuerung
    Differential: Je nach Trend (Änderung der Abweichung) ändert sich die Gegensteuerung.



    PID.c

    Code:
    #include <stdint.h>
    #include <math.h>
    #include <string.h>
    #include "PID.h"
    
    
    
    //Init array: iRead/iWrite = 0, data elements = 0, Buffer length = array length -4
    void InitPIDStruct(uint8_t arr[], uint16_t size)
    {
        memset( arr, 0, size);
        arr[0] = (size-PID_SIZEOFFSET) / sizeof(double);
    }
    
    double p, i, d;
    
    void PIDCalculate(PID_t* pid, double diff, double* result)
    {
        //Proportional
        p = diff * pid->KP;
    
        //Differential
        double previous = pid->Buffer[pid->Index];
        d = (diff - previous) * pid->KD;
    
        //Integral
        pid->Index = (pid->Index + 1) % pid->Depth; //Step up index
        double oldVal = pid->Buffer[pid->Index];
        pid->Buffer[pid->Index] = diff;
        pid->Sum -= oldVal;
        pid->Sum += diff;
        i = (pid->Sum/ pid->Depth) * pid->KI;
    
        *result = -1.0 * (p + i + d);
    }
    Um den integralen Anteil zu berechnen, verwende ich hier ein Array, dass die letzten 16 Werte hält. Allerdings berechne ich nicht die komplette Summe in jedem Durchlauf neu, sondern ziehe immer nur das älteste Element ab und füge das neu hinzugekommene Element hinzu.



    Initialisierungsbeispiel:
    Code:
    static uint8_t arrDistance[16 * sizeof(double) + PID_SIZEOFFSET];
    static PID_t* PIDDistance;
    
    void Drive_Init()
    {
        InitPIDStruct(arrDistance, sizeof(arrDistance));
        PIDDistance = (PID_t*) arrDistance;
        
        PIDDistance->KP = 0.6;
        PIDDistance->KI = 0.2;
        PIDDistance->KD = 0.4;
    }
    Vielleicht wird's hier klar, warum ich zuerst ein Array anlege und anschließend auf den Strukturtyp caste. Ich kann dadurch die Größe des Integrationspuffers in der Arraydefinition anpassen (in InitPIDStruct wird entsprechend dann das "Depth" errechnet).


    Ein Durchlauf in etwa so:
    Code:
        //calculate Distance regulation value
        static double dregDistance;
        PIDCalculate(PIDDistance, dDistance, &dregDistance);
       
        //!!! Wenn Neutral = 15000, dann hier aufaddieren
        int16_t newPWM = 15000 + (int16_t) dRegDistance;
    Eingang ist die Regeldifferenz dDistance, also Sollwert-Istwert
    Ausgang ist der Regelwert, hier als Beispiel mal die PWM.

    Die drei Konstanten kP, kI und kD einzustellen, ist allerdings eine Kunst für sich. Es gibt sowohl mathematische Ansätze als auch den reinen Probieralgorithmus, in dem zuerst kP möglichst optimal eingestellt, danach kI dazugenommen und kD als optimierendes i-Tüpfelchen zum Schluss ausgetestet wird.
    Geändert von Holomino (08.10.2016 um 10:23 Uhr)

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    In der Industrie haben Motoren, die eine Position unter Last halten sollen, üblicherweise 3 Regler.
    Drehzahl-Reglung, Positions-Reglung, Strom-Reglung.
    Wobei dort neben Drehgebern auch Resolver zum Einsatz kommen.
    Durch Abgleich des Reglers mit dem Resolver wird die Winkelstellung unter unterschiedlichsten Lasten gehalten.
    Da der Regler bei dem CPC Encoder mindestens 2 Flankenwechsel (einen je Kanal) braucht, um die Drehrichtung zu erkennen, wird die Positionsreglung minimal um 4 Impulse schwanken.
    Ohne PID Regler ist diese Regelgüte aber nicht erreichbar.
    Geändert von i_make_it (08.10.2016 um 12:41 Uhr)

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    ...wobei Du bei Batteriebetrieb gleich 'nen vierten Regler zum Ausgleich der Versorgungsspannungsänderung einplanen kannst...

    ...sofern die Motorspannung nicht über 'nen Stabi vorher stabilisiert wird...

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    08.03.2010
    Beiträge
    66
    Ich habe mit der PID-Regelung nun ein wenig herumgespielt. Vielleicht erwarte ich auch zuviel davon.
    Im Grunde würde es mir ja schon reichen wenn das Fahrzeug auf einer geraden Strecke von A nach B fährt.
    Ohne in diesen Regelkreis einzugreifen bekomme ich es nicht hin.
    Damit meine ich: Ich muss mindestens die Regelung stoppen wenn das Ziel erreicht ist.
    (Auf einer schiefen Ebene würde er dann gnadenlos herunter fahren)

    Nur mal angenommen ich setze die Werte für KI und KD auf 0 und fange nun an KP hochzusetzen.
    In meinem Fall fährt das Fahrzeug mit KP=0 quasi gar nicht, sondern zuckelt nur auf der Stelle.
    Setze ich KP so hoch das das Fahrzeug fährt, schwingt er am Zielpunkt hin und her.
    Es gibt keine Einstellung wo er nicht schwingt.
    Ich weiß nicht ob das so sein soll???

    Gruß, Andreas

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Zitat Zitat von MechMac Beitrag anzeigen
    ich habe einen Modellbaumotor mit Regler, an dem ein Encoder (360 incremente) angeschlossen ist.
    Kann es sein, das Du versuchst den Regler zu Regeln und der daraus mit seinen Reglersettings wiederum was macht das er dem Motor gibt?
    Oder ist der Quellcode der von eben diesem Regler?

    Den PID Regelung an sich funktioniert, wie CNC Maschinen, Industrieroboter, Aufzüge, Eisenbahn, Segways etc. beweisen.
    Also muß entweder die Implementierung fehlerhaft sein oder im Regelkreis befinden sich Störgrößen wie eben ein zweiter Regler der sein eigenes Ding macht.

    Eventuell wären Daten zu Motor, Regler, Aufbau des Ganzen, hilfreich.
    Geändert von i_make_it (16.10.2016 um 20:13 Uhr)

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    08.03.2010
    Beiträge
    66
    Der Motor ist ein Brushless-Motor mit Sensoren. Er wird von einem gewöhnlichen Modellbau-Regler gesteuert.
    Dieser Modellbau-Regler hat jedoch kein "Eigenleben". Er erwartet eine PWM im Bereich von etwa 1 - 2 Millisekunden.
    Diese sagt ihm wie er den Motor ansteuern soll. 1,0=Rückwärts 1,5=Neutral 2,0=Vorwärts

    Motor: LRP-Eraser
    Regler: AI-Pro
    Der Encoder sitzt hinter einem Planetengetriebe, da der Motor zu schnell dreht. (Ich weiß das der Encoder eigentlich auf den Motor gehört)

    Das eine PID Regelung funktioniert glaube ich. Vielmehr denke ich das der Fehler bei meinem Aufbau bzw. der Umsetzung liegt.
    Der Quelltext oben findet aktuell keine Verwendung mehr, da ich ja jetzt mit der PID-Regelung arbeite.

    Vom Aufbau her ist es ein ehemals Allrad-Fahrzeug, welches auf Frontantrieb reduziert wurde.
    Am zweiten Ausgang des Planetengetriebes sitzt jetzt der Encoder (da wo vorher die zweite Kardanwelle für das Heck dran war)
    Die Einheit, welche den encoder ließt und die PWM für den Modellbau-Regler erzeugt ist ein Arduino Nano, dieser wird von einem Arduino Mega über I2C mit den Infos (z.B.Fahrbefehl, Halt, KP,KD und KI versorgt). Der Mega wiederum erhält via XBee seine Befehle von meinem Computer.
    Somit kann ich sehr bequem mit den Werten spielen.

    Gruß, Andreas

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    55
    Beiträge
    2.814
    Wenn der Regler der "A.I. BRUSHLESS (PRO) REVERSE" ist, hat der eine eigene Regelung. Alleine schon wegen der EMK Bremse wird er sich nicht passiv verhalten.
    Laut der Beschreibung die ich eben gelesen habe, kann man die Bremse wohl auch nicht abschalten.
    Willst Du den Motor wirklich selbst regeln, wirst Du in dem Fall wohl drei Halbbrücken brauchen und selbst einen Motortreiber bauen müssen oder anstelle einem Regler nach einem reinen Motortreiber für BLDC suchen müssen.

  9. #9
    Unregistriert
    Gast
    wenn es allerdings tatsächlich über normale H-Brücken geregelte Motoren sind (L293 o. L298 o.ä.) , wäre es vielleicht auch ein Tipp, die PID_v1 lib der Arduinos zu verwenden. Es gibt dafür sogar ein eigene Autotuning-Zusatzlib.
    http://playground.arduino.cc/Code/PIDLibrary
    http://playground.arduino.cc/Code/PIDLibaryBasicExample

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Hallo Andreas.
    .. Wer kann mir da ein bisschen helfen? ..
    Vor längerer Zeit hatte ich mich in die Regelungstechnik (siehe hier) von Gleichstrommotoren (klicken) zur Geschwindigkeitsregelung eingearbeitet. Daraus wurde dann die Geschwindigkeitsregelung meiner Roboterantriebe. Die Vorgehensweise ist hier beschrieben und zeigt (m)ein Codebeispiel. Die Funktion ist ziemlich gut. Es ist ein sauberer Geradlauf bzw. Gleichlauf der beiden kleinen Motörchen in meinem MiniD0 möglich. Der saubere Gleichlauf erlaubt z.B. diese sauber-platztreue Pirouette im Video.

    Die Sprungantwort zur Dimensionierung der Reglerkennwerte ist sehr praktisch. Hatte ich später nicht am freilaufenden Motor bestimmt sondern im fertigen Target. Ne ähnliche Regelung hatte ich auch bei meinem Archie verwendet - die Dimensionierung der Reglerkennwerte erfolgte nach einiger Erfahrung mit früheren Auslegungen eher über den Daumen gepeilt.

    Später hatte ich eine Stellungsregelung in ähnlicher Weise programmiert für nen "Servomotor" eigener Zusammenstellung am Handgelenk meines Archie. Dort ist, wegen der relativ einfachen Aufgabenstellung, nur ein PD-Regler (Software) eingebaut. Der I-Anteil konnte wegen geringer Lastvariation weggelassen werden. Die Vorgehensweise war wie oben beschrieben, der Code lehnte sich ebenfalls an diese erste Variante an.

    Der Motor ist ein Brushless-Motor mit Sensoren .. Modellbau-Regler hat jedoch kein "Eigenleben" ..
    Ich hatte noch nie Brushless´ in der Hand :-/ . Meine Regelungen laufen üblicherweise über käufliche Motortreiber-ICs/Motor-Vollbrücken wie L293D oder VNH2SP30.
    Ciao sagt der JoeamBerg

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Antworten: 1
    Letzter Beitrag: 21.03.2012, 18:43
  2. Motor Positionsregelung
    Von Che Guevara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 11.10.2011, 12:13
  3. Encoder für BL Motor
    Von kristof81 im Forum Motoren
    Antworten: 10
    Letzter Beitrag: 05.06.2010, 13:10
  4. Motor mit Encoder
    Von Da_Vinci13 im Forum Motoren
    Antworten: 3
    Letzter Beitrag: 19.01.2009, 19:55
  5. Antworten: 2
    Letzter Beitrag: 23.07.2007, 08:44

Berechtigungen

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

Solar Speicher und Akkus Tests