In my previous post I talked about modifying the gearbox of a continuous servo motor so that it span faster, albeit with lower torque. Since then I have been fighting with a new issue that was proving to be a show stopper. The issue is demonstrated in this video:
As you can see, when I heat the servo with a hair drier, it begins to spin and then when I blow on it, the spinning stops. This is an issue because when the motor is used it gets hot and then I am unable to stop the motor and because there is no feedback, the microcontroller has no way of knowing that the motor has not stopped.
Continuous servos are controlled by sending pulses on the control wire every 20ms. A pulse of 1500us tells the servo to stay still. This is called the “neutral postition”. Longer or shorter pulses tell the servo to turn one way or the other at a speed proportional to the variation from 1500us. However this value of 1500us can be varied by trimmed by adjusting the potentiometer inside the servo.
My first solution was to take the servo circuit board outside of the servo to increase airflow so that the electronics would not get so hot – this definitely decreased the effect but not enough to be reliable.
My first guess was that the increase in temperature was causing the value of the potentiometer to shift slightly so that the neutral position shifts up or down and therefore when I send 1500us pulses the motor moves as this is greater or less than the neutral position. However I measured the voltage on the middle pin of the potentiometer on my oscilloscope as I heated the servo expecting the voltage to drift, but it did not. Therefore my best guess is that the servo controller chip is actually getting hot and this is in someway affecting its decision. It seemed like I would need to find a new servo.
It occurred to me however that instead of sending pulses of 1500us, maybe if I sent no pulses at all the servo would do nothing? This makes sense, but when I tried to send no pulses the servo span faster than ever!
To explain this, I first need to explain a little about how the pulses are generated by the microcontroller. The microcontroller has a hardware timer in it that repeatedly counts from bottom (zero) to top (user defined) and back to bottom. Therefore with a clock of 1MHz and a TOP value of 20000, the timer will complete a loop every 20ms. Each time the timer resets, it sets the output pin high. I also define a COMPARE value. When the timer reaches the COMPARE value, it sets the pin low. Therefore I can control the length of my pulse by changing this value. A COMPARE of 1500 will send a pulse of 1500us. Therefore when I set COMPARE to zero, you would expect no pulse at all but I was actually getting a 1us pulse which is enough to tell the servo to spin very quickly!
This is what I missed in the datasheet and explains the spike:
The extreme values for the OCR1x (COMPARE) Register represents special cases when generating a PWM waveform output in the fast PWM mode. If the OCR1x (COMPARE) is set equal to BOTTOM (0x0000) the output will be a narrow spike for each TOP+1 timer clock cycle.
However there are two other was to stop the pulses. I can either pause the timer, or disconnect the timer from the pin. Stopping the timer is a messy solution – if I stop it when the pulse is high it stays high and we get a very long pulse. Disconnecting the timer from the pin is a much neater solution.
From the diagram you can see that if I clear COMnx1 and COMnx0 then the pin will be controlled by the GPIO rather than the timer (waveform generator) and I can therefore use this to set the pin as high impedance – no more pulses. Then when I need the pulses again I set the COM bits correctly and the timer will again be connected to the pin.
This solution works and is a neat solution that means no matter how much the neutral position of the servo may shift, it will never start spinning unexpectedly.