gcjr:
i've been thinking about this braking approach. by braking, i assume you mean shorting the motor thru the h-bridge
it adds a non-linear component to the linear PID algorithm which slightly complicates the code. The effect is proportional to speed. so i doubt braking when the motor is going slow has any effect.
where i think this is likely to become relevant during position control is at some distance from the target where the P and D (speed) terms balance (cancel one another) and the desire is to maintain that speed. It's likely that subsequent iterations would push the motor voltage negative which would actively brake regardless of speed.
so it seems that the dead zone should be handled by recognizing the minimum voltage to the motor and when the PID output swings from >0 to <0 to swing the motor voltage from minimum positive, thru zero (when PID == 0) to minimum negative (step change).
i wouldn't say this makes PID non-linear, it makes the motor control mapping PID output to motor voltage non-linear.
on the other hand, perhaps a non-PID approach could use braking while the motor is at speed if a good estimate of the deceleration rate were known (obtained during a calibration sweep). if you know that it takes so much distance to come to a stop from a specific speed, you could apply braking at that speed and distance. It's conceivable that braking is modulated (on/off) as you approach the target (like spoilers on a glider) so apply braking early.
if you come up short or long, i wonder if pulsing the motor could change position sufficient to reach the target +/- some tolerance. is one motor revolution acceptable tolerance?
thanks for your explanation
greg
Greg,
Breaking is minimal compared to powering up the motor in reverse and letting the motor cost with no power is potentially a loss of control. with my Balancing bot, consider that it only breaks when we are calling for literally 0 when swinging from forward 30 pwn to Reverse 30 PWM through the H-Bridge. At 30 PWM my motors on my balancing bot hum and possibly try to move in the direction I'm requesting this power level is definitely breaking for the opposite direction that I'm calling for. For 6 steps through setpoint (+-3) which is relatively small compared by the full control range of +-500 (which is a floating-point number with enough detail that because we are at setpoint we could float around the +-3 for some time). By hindering movement in both directions using the H-Bridge breaking mode seem to me to be a more accurate representation of what I am desiring. Consider driving a balancing bot up a hill then attempting to stop, would you rather release the motors to coast when you are balanced or cause some resistance by applying braking to the H-Bridge. Of course, balancing on a flat surf if you are moving forward you may want to coast while balanced. I tend to find breaking a better option here as breaking will slow the balancing bot towards stopping possibly helping me maintain a position.
This breaking/no-breaking, by the way, has come about with many many tests, I seem to like breaking but I have great control without breaking as well.
Here is my H-Bridge "TankPWM" code for my balancing bot and all Tank-style 2 motor steering Bots I have:
/* TankPWM *
LeftDrive: PWM Value +-500
RightDrive: PWM Value +-500
Breaking: Breaking Level 0 ~ 255
LeftPin, Forward_LeftPin, Reverse_LeftPin, RightPin, Forward_RightPin, Reverse_RightPin :
are the pins on the Uno that are being used to control the H-Bridge
*/
void TankPWM(int16_t LeftDrive,int16_t RightDrive, int16_t Breaking, uint8_t LeftPin, uint8_t Forward_LeftPin , uint8_t Reverse_LeftPin, uint8_t RightPin, uint8_t Forward_RightPin, uint8_t Reverse_RightPin ){
static int16_t LastLeftDrive;
static int16_t LastRightDrive;
static int16_t LastLeftDriveDirection;
static int16_t LastRightDriveDirection;
static int16_t ActualLeftDrive;
static int16_t ActualRightDrive;
ActualLeftDrive = abs(LeftDrive);
ActualRightDrive = abs(RightDrive);
if ((LeftDrive == 0) ||((LastLeftDriveDirection > 0) != (LeftDrive > 0))){
digitalWrite(Forward_LeftPin, LOW);
digitalWrite(Reverse_LeftPin, LOW);
ActualLeftDrive = min(255,abs(Breaking));
}
if ((RightDrive == 0) ||((LastRightDriveDirection > 0) != (RightDrive > 0))){
digitalWrite(Forward_RightPin, LOW);
digitalWrite(Reverse_RightPin, LOW);
ActualRightDrive = min(255,abs(Breaking));
}
//todo Add Slow Ramp up to Prevent sudden changes in direction for more powerful motors
LastLeftDriveDirection =LeftDrive;
LastRightDriveDirection= RightDrive;
LastLeftDrive = abs(LeftDrive);
LastRightDrive = abs(RightDrive);
analogWrite(LeftPin,constrain(map(ActualLeftDrive,0,500,0,255),0,255));
analogWrite(RightPin,constrain(map(ActualRightDrive,0,500,0,255),0,255));
if(LeftDrive < 0){
digitalWrite(Forward_LeftPin, HIGH);
digitalWrite(Reverse_LeftPin, LOW);
}
if(RightDrive < 0){
digitalWrite(Forward_RightPin, HIGH);
digitalWrite(Reverse_RightPin, LOW);
}
if(LeftDrive > 0){
digitalWrite(Forward_LeftPin, LOW);
digitalWrite(Reverse_LeftPin, HIGH);
}
if(RightDrive > 0){
digitalWrite(Forward_RightPin, LOW);
digitalWrite(Reverse_RightPin, HIGH);
}
}
Z
P.S.
@ dwnld99
Thanks for letting us steal your post I hope this is helpful with your project as it is relevant is many ways to controlling a positioning bot.