Digital & Embedded Systems

PID Implementation on Eyebot

If we want the motor to go at speed D, but it actually goes at speed A then the error is:
E =A-D

Proportional Control
We would like the motor to go at speed A+E. Ideally we would add E to the motor input which would set it at the desired speed.

In the real world, the motor takes some time to react; also there are delays in the system. Therefore, by the time we add E to the motor input, the motor could be going at a different speed. To allow for this, we add a small proportion, kP, of E to the motor input, check the speed again, and keep adding small proportions of the error until desired speed is reached.

Motor = Motor + kP*E

Derivative Control
The proportional controller responds slowly to a change in error - flick the wheel (impulse response) and watch it oscillate and return slowly to original position. To solve this problem: make the speed setting dependant on the rate of change of error - the derivative.

In practice, the rate of change is just the current error value minus the previous one.

dE = E(current) - E(last);

To introduce derivative control, add a portion of dE to the motor input,

Motor = Motor + kP*E + kD*dE

Integral Control
Equilibrium may be reached without reaching target velocity (try turning the wheel slowly with just the PD controller). To minimise this, take a sum of the errors and add a proportion, kI, of this to the Motor input.

sE = sE + E

Motor = Motor + kP*E + kD*dE + kI*sE

Introducing the integral component of the PID controller also has some associated problems. Namely, the settling time for the motor will increase as well as the % overshoot.

Calling Functions Periodically
Use OSAttachTimer, for this specify the scale and cast the function to be called to TimerFnc type (see RoBiOS documentation).

Initialising the motor
MotorHandle MOTORInit(DeviceSemantics semantics);


MotorHandle leftWheel;
leftWheel = MOTORInit(MOTOR_LEFT);

The variable LeftWheel (of type MotorHandle) can now be used to identify the left motor for subsequent function calls that use the motor.

Driving the motor
int MOTORDrive(MotorHandle handle, int speed);

Example (Using the previously defined handle, leftWheel):

int motorSpeed = 50;
MOTORDrive(leftWheel, motorSpeed);

This sets the left motor to 50% (valid speed from -100 to 100).

Releasing the motor
Once the motor is no longer needed, 'release' it - see RoBiOS documentation for function.

Reading Motor Speed
Motor shaft position is determined using the 'Quad' functions in a similar way to setting motor speed (get a handle, take the speed, once no longer needed, release the handle). See the RoBiOS documentation for details. Motor speed can be derived as the change in position.

NOTE: In the same way that MOTOR_LEFT was used to get a handle to the left motor, use QUAD_LEFT for the motors position encoder.