AFAIK no, the PID controller in the balanduino requires the user to set the balancing angle. I think that this can be done however using another form of full state feedback control and an observer model to estimate slope.

Now that I think about it, if another PID controller is set to control the balancing angle with the wheel velocity as its control input, it would be possible to have the balanduino automatically balance at an angle that would minimize the wheel velocity error, which would be the balancing angle.

Actually it should be possible, but the PID parameters would need to be tweaked.Currently the Balanduino has one PID loop for keeping the balance, but together with this loop there is actually also another controller that keeps track of the encoder.An unexpected change in encoder value will also influence the motor speed, so if the gain of this controller is increased, this should increase the stability on sloped floors.

I've studied the balanduino code for position error correction (Back to spot feature), it is almost like a fuzzy controller but with hard limits (multiple zones without overlap). If this controller is replaced with a PID controller with separate tunable gains, with the wheel velocity error as input, a setpoint of zero (unless it is required to move the robot forward or backward) and the output as the angle offset (constrained to +/-45 degrees) that would be added to the default balancing angle of 180, it should work.

I've studied the balanduino code for position error correction (Back to spot feature), it is almost like a fuzzy controller but with hard limits (multiple zones without overlap). If this controller is replaced with a PID controller with separate tunable gains, with the wheel velocity error as input, a setpoint of zero (unless it is required to move the robot forward or backward) and the output as the angle offset (constrained to +/-45 degrees) that would be added to the default balancing angle of 180, it should work

encoders_pid.Compute(); restAngle += cfg.targetAngle;In my approach I'm using the input as the error in wheelPosition, output as the +/- offset of the restAngle and the setpoint as zero (basically the same thing).

AnglePID.SetOutputLimits(-5,5);The problem right now with mine is it exhibits oscillatory behavior and then after some time the oscillation amplitude magnifies and it drifts off.

Also note that limiting the output of the PID controller with SetOutputLimits doesn't limit the final targetAngle because the output of the PID controller is added to the restAngle as an offset. That's why I constrained my final targetAngle to 145 and 215 degrees.

Have you tried using the wheelVelocity as the input to the PID controller and zero as the Setpoint? I'm testing this right now and it's giving me good results. (The balanduino wheel velocity should decrease as the target angle becomes closer to the balancing angle)

Also, are we sure that the PID controller output should be DIRECT or should be REVERSE? I've tried it with both and for some reason REVERSE is also working with almost exactly the same results.

EDIT: No, after some testing I've confirmed it's DIRECT. I now have it balancing well, still with oscillation but after it finds the balancing angle it keeps balanced. The issues i'm having is it is slow to determine the balancing angle when a change occurs (plane is tilted or eccentric mass is added) so it will keep oscillating for a while to determine the new balancing angle. This I guess can be solved by better tuning the PID controller.

BTW; So far I'm having better luck with a PD controller instead of a PID controller, but could be a false positive, I'm still checking it out. (Kp=15, Kd=5)

Also note that limiting the output of the PID controller with SetOutputLimits doesn't limit the final targetAngle because the output of the PID controller is added to the restAngle as an offset. That's why I constrained my final targetAngle to 145 and 215 degrees.

No that is not correct. Please have an extra look at my code. Note that I do not modify the targetAngle, as it is intended to be adjusted if the weight is not perfectly in the center. For instance I used this when I mounted a GoPro on the back:

So targetAngle is a constant and I simply limit the restAngle to +-10 degrees. Finally I add the targetAngle (normally 180 degrees) . The result is that I have a restAngle from 170 to 190 degrees.

Quote

Have you tried using the wheelVelocity as the input to the PID controller and zero as the Setpoint? I'm testing this right now and it's giving me good results. (The balanduino wheel velocity should decrease as the target angle becomes closer to the balancing angle)

I have also tried this previously without much success, but two minds is always better than one

Quote

BTW; So far I'm having better luck with a PD controller instead of a PID controller, but could be a false positive, I'm still checking it out. (Kp=15, Kd=5)

Have you forked the Balanduino code on Github? I would love to try it out. Also are these values divided by 100 in your code?

No I haven't forked it on Github but Here's the progress I've made so far. It can balance without any eccentric mass added, and if you gradually change the center of gravity by adding eccentric mass to the body it will eventually find the new balancing angle. But it takes too long and keeps oscillating around for a while till it finds it. (Can't do sudden changes)

I've modified my code quite a bit, and now I have it finally working. It is balancing well with acceptable performance using a PD controller that only activates outside a certain zone of position error, note that the gains still need a little bit of tuning and the zone that the controller gets activated in might also need more consideration. Please check attached code and tell me what you think.

I'm using gains for the main balanduino PID controller of Kp=7.5, Ki=2 & Kd=3.

Finally, there is quite a major issue that I think we didn't consider, while we can get the robot to balance on inclines, if you reorient (spin) the robot so that it's facing the other way (180 degrees) while it's on the incline, the controller can't adjust fast enough to reverse the tilt angle all the way around. A possible solution is to read the orientation reading from the IMU (Z axis) and "invert" the PWM values going to the motors?