Regler programmieren

hi

ich möchte gerne ein Regler programmieren habe aber keine erfahrung.

Problem: ich habe ein Modellauto mit 2 DC-Motoren die von einem Dual MC33926 Motor Driver Carrier angesteuert werden für die geschwindigkeitsüberwachung benutze ich eine encoderscheibe mit einer lichtschranke.

Das Auto driftet leicht in einer richtung obwohl es eigentlich geradeaus fahren soll. da war meine idee ne regelung zu programmieren.

Meine frage wie ist die vorgehensweise.

welchen regler muss ich benutzen muss man irgendwas ausrechnen oder messen habe im forum gesehen dass es ne fertige library gibt z.b. für den pid-regler ist es schwierig so ein pid regler selber zu programmieren das wäre mir lieber damit ich dieses thema besser verstehe

ich hatte regelungstechnik als vorlesung aber habe vieles schon vergessen

danke

https://www.pololu.com/product/1213

ist es schwierig so ein pid regler selber zu programmieren

Nein. Man muss nur den P, I und D Anteil ausrechnen. Wenn du dir die PID Library anschaust, dann siehst du dass der Aufwand dafür minimal ist.

Erst wird die Regelabweichung berechnet. Also einfach Sollwert Minus Istwert

double error = *mySetpoint - input;

Für den Integral-Teil addiert man einfach die Regelabweichung (mal den Regelfaktor Ki) immer wieder auf

ITerm+= (ki * error);

Damit sich das nicht aufschaukelt falls der Fehler nicht ausgeregelt wird gibt es einen Anti-Windup der der Wert auf ein Maximum oder Minimum begrenzt

if(ITerm > outMax) ITerm= outMax;
else if(ITerm < outMin) ITerm= outMin;

Der Differential-Anteil ist die Differenz zwischen den letzten beiden Ist-Werten

double dInput = input - lastInput;

Der Stellwert ist dann die Summe aus dem Proportional-Wert (welcher einfach Kp * Regelabweichung ist), dem Integral-Wert und dem negativen Differential-Wert

double output = kp * error + ITerm - kd * dInput;

Der Code außen herum - z.B. für die Sample-Zeit - ist deutlich mehr. Dazu das ganze Klassen-Gerüst und die Übernahme der Parameter. Darauf könnte man verzichten und statt dessen eine einzige Funktion nehmen der man die Werte übergibt. Da bietet sich ein struct für jeden Regler an dass man dann einfach übergibt (natürlich per Referenz!). Sowas vielleicht:

struct controlData
{
   double setpoint;
   double input;
   double output;
 
   double iTerm;
   double lastInput;
   unsigned long previousMillis;    //für die Sample-Zeit
};

void compute(controlData& data);  //der Prototyp ist hier nötig, da ihn die IDE über das struct schreibt wenn man sie das automatisch machen lässt
void compute(controlData& data)
{
   ...
}

So hat man die Variablen für jeden Regler zusammengefasst und kann auf einmal eine Referenz darauf übergeben. Dann braucht man noch eine Zeit-Steuerung so dass das z.B. nur alle 100ms berechnet wird. Das geht einfach nach dem BlinkWithoutDelay Prinzip

Für den Integral-Teil addiert man einfach die Regelabweichung

... mit dem Berechnungsintervall multipliziert. Wenn man mit unterschiedlichen Rechenzyklen experimentiert, müssen die zeitabhängigen Parameter ki / kd automatisch angepasst werden.

Wenn du dir die PID Library anschaust, dann siehst du dass der Aufwand dafür minimal ist.

;)

ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;

Bei dieser Geschichte würde ich auf den D- Anteil verzichten. Hier geht es ja auch nicht um hoch präzises nachregeln sondern um Ausgleich der Differenz, da reicht es in meinen Augen den absolute Differenz über P und der verbleibende Fehler aufgrund der zu kleinen Soll Ist abweichung per I-Anteil aufzufangen. Das denke ich ist für einen Anfänger einfacher. Man kann aber nach wievor die PID-Lib nutzten aber einfach für d 0 schreiben. Ein bisschen Try&Error dürfte nötig sein das ganze zu stabilisiern. Mach am besten zwei Spindeltrimmer (10-Gang Potis) dran die du aus liest und dann damit die P und I Anteile einstellst. Dann brauchst du nicht bei jedem ändern neu zu übertragen. Wenn die Werte gefunden sind kann man sie ja fest ins Programm einbinden. Gruß DerDani