/***************************************************************************/ /* balance.c */ /* Balancing robot algorithm with PID control for driving straight */ /* Author: Rich Chi Ooi */ /* Version: 1.4 */ /* Date:28.08.2003 */ /* ------------------------------- */ /* Compilation procedure: */ /* Linux */ /* gcc68 -c XXXXXX.c (to create object file) */ /* gcc68 -o XXXXXX.hex XXXXXX.o ppwa.o */ /***************************************************************************/ /* In this version: */ /* Codes are restructured and reorganised to ensure proper execution */ /***************************************************************************/ #include #include #include "eyebot.h" #include "ppwa.h" #include "sensors.h" #include "kalman.h" /*Scale factor and constants*/ static const float MPT = (M_PI*0.051)/540; /*Metres per tick*/ static const float GY_SCALE = 0.002798; /*Gyro scaling to rad/s*/ static const float DT = 0.02; /*Time step for encoder reading*/ /*Gain values for state control*/ static const float X_K = -31.6; /*Vehicle Positon*/ static const float Xdot_K = -36.1; /*Vehicle Velocity*/ static const float PHI_K = 1641.5; /*Tilt angle*/ static const float PHIdot_K = 127.2; /*Tilt Angle velocity*/ /*PID Gains*/ static const float KP = 0.35; static const float KI = 0.025; static const float KD = 0.75; /*Handle declarations*/ MotorHandle motorLeft; MotorHandle motorRight; QuadHandle quadLeft; QuadHandle quadRight; static float distance_old = 0; static int r_old = 0; static int e_old = 0; static int e_old2 = 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 int motor_command = 0; static int enc_left = 0; static int enc_right = 0; /* *Initialize the filter */ void stateInit(){ q_bias = gyroRaw()*GY_SCALE; angle = incAngle(); } void balance() { stateUpdate(gyroRaw()*GY_SCALE); kalmanUpdate(incAngle()); enc_left = QUADRead(quadLeft); enc_right = QUADRead(quadRight); /*States values*/ PHI = incAngle(); PHIdot = rate; X = ((enc_left+enc_right)/2)*MPT; Xdot = (X - distance_old)/DT; e_func = enc_left-enc_right; 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); } /* Main program*/ int main(void) { ServoHandle gyro; TimerHandle balanceTimer; /*Initialize motors and encoders*/ motorLeft = MOTORInit(MOTOR_LEFT); motorRight = MOTORInit(MOTOR_RIGHT); quadLeft = QUADInit(QUAD_LEFT); quadRight = QUADInit(QUAD_RIGHT); /*initialize ports and sensors*/ tpuInit(); OSWait(50); gyroInit(gyro); OSWait(50); inclinoInit(); OSWait(50); 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); }