/***************************************************************************/ /* balanceREAD.c */ /* Balancing robot algorithm with PID control for driving straight */ /* Collectind Data for analysis */ /* Author: Rich Chi Ooi */ /* Version: 1.0 */ /* 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 "stdio.h" #include "eyebot.h" #include "ppwa.h" #include "sensors.h" #include "kalman.h" #define MAX 5000 int counter = 0; float XDIST[MAX]; float XRATE[MAX]; float PHIANGLE[MAX]; float PHIRATE[MAX]; float ANGLE[MAX]; int MOTORCOMMAND[MAX]; /*metre per tick*/ static const float MPT = (M_PI*0.051)/3495; /*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 = -31.6; static const float Xdot_K = -34.3; static const float PHI_K = 1467.6; static const float PHIdot_K = 113.8; /*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>95){ motor_command = 95; } if(motor_command<-95){ motor_command = -95; } MOTORDrive(motorLeft,motor_command-r_motor); MOTORDrive(motorRight,motor_command+r_motor); XDIST[counter]= X; XRATE[counter] = Xdot; PHIANGLE[counter] = PHI; PHIRATE[counter] = PHIdot; ANGLE[counter] = angle; MOTORCOMMAND[counter] = motor_command; counter++; /* 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:%d\n",motor_command); */ } /* *Uploading data to PC */ static void uploadData(){ FILE *ser; int iKey; int i; LCDPrintf("Upload Data?\n"); OSWait(50); LCDMenu(" "," ","YES","END"); iKey=KEYGet(); if(iKey==KEY3){ OSInitRS232(SER115200,NONE,SERIAL1); ser = fdopen(SERIAL1, "w"); if (ser==NULL){ LCDPrintf("serial init error\n"); }else{ LCDPrintf("init OK >%d<\n", (int) ser); } fprintf(ser,"X,Xdot,PHI,PHIdot,ANGLE,motor_command\n"); for(i=0;i