A perfect motor driver is bi-directional, switches instantly at any frequency without generating interference, and delivers full voltage to the motor, consuming no power and generating no heat. And it doesn't exist. Nevertheless, if I were designing this robot now I would use H-bridge drivers, probably the ubiquitous L293D. At the time, things were not so clear cut. L293Ds could be bought, but I wasn't sure they would handle the current or whether they would run without complicated cooling. Bigger chips were probably available too, but not so easy to find and relatively expensive. Bear in mind, also, the intention to build the robot, as far as possible, from stuff I had lying around or could salvage.
Circuit (a) is about as simple as electronic motor control gets. It can be used in a linear fashion with a varying dc input, in which case the transistor could get quite warm and might need a good heatsink, or it can be used with a pwm input, in which case the transistor will be either hard on or hard off for most of the time and should run cooler. The addition of a two-pole changeover relay, in circuit (b), allows us to reverse the direction of rotation, so we have a bi-directional, variable speed motor controller.
Suitable pcb mounting relays are probably not that easy to source, and if I had needed to buy them I would probably have gone with the H-bridge instead. However, I was able to salvage suitable relays from an old circuit board, and I had the rest of the components, so circuit (b) above is the one I used. I designed a pcb, built two of them, and they worked.
A shortcoming with the motor controllers, however, was that when the drive was switched off the robot didn't stop immediately but rolled to a halt. In a robot using a bump detector, this is not good. If you are going to detect objects by running into them, then you really want the robot to stop pretty much immediately when it encounters an obstacle, so some form of braking was needed.
The right-hand part of circuit (c) may look a bit like half an H-bridge, but it's not. When the input is low, transistor Q2 is off, Q4 (the TIP121) is on and the motor runs in whichever direction is determined by the relay. When the input is high, Q2 is on and Q4 is off, so there is no drive to the motor. Q3, however, is on and applies a low resistive load to the motor which results in dynamic braking. I made two of these to replace the original motor controllers. They are the ones you can see in the photograph, fitted to the rear of the robot, and they are very effective.
The pillars above the level of the circuit boards, by the way, were part of an expansion in phase two, described later, which was never completed.
The braking issue does raise a question to which, I confess, I still do not know the answer. With pwm, during the on part of the cycle, you drive the motor with the maximum voltage available. But what is supposed to happen during the off part of the cycle? There are two options: you either let the motor freewheel, or you apply braking. Braking is inefficient, converting precious battery power to heat, but at least you are in control of what is happening. If you let your vehicle freewheel then you are in the hands of the gods. Friction and other losses will slow it down, while inertia (don't forget the weight of the chassis, the motors, and all those batteries, etc) will tend to keep it going. And while inertia (probably) will affect each side of your drive equally, friction almost certainly won't. With non-precision engineered drive trains there is likely to be more drag on one side than the other.
Some day I may set up an experiment to sort this out. My instinctive preference is for run/brake/run, but clearly the pwm frequency must be kept high to avoid juddering, especially at low speeds. I don't know the answer, and if anyone reading this does, or has thoughts on the matter, feel free to get in touch.