I've adapted the PDI feedback controller for use with a small 3V DC motor. The AVR 8515 provides speed control with an 8-bit PWM signal, and gets back speed data via an optical interrupter switch. The AVR chip is also optically isolated from the motor electronics. The feedback control loop operates at 2 samples/corrections per second.
In the photo below, the motor circuit is on the breadboard, with the motor at right. The scope shows the PWM signal (top trace) which is fixed at 28 Hz, and the output of the optical sensor mounted on the motor (bottom trace). The motor is running at 28 revs/sec, so the two signals are currently phase locked for display purposes. However, the motor can run from about 10 rps to about 215 rps from the PWM signal at this frequency, and the input and output are usually frequency and phase independent. The motor usually stalls below 20 rps unless it is under active control.
Here is a closeup of the motor and optical sensor. The shutter is just a piece of cardboard which triggers the sensor at 2x the motor speed. The motor is glued to a piece of flexible tubing, and then to a wood base. Originally, I had used a custom cardboard cradle for the motor, and had glued everything down tightly, but that produced way too much noise and resonance in the board, robbed energy from the motor, changed the step response considerably, and made it much harder to control. Let this be a lesson that real-world physical devices are much more than just idealized Laplace transfer functions, and that all aspects of the system must be empirically taken into consideration in the engineering.
Here is the overall circuit. The 8.4V/G1 rails are from a 1.5A camcorder power supply I found in the trash, while the 5V/G2 rails are from the AVR development board. These produce two completely independent electrical circuits which are interfaced by the 4N29 and 422A2 optical devices. The main purpose of the top transistor is just to reduce the 8.4V supply for the motor, which takes only 3V. The PWM signal comes in at left, and the speed signal goes out at right.
Here is a step response for the kP coefficient set at -2. (The plot is 60 sec long.)
Here kP has been reduced to -1, but the response still oscillates.
Even at kP = -0.5 there is a small oscillation. This suggests that the sampling/correction rate of 2/sec is not quite fast enough to control this system, and the delay is too long to prevent an oscillation. Nevertheless, the motor can actually be controlled at this rate by properly tuning the other coefficients and using another 'trick' below.
Setting kD = -1.5 damps the oscillation.
Setting kI = -0.075 slightly improves the rise time, but I don't want to overshoot for reasons you'll see in the next picture.
Here is a sequence of target settings from 127 -> 63 -> 191 -> 127 -> 10. As you can see, the downward response way overshoots the target. This demonstrates that the system is not symmetric: the motor slows down much faster than it speeds up. (But, neither is it linear or time invariant either, both of which are requirements for a PDI controller to work right.) Also, the motor tends to stall when set to its lowest speed range. But, the controller will eventually get it going again and find the right speed.
All of these problems can be obviated if the target setting is not allowed to be a step function (i.e. is band-limited). This makes sense since the 2 samples/sec control loop has a maximum frequency response of only 1 Hz! The solution is to filter the target setting, in this case with a simple exponential filter. This makes it much easier for the controller and motor to follow the desired setting, and allows the motor to idle slowly without stalling.
I've since added a slider to set the target value continuously, and buttons to start and stop the motor in a controlled way. Next projects will involve controlling two motors simultaneously for a differential robot drive, or using a motor to point and hold an orientation for a steering wheel(s).
İSky Coyote 2006