/***************************************************************************/ /* balancePID.c */ /* Balancing robot algorithm with PID control for driving straight */ /* Author: Rich Chi Ooi */ /* Version: 1.3 */ /* Date:14.08.2003 */ /* ------------------------------- */ /* Compilation procedure: */ /* Linux */ /* gcc68 -c XXXXXX.c (to create object file) */ /* gcc68 -o XXXXXX.hex XXXXXX.o ppwa.o */ /***************************************************************************/ /* In this version: */ /***************************************************************************/ #include #include #include "eyebot.h" #include "ppwa.h" #include "sensors.h" #include "kalman.h" #define MAX 5000 /*metre per tick*/ static const float MPT = (M_PI*0.051)/540; /*Gyro Scaling to rad/s */ static const float GY_SCALE = 0.002798; /*Time step for encoder reading*/ static const float DT = 0.02; MotorHandle motorLeft; MotorHandle motorRight; QuadHandle quadLeft; QuadHandle quadRight; /*Gain values for state control*/ static const float X_K = -80.6; static const float Xdot_K = -36.1; static const float PHI_K = 231.5; static const float PHIdot_K =57.2; /*PID Gains*/ static const float KP = 0.35; static const float KI = 0.025; static const float KD = 0.75; static float distance_old = 0; static int r_old = 0; static int e_old = 0; static int e_old2 = 0; static int enc_left_new = 0; static int enc_right_new = 0; static int e_func = 0; static int r_motor = 0; static float X = 0; static float Xdot = 0; static float PHI = 0; static float PHIdot = 0; static float command = 0; static float gy_angle = 0; static float in_angle = 0; static int motor_command = 0; /* *Initialize the filter */ void stateInit(){ int gyRaw = 0; gyRaw = gyroRaw(); q_bias =gyRaw*GY_SCALE; angle = incAngle(); } void balance(){ gy_angle = gyroRaw()*GY_SCALE; in_angle = incAngle(); stateUpdate(gy_angle); kalmanUpdate(in_angle); enc_left_new = QUADRead(quadLeft); enc_right_new = QUADRead(quadRight); PHI = in_angle; PHIdot = rate; X = ((enc_left_new+enc_right_new)/2)*MPT; Xdot = (X - distance_old)/DT; e_func = enc_left_new-enc_right_new; r_motor =(int)( r_old+KP*(e_func-e_old)+KI*(e_func+e_old)/2 +KD*(e_func-2*e_old+e_old2)); e_old2 = e_old; e_old = e_func; r_old = r_motor; distance_old = X; motor_command =(int) (-1*((X*X_K)+(Xdot*Xdot_K)+(PHI*PHI_K)+(PHIdot*PHIdot_K))); if(motor_command>100){ motor_command = 100; } if(motor_command<-100){ motor_command = -100; } MOTORDrive(motorLeft,motor_command-r_motor); MOTORDrive(motorRight,motor_command+r_motor); LCDSetPos(1,0); LCDPrintf(" X:%.4f\n XD:%.4f\n",X,Xdot); LCDSetPos(3,0); LCDPrintf(" P:%.4f\n PD:%.4f\n",PHI,PHIdot); LCDSetPos(5,0); LCDPrintf("CMD:%.4f\n",command); } int main(void) { ServoHandle gyro; TimerHandle balanceTimer; /*initialize ports and sensors*/ tpuInit(); gyroInit(gyro); inclinoInit(); motorLeft = MOTORInit(MOTOR_LEFT); motorRight = MOTORInit(MOTOR_RIGHT); quadLeft = QUADInit(QUAD_LEFT); quadRight = QUADInit(QUAD_RIGHT); QUADReset(quadRight); QUADReset(quadLeft); stateInit(); OSWait(200); LCDPrintf("ROBOT INITIALIZED \n"); LCDClear(); balanceTimer = OSAttachTimer(2,(TimerFnc)balance); while(KEYRead()!=KEY4){ } /*release all handles*/ OSDetachTimer(balanceTimer); SERVORelease(gyro); MOTORRelease(motorLeft); MOTORRelease(motorRight); QUADRelease(quadLeft); QUADRelease(quadRight); }