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);
Example:
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.