| Motor Control and Optical Encoders
First, as the robot's battery voltage would slowly drop, the servo's centre point would drift. After a while, one or both servo motors would begin to creep even though they should have been stopped.
Secondly, servos are designed to hold a position and not a set speed. Normally the position would be set by the length of the control pulse. 1.0mS would be one extreme and 2.0mS the other. Normally 1.5mS would be in the middle. After being modified for continous rotation, any pulse length shorter than 1.5mS causes the servo to rotate one direction, and anything longer causes the servo to rotate in the other direction. The magnitude of the pulse width deviation from 1.5mS has an affect on the rotation speed, but it's a bit variable and not linear.
For this project I decided to use some 1:100 gear head motors I bought from Pololu.com. I also decided that I needed feedback so I could accurately know how fast the wheels were actually rotating. One way to do this is to use optical sensors that detect a pattern attached to the wheel. If there are two sensors and they are positioned correctly then you can implement something called quadrature detection (like was used in the old wheeled mice). Then you can tell not only the amount of rotation by counting pulses but also its direction by observed the phase between the two sensors.
Fitzy and Carraldo are using the MicroChip dsPIC33FJ64MC804 as their brain. The MC variant includes dual built in quadrature encoders that are just what I need to turn pulses from optical sensors into direction and distance.
Now I'll be the first to admit that mechanical design is not my strongest skill. When designing the PCB I had only located the position of the motors but I hadn't really decided exactly how I would attach them. Caught up in the excitement of making the boards I assumed that something clever would present itself.
How Not to Implement Optical Sensors
There are two common types of optical sensors; reflective and transmissive.
In reflective sensors an assembly contains an LED and a phototransistor both facing in the same direction. If a reflective surface comes in front of the assembly, the LED's light is reflected onto the phototransistor and a signal is detected.
Here you can see the OP609 Reflective Object Sensor that I chose. The LED is glowing blue because my camera is slightly sensitive in the IR region. With the human eye, there's nothing to see.
The major problem I hadn't anticipated is that sub millimeter changes in the distance from the sensor to the target result is huge changes in the detected signal. Problems with mounting the motors and the wheels caused the wheels to wobble slightly and this made the detected signals completely unusuable.
Because of the wobbling I had to use a coarse pattern. Although I eventually got it working, the method of mounting the motors and sensors was just too clumbsy. Because of my limited mechanical skills I decided an alternate approach was required. One that would minimize sources of wobble.
Finally a Method That Works
The second kind of sensor is transmissive. The LED and phototransistor are mounted facing each other. When an opaque object blocks the LED an signal is detected. I decided to minimize physical positioning errors by mounting the sensors and the motor onto the same PCB. Fortunately the gear-head motors have a brass plate that can be soldered to a PCB. The part I chose is the RPI-125 from Rohm Semiconductor. Finding a side mount component that was reasonably priced proved impossible so I used a vertical mount part and just mounted it sideways. A bit of a kludge but that's life.
One problem I did have related to the optical encoder disk. I thought that just printing a disk onto a photocopier transparency would do the trick. The pattern was disappointly light.
I wasted a lot of time trying to come up with alternate types of encoder disks. After a lot of failed attempts I returned to the photocopier transparency. I laminated two printed encoder disks together using a clear 5-minute epoxy. Not only did this give the disk better stiffness but surprisingly the printed areas looked much darker than without the epoxy. Go figure. By lowering the brightness of the transmitting LED I achieved a good signal.
The circuit is very simple. I tried to allow for various filtering schemes so the PCB is slightly more complicated than necessary. This will be fixed before I send away for the next batch of PCBs.
I may yet adjust the current limiting resistors. 220Ohm work but 330Ohm may be better. Your mileage may vary depending on the opacity of the encoder disc.
H-Bridge Motor Drive
I'm using Pololu gear head motors. In order to drive the motors in either direction I'm using H-bridges. This circuit gets it's name from its distinctive shape. It consists of four switches arranged in an H as seen below. The load occupies the bridge of the H. When opposing upper and lower switches as closed, current flows through the load. The direction of the current, and the direction the motor rotates, can be controlled by which pair of switches you close.
I've built a prototype of the H-bridge in order to ensure that it works as planned. In my case, the upper switches are p-channel mosfets and the lower switches are n-channel mosfets. These mosfets are rated in excess of 4A and 30V. The Pololu motors have a stall current of 1.6A and should pose no challenge.
Mosfets have three terminals; gate, source and drain. For n-channel mosfets, when the gate and source are at the same voltage, the resistance between the drain and the source will be very high; effectively the open switch. As the gate voltage (Vgs) rises there comes a point where the drain-source resistance (Rds) begins to drop very rapidly. When the gate voltage is sufficiently high, the drain-source resistance will be very small, often in the milli-ohms. For many mosfets the gate voltage needs to be quite high, perhaps 10 to 12V above the the source voltage to reach this very low resistance state. There are, however, logic level mosfets that can achieve this state when Vgs is only 2.5V (I am using 3.3V).
A similar situation exists for p-channel mosfets. When Vgs is zero (the gate voltage is high), the source-drain resistance is high. To get the mosfet to conduct, you lower the gate voltage. As Vgs passes -2.5V, the mosfet reaches the low source-drain resistance region.
The circuit above reflects what I'm using for my robot. You'll notice a few extra elements. First, I have pull-up resistors on the p-channel gates, and pull-down resistors on the n-channel gates. This is first of all a precaution for when the circuit powers up. In the absence of control signals, I want the gates to be shut.
The pull-up resistors on the p-channel gates serve a second function. My microcontroller and all associated hardware runs at 3.3V. The motors run at 6V. Without some level translation I cannot set the p-channel gates to 6V in order to turn the mosfets off. To get around this, I pull the gate high to 6V. I then use a second n-channel mosfet that I can control using 3.3V to pull the p-channel gate low when I want to turn the upper switch on.
The logic gates attached to the circuit allow me to control the H-bridge using only two control lines. One is direction and the other is PWM. The direction line controls which upper p-channel mosfet is turned on. Using the PWM line I turn on and off the complimentary lower n-channel mosfet. Using PWM allows me to control the speed of the motor. The inherent logic ensures that I cannot turn on both the mosfets on one side of the H-bridge. Doing so results in shoot-through (a short circuit) that will surely release the magic smoke in the mosfets.
Once I flipped the p-channel mosfets around (sigh) the circuit performs very well at a PWM frequency of 20KHz. Lower frequencies work as well but the motor produces progressively larger back-EMF spikes as the frequency drops. I've run the Pololu motors aggressively with a heavy load but the mosfets don't even get warm. In the picture you can see the diminuitive NAND and AND logic packages. Barely larger than the SOT-23 mosfets themselves.
Not shown in the schematic but very important nonetheless (visible on the board by the voltage regulator) is a sizeable capacitor (minimum of 100uF) between the 6V rail and ground. I'm thinking that 330uF would be a good value if I can find a small enough package.
Next Section: I2C LCD Display