Self-BalanceRobot Code
Self-BalanceRobot Code
#include <PinChangeInt.h> //This library file can make all pins on the REV4
board as external interrupts. Define three-axis acceleration, three-axis
gyroscope variables
int16_t ax, ay, az, gx, gy, gz; //Define three-axis acceleration, three-axis
gyroscope variables
///////////////////////angle parameters//////////////////////////////
///////////////////////angle parameter//////////////////////////////
///////////////////////Kalman_Filter////////////////////////////
char C_0 = 1;
float K_0,K_1,t_0,t_1;
float angle_err;
float accelz = 0;
float angle;
float angleY_one;
float angle_speed;
//////////////////////Kalman_Filter/////////////////////////
//////////////////////PID parameter///////////////////////////////
double kp = 34, ki = 0, kd = 0.62; //angle loop parameter
float pwm1=0,pwm2=0;
int speedcc = 0;
//////////////////////pulse count/////////////////////////
int lz = 0;
int rz = 0;
int rpluse = 0;
int lpluse = 0;
int pulseright,pulseleft;
float speeds_filterold=0;
float positions=0;
int flag1;
double PI_pwm;
int cc;
int speedout;
float speeds_filter;
//////////////////////////////turning PD///////////////////
int turnmax,turnmin,turnout;
float Turn_pwm = 0;
int zz=0;
int turncc=0;
//Bluetooth//
char val;
int i,button;
void setup()
pinMode(right_R1,OUTPUT);
pinMode(right_R2,OUTPUT);
pinMode(left_L1,OUTPUT);
pinMode(left_L2,OUTPUT);
pinMode(PWM_R,OUTPUT);
pinMode(PWM_L,OUTPUT);
//assign the initial state value
digitalWrite(right_R1,1);
digitalWrite(right_R2,0);
digitalWrite(left_L1,0);
digitalWrite(left_L2,1);
analogWrite(PWM_R,0);
analogWrite(PWM_L,0);
pinMode(PinA_right, INPUT);
pinMode(btn,INPUT);
pinMode(buz,OUTPUT);
delay(1500);
delay(2);
//5ms; use timer2 to set the timer interrupt (note: using timer2 may affects
the PWM output of pin3 pin11)
//buzzer
void buzzer()
for(int i=0;i<50;i++)
digitalWrite(buz,HIGH);
delay(1);
digitalWrite(buz,LOW);
delay(1);
delay(50);
for(int i=0;i<50;i++)
digitalWrite(buz,HIGH);
delay(1);
digitalWrite(buz,LOW);
delay(1);
void loop()
//Serial.println(angle0);
//Serial.print("angle= ");
//Serial.println(angle);
//delay(1);
//Serial.println(PD_pwm);
//Serial.println(pwm1);
//Serial.println(pwm2);
//Serial.print("pulseright = ");
//Serial.println(pulseright);
//Serial.print("pulseleft = ");
//Serial.println(pulseleft);
//Serial.println(PI_pwm);
//Serial.println(speeds_filter);
//Serial.println (positions);
//Serial.println(Turn_pwm);
//Serial.println(Gyro_z);
//Serial.println(Turn_pwm);
while(i<1)
button = digitalRead(btn);
if(button == 0)
angle0=-angle;
//Serial.println(angle0);
buzzer();
i++;
if(Serial.available())
{
val = Serial.read(); //assign the value read from the serial port to val
//Serial.println(val);
case 'F': front=250; break; //if val equals F,front=250,car will move
forward
/////////////////////Hall count/////////////////////////
void Code_left()
{
count_left ++;
void Code_right()
count_right ++;
////////////////////pulse count///////////////////////
void countpluse()
rz = count_right;
count_right = 0;
lpluse = lz;
rpluse = rz;
if ((pwm1 < 0) && (pwm2 < 0)) //judge the car’s moving
direction; if backward (PWM namely motor voltage is negative), pulse is a
negative number.
rpluse = -rpluse;
lpluse = -lpluse;
else if ((pwm1 > 0) && (pwm2 > 0)) //if backward (PWM namely
motor voltage is positive), pulse is a positive number.
{
rpluse = rpluse;
lpluse = lpluse;
else if ((pwm1 < 0) && (pwm2 > 0)) //judge the car’s moving
direction; if turn left, right pulse is a positive number; left pulse is a negative
number.
rpluse = rpluse;
lpluse = -lpluse;
else if ((pwm1 > 0) && (pwm2 < 0)) //judge the car’s moving
direction; if turn right, right pulse is a negative number; left pulse is a
positive number.
rpluse = -rpluse;
lpluse = lpluse;
pulseright += rpluse;
pulseleft += lpluse;
/////////////////////////////////interrupt ////////////////////////////
void DSzhongduan()
angle_calculate(ax, ay, az, gx, gy, gz, dt, Q_angle, Q_gyro, R_angle, C_0,
K1); //get angle and Kalmam filtering
anglePWM();
cc++;
speedpiout();
cc=0; //Clear
turncc++;
turnspin();
turncc=0; //Clear
///////////////////////////////////////////////////////////
/////////////////////////////tilt calculation///////////////////////
{
float Angle = -atan2(ay , az) * (180/ PI); //Radial rotation angle
calculation formula ; negative sign is direction processing
//accelz = az / 1604;
float angleAx = -atan2(ax, az) * (180 / PI); //calculate the inclined angle with
x-axis
////////////////////////////////////////////////////////////////
///////////////////////////////KalmanFilter/////////////////////
Pdot[1] = - P[1][1];
Pdot[2] = - P[1][1];
Pdot[3] = Q_gyro;
P[0][0] += Pdot[0] * dt; //The integral of the covariance differential of the
prior estimate error
//denominator
//gain value
K_0 = PCt_0 / E;
K_1 = PCt_1 / E;
/////////////////////first-order filter/////////////////
//////////////////angle PD////////////////////
void PD()
//////////////////speed PI////////////////////
void speedpiout()
speeds_filterold = speeds_filter;
positions += speeds_filter;
//////////////////speed PI////////////////////
///////////////////////////turning/////////////////////////////////
void turnspin()
int flag = 0; //
float turnspeed = 0;
float rotationratio = 0;
if (left == 1 || right == 1)
flag=1;
turnspeed = -turnspeed;
rotationratio = 0.5;
if (rotationratio > 5)
rotationratio = 5;
else
rotationratio = 0.5;
flag = 0;
turnspeed = 0;
turnout += rotationratio;
turnout -= rotationratio;
}
else turnout = 0;
///////////////////////////turning/////////////////////////////////
void anglePWM()
pwm1=255;
if(pwm1<-255)
pwm1=-255;
if(pwm2>255)
pwm2=255;
}
if(pwm2<-255)
pwm2=-255;
pwm1=pwm2=0;
digitalWrite(left_L1,LOW);
digitalWrite(left_L2,HIGH);
analogWrite(PWM_L,pwm2);
else
digitalWrite(left_L1,HIGH);
digitalWrite(left_L2,LOW);
analogWrite(PWM_L,-pwm2);
if(pwm1>=0)
{
digitalWrite(right_R1,LOW);
digitalWrite(right_R2,HIGH);
analogWrite(PWM_R,pwm1);
else
digitalWrite(right_R1,HIGH);
digitalWrite(right_R2,LOW);
analogWrite(PWM_R,-pwm1);