Hi,
I managed to implement a balancing algorithm based on many examples on the web. It seems that I get the angle right, fast and reasonable, but I have problems in tuning the PD control law there. I only once got it close to balancing, now can't go back there
My small knowledge is that the "P * angle" will introduces the proportional movement of motor related to the current angle and at the same time, the "D * rate" will introduce a damping effect, so that the robot won't swing all the time, but to stay stable in balance. How best to approach the balance point? I started to keep D zero and first add to P, but this also didn't considerably change the situation. when the robot is falling, the motor response is not that fast at first, but near the 30deg gets enough fast, but it is too late! Also, if I just add to P so that to have faster move on small change in deg. then the robot comes wild and no success again! Confused how to balance it!
I'd be thankful to have suggestions how to tune it. Below comes my code.
#define LPWM 3Â Â Â Â Â
#define RPWM 9Â Â Â Â
#define LDIRAÂ 6Â Â Â Â
#define LDIRB 5Â Â Â Â
#define RDIRAÂ 11Â Â Â Â
#define RDIRB 10Â Â Â Â
#define A_PIN 5Â Â
#define G_PIN 0Â Â Â Â
#define A_ZERO 553
#define G_ZERO 473Â Â Â
#define A_GAIN 0.280Â Â
#define G_GAIN 0.33Â Â
#define DT 0.01Â Â Â Â
#define A 0.962Â Â Â
float angle = 0.0;Â Â Â
float rate = 0.0;Â Â Â
float output = 0.0;Â Â
void setup()
{
 pinMode(LPWM, OUTPUT);
 pinMode(RPWM, OUTPUT);
 pinMode(LDIRA, OUTPUT);
 pinMode(LDIRB, OUTPUT);
 pinMode(RDIRA, OUTPUT);
 pinMode(RDIRB, OUTPUT);
Â
 Serial.begin(9600);
}
void loop()
{
  signed int accel_raw = 0;
  signed int gyro_raw = 0;
   accel_raw = (signed int) analogRead(A_PIN) - A_ZERO;
   gyro_raw = (signed int) analogRead(G_PIN) - G_ZERO;
Â
 rate = (float) gyro_raw * G_GAIN;
 angle = A * (angle + rate * DT) + (1 - A) * (float) accel_raw * A_GAIN;
Â
Serial.println(angle);
 if(!(angle>30 || angle < -30))
 {
output = angle * 7 + rate * 2 ;
 if(output < -255.0) { output = -255.0; }
 if(output > 255.0) { output = 255.0; }
 if(output >= 0)
 {
  digitalWrite(LDIRA, HIGH);
  digitalWrite(LDIRB, LOW);
  analogWrite(LPWM, output);
 }
 else
 {
  digitalWrite(LDIRA, LOW);
  digitalWrite(LDIRB, HIGH);
  analogWrite(LPWM, -output);
 }
Â
 output = -1 * output;
  if(output >= 0)
 {
  digitalWrite(RDIRA, HIGH);
  digitalWrite(RDIRB, LOW);
  analogWrite(RPWM, output);
 }
 else
 {
  digitalWrite(RDIRA, LOW);
  digitalWrite(RDIRB, HIGH);
  analogWrite(RPWM, -output);
 }
 }//if(!(angle>30 || angle < -30))
 else
 {
  analogWrite(LPWM, 0);
  analogWrite(RPWM, 0);
 }
 delay(10);
}