For the steering to work correctly, the steering mechanism has to be calibrated. One needs to know when the steering is centered. The easiest way is to do it by hand, remove the 12 tooth pinion, center the steering and put it back on. I used this method until today.

Today, I had a day of from work and family. I used it to make the car calibrate its steering while driving.

Calibration is done everytime the car has to drive a straight line. It then uses it’s gyro and a PID controler to drive straight. If the steering is miscalibrated this will take some time. But once FreeRover drives straight, it stores the current encoder value as steering centre. Thus calibrating the steering.

Writing a PID controller is not very difficult, but it needs to be tuned before it works well. Tuning is difficult. It took me some time to tune the PID controller but now it’s working like a blast.

The autocalibration calibrates within a meter, but well before that it corrects for an offset steering. For FreeRover autocalibration is very usefull because the steering gets lots of strain from collisions, the front wheel drive system and design errors. As a result, it gets miscalibrated very easily.

Here is the robotC code dealing with autocalibration. Note that calibration is done if the absolute value of past errors is below a certain treshhold. This treshhold is then decreased to allow for even bettter calibration. The treshhold is reset every time the car starts driving straight.

// PID controller using the gyro to tune the car for driving straight task driveStraight() { float Kp=1.6, Ki=0.008, Kd=0.2, memory=0.6; float error=0, integral=0, absIntegral=0, derivative, lastError=0, sumError, calibrationOffset=32; int i, dT=80,x=0, q=0 ; while (true) { wait1Msec(100); calibrationOffset=32; q=0; while(state==STdrive) { // Read the gyro 20 times (to eliminate noise) and calculate the error; sumError=0; for (i=0;i<20;i++) { sumError+=(float)HTGYROreadRot(HTGYRO); wait1Msec(4); } error=(-sumError/20); // Test again, for gyro loop took some time if (state==STdrive) { // If the sum of last errors is below a treshold then the car is driving straight steadily. // Calibrate the center steering if (q++>20 && absIntegral<calibrationOffset) { nMotorEncoder[steer]=0; calibrationOffset=calibrationOffset/2; } else { // Calculate the values for PID integral=memory*integral+(error*dT); absIntegral=memory*absIntegral+(abs(error)); derivative=(error-lastError)/dT; // calculate the steer correction value (it will be picked up by the steering task steerCorrection=clip(Kp*error+Ki*integral+Kd*derivative,-80,80); lastError=error; // Plot the sum of the last errors. /* nxtEraseLine(x, 0, x, 50); nxtSetPixel(x, absIntegral); if (x++>99) x=0; nxtDrawLine(x, 0, x, 47); nxtDisplayTextLine(0, "E:%4.2f", error); nxtDisplayTextLine(1, "I:%4.2f", absIntegral); */ } } } } }