Drehzahlermittlung in sunray

No, not realy. The PID is an algorithm to minimize the error between set and current value. Without PID you didn't have any errorcorrection for the speed. Normaly a good PID needs a P-Factor for fast errorcorrection. But due to the low frequency of 50ms and the high dynamic of the drive-motors I didn't find good values for P and D.
 
So, motor control looks a bit more accurate now with correct PID implementation, Im using a factor o 10 for the integral, now RPM changes have to be handled a bit more smoothly in Stanley otherwise you get a lot of harsh movement at rotations that were hidden by the "incorrect" PID implementation.

Yeah, my motors start vibrating as soon as I introduce some P, might have to look into it.
 
Für alle Schnellfahrer unter uns, habe ich heute noch eine Änderung der Motorsteuerung vorgenommen. Mir war aufgefallen, dass der Mäher bei vollem Tempo nur noch eingeschränkt oder gar nicht mehr lenkbar war. Das liegt daran, dass einer oder beide Motoren bereits mit pwmMax angesteuert werden. Um das Problem zu lösen habe ich folgende Änderung in die motor.cpp eingebaut:

//######################## Calculate PWM for left driving motor ############################
motorLeftPID.TaMax = 0.1;
motorLeftPID.x = motorLeftRpmCurr;
motorLeftPID.w = motorLeftRpmSet;
motorLeftPID.y_min = -pwmMax * 4;
motorLeftPID.y_max = pwmMax * 4;
motorLeftPID.max_output = pwmMax;
motorLeftPID.compute();
motorLeftPWMCurr = motorLeftPID.y;
/*
motorLeftPWMCurr = motorLeftPWMCurr + motorLeftPID.y;
if (motorLeftRpmSet >= 0) motorLeftPWMCurr = min( max(0, (int)motorLeftPWMCurr), pwmMax); // 0.. pwmMax
if (motorLeftRpmSet < 0) motorLeftPWMCurr = max(-pwmMax, min(0, (int)motorLeftPWMCurr)); // -pwmMax..0
*/
if ((abs(motorLeftRpmSet) < 0.01) && (abs(motorLeftPWMCurr) < 30)) motorLeftPWMCurr = 0;
//######################## Calculate PWM for right driving motor ############################

motorRightPID.TaMax = 0.1;
motorRightPID.x = motorRightRpmCurr;
motorRightPID.w = motorRightRpmSet;
motorRightPID.y_min = -pwmMax * 4;
motorRightPID.y_max = pwmMax * 4;
motorRightPID.max_output = pwmMax;
motorRightPID.compute();
motorRightPWMCurr = motorRightPID.y;
/*
motorRightPWMCurr = motorRightPWMCurr + motorRightPID.y;
if (motorRightRpmSet >= 0) motorRightPWMCurr = min( max(0, (int)motorRightPWMCurr), pwmMax); // 0.. pwmMax
if (motorRightRpmSet < 0) motorRightPWMCurr = max(-pwmMax, min(0, (int)motorRightPWMCurr)); // -pwmMax..0
*/
if ((abs(motorRightRpmSet) < 0.01) && (abs(motorRightPWMCurr) < 30)) motorRightPWMCurr = 0;
//######################## Reduce PWM if more than pwmMax ##########################
float maxPWMCurr = max(abs(motorLeftPWMCurr), abs(motorRightPWMCurr));
if((maxPWMCurr > pwmMax) && (maxPWMCurr != 0)){
motorLeftPWMCurr = (int)(motorLeftPWMCurr / maxPWMCurr * pwmMax);
motorRightPWMCurr = (int)(motorRightPWMCurr / maxPWMCurr * pwmMax);
}

Im Detail:​

  1. das Limit des PID auf pwmMax * 4 gesetzt.
  2. den max. PWM-Absolutwert für die beiden Antriebsmotoren ermittelt.
  3. beide PWM-Werte im Verhältnis der Überschreitung reduziert.
Durch die Änderung bleibt die gewollte Drehzahldifferenz zwischen links und rechts vorhanden und der Mäher ist voll lenkbar. Ebenso wird der Mäher stabilisiert, wenn er einseitig über ein Hindernis fährt. Mein Test ist, auf einer gepflasterten Ebene mit einem Rad über einen Gartenschlauch zu fahren. Bisher hat der Mäher dabei eine großen Schlenker gemacht. Jetzt ruckelt er nur noch sehr leicht.
 
Zuletzt bearbeitet:
Ok, after a bit of research, seems lke you need some kind of feedfordward for controlling velocity with PID in this case.
The PWM then becomes this:
C++:
pwm = 10.0 * sign(setRPM) + setRPM * 3.0 + PIDoutput
The constants will depend on the motors.

Basically a hybrid approach, you have the simple FF doing most of the work and then PID just correcting the errors. Now P can be set properly.

Ive also added a pwm change limiter, otherwise you get too sudden movement when turning or stopping.
Id say it feels a bit better than PID with just the integral.
 
Zuletzt bearbeitet:
This seems more of a reason. Let the PID handle the Error and decuple the vel setpoint from from pure Ticks.
 
Basically a hybrid approach, you have the simple FF doing most of the work and then PID just correcting the errors. Now P can be set properly.
I also thought about that. On even ground its nice, but on high gradient, like on my lawn, that dosn't work.
pwm = 10.0 * sign(setRPM) + setRPM * 3.0 + PIDoutput
What is the reason for 10.0 * sign(setRPM)? May you post your PID-values?
 
I really think it depends on the drivers. For high slope environment, you mean going down will result at much higher velocity and vice versa?
The rotor of the motor will unsync with the em field. For yjqd i think i observed different: when under load, like going up or mowing high lawn with constant pwm input the consumed power will rise, so the rotor isnt desyncing. On the software and or physical powercap drivers rotor starts desyncing. I am not sure i did no researching, but is this reasonable?
 
You still have pid in there, the integral part will remove the error between the FF and the measured speed.

The 10.0 is friction, motors need a bit of voltage to get started, its around 10 pwm for me, the sign is to get the direction of the motor.
Im running 5.0 P and 5.0 I, havent spent too much time tuning but Im happy with those.
 
Zuletzt bearbeitet:
Oben