Synchronlauf einer zweiachsigen Antriebssteuerung mit PID Libary

Hallo allerseits,

ich versuche gerade zwei DC-Motoren synchron laufen zu lassen. Der Aufbau ist wie folgt. Zwei Motoren werden über einen Pololu Motor Treiber gesteuert . An den Motoren befinden sich jeweils ein Geber, die die Impulse an einen Encoder (Robogaia) übergeben und mir als Zahlenwert ausgibt(mega.XAxisGetCount()). 2000 Counts sind eine Umdrehung. Die Geber haben leider keinen Index Channel und ich richte die Motoren aus, die makiert sind, bevor ich sie starte.
Gesteuert wird über ein Delphi-Programm, mit dem ich erstmal den Motor1 starten bzw. stoppen kann.
Ich wollte mit der Arduino PID Library die Motoren regeln lassen. Und zwar dreht sich z.b. Motor 1 mit einer Geschwindigkeit von sagen wir mal 20 und Motor 2 soll jetzt versuchen synchron zu Motor 1 zu laufen.
Als Sollwert habe ich den Count-Wert von Motor1 und also Istwert habe ich den Count-Wert des Motor2. Und dann berechnet mir myPID.Compute() eine Stellgröße. Sagen wir mal, dass bei der ersten Messung der Setpoint einen Wert von 400 Counts und der Input von 340 Counts liefert und der Fehler beträgt dann 60 Counts. Dann sollte Motor2 sich bisschen schneller drehen bis der Fehler quasi Null wird. Und ist der Fehler negativ, sollte er sich langsamer drehen usw.
Das Problem ist, dass er nicht regelt, sondern nur mit voller Geschwindigkeit dreht. Ich habe auch schon mit den Parameter kp, ki und kd rumgespielt, also mit sehr kleinen Werten oder D-Anteil auf Null usw, aber es kommt immer auf das gleiche hinaus.
Limitiert habe ich mit setLimits, weil er sonst zu schnell drehen würde.
Ich habe der Übersichtlichkeit Codezeilen entfernt, die jetzt nicht zum PID gehören.

#include <MegaEncoderCounter.h>
#include "DualMC33926MotorShield.h"
#include<PID_v1.h>

DualMC33926MotorShield md;
MegaEncoderCounter mega;


// Definiere die Variablen für PID Regler
double Setpoint, Input, Output;
int speedo;  



boolean isReset = false;
PID myPID(&Input, &Output, &Setpoint, 3, 0.5, 0, P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used



void setup() {
  
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
 

  Serial.println("Dual MC33926 Motor Shield init()");
  md.init(); // Ports für Motortreiber werden initialisiert
  Serial.println("Mega Encoder Counter initialisieren");
  MegaEncoderCounter(4);
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(18, 23);  
  myPID.SetSampleTime(100);
  mega.XAxisReset();
  mega.YAxisReset();

  //  Input = mega.XAxisGetCount();
  //  Setpoint = mega.YAxisGetCount();
  speedo = 20;
}

void loop() {



  if (!isReset) {
    Input = (double)mega.YAxisGetCount();
    Setpoint = (double)mega.XAxisGetCount();
    int fehler = (int)Setpoint -Input; // Nur für Testzwecke... ansich braucht man es nicht
    myPID.Compute();
    Output = (int)Output;
    md.setM2Speed(Output);
    mega.XAxisReset();
  mega.YAxisReset();
  }
}

PIDv3_netzwerk.ino (4.33 KB)

So ganz verstehe ich Dein Problem noch nicht. Die Führungsgröße ist wohl die Geschwindigeit, mit der sich ein Motor drehen soll.

Was ist die Stellgröße, die an den Motor-Treiber ausgegeben wird? Im einfachsten Fall ist das ein PWM Signal, das vom Treiber in einen Motor-Strom oder -Spannung umgewandelt wird. So ein Regler wird für beide Motoren benötigt.

Die Count-Werte entsprechen dann der Regelgröße der Motoren (aktuelle Drehzahl), nicht der Führungsgröße (Soll-Drehzahl)!

Sollen beide Motoren synchron laufen, dann kann man beiden die gewünschte Drehzahl als Führungsgröße geben. Dann laufen sie durchschnittlich mit dieser Geschwindigkeit, kurzfristig bzw. beim Anhalten können ihre Positionen aber unterschiedlich sein.

Wenn die Positionen der beiden Motoren synchronisiert werden sollen, dann wird die Sache bei DC Motoren komplizierter. Man kann zwar einen Regler basteln, der einen Motor zu einer vorgegebenen Position laufen läßt, hat dann aber wenig Einfluß auf dessen Drehzahl bzw. auf die Zeit, nach der diese Position erreicht wird. Wenn sich die Führungsgröße (Soll-Position) ändert, dann versucht der Regler ja, diese neue Position schnellstmöglich zu erreichen, und das scheint das Verhalten zu sein, das Du beobachtet hast.

Ich vermute mal, daß für eine Nachlaufregelung anhand der Encoder-Schritte (Counts) ein I Regler ein besseres (gleichmäßigeres) Verhalten haben könnte (kp=kd=0).

Grundsätzlich hat man bei DC Motoren das Problem, daß sie zum Anlaufen eine Mindestspannung benötigen. Soll ein Motor nur in eine Richtung laufen, könnte man diesen Anteil zum Ausgang des PID Reglers hinzufügen, und nur abschalten, wenn die Regelabweichung tasächlich 0 ist. Bei Drehung in beide Richtungen müßte der Anteil je nach Vorzeichen der Abweichung hinzugefügt werden. Das wäre dann eine Kombination aus PID und Dreipunktregler. Ob sich ein ähnlicher Effekt mit dem D Anteil erreichen läßt, wäre auszuprobieren.

Für echt synchrone Verläufe, z.B. schräge Geraden mit NC-Maschinen, nimmt man besser Schrittmotoren. Die brauchen keinen Regler für gleichmäßige Drehzahl, die Schrittrate wird direkt vorgegeben.