Sat Mar 26, 2016 9:34 am
First I should say I am very new to Raspberry Pi and electronics so I have been experimenting to see what is and isn't possible.
Due to a desire to build a complex robot and because the RasPi does not have an unlimited number of pins I thought that using the Adafruit 16 channel servo controller and driver would leave me plenty of scope for many servo's and motors without using up all my GPIO pins.
I have successfully managed to drive 2 servo's, however I found the instructions somewhat complex and as soon as I started to experiment I got some quite unexpected results. To shed some light on what was happening I purchased a cheap USB oscilloscope so I could see on screen exactly what output I was getting from the PWM controller.
Now if I want to drive servo's I have to use a 50Hz frequency, and 50Hz may not be the best frequency for controlling DC motors but as this can only be set once on the board I am stuck with it. The board does support 40Hz to 1000Kz and with a little experimenting I found that it really does not make too much difference to the power output or the current used.
To hook up the DC motors I used an L293D H-Bridge controller, this requires 3 inputs to control a DC motor (forwards, reverse and enable). Manual testing showed that this works so then I started pulsing the enable pin on and off using the Pi and this controlled the speed of the motor.
So armed with this knowledge I hooked up the servo driver PWM pin only to the enable pin of the L293D, now when I set the PWM frequency and pulse length it directly controls the speed of each motor and if I set the PMW channel to off the motor stops. This means that I now only need to use 2 GPIO pins or each motor (forward and reverse) with the enable pin (speed) now controlled by the servo board.
The servo board uses a the notion of ticks to control the pulses so each cycle is measured as 4096 ticks (0 to 4095), this means to set a particular pulse length you need to specify the tick on which to send the signal high and the tick on which to send the cycle low. The actual length of a tick varies based upon the frequency used. To make more sense of this I manually calculated and then wrote code to replicate my calculations and then tested the results on an oscilloscope until I got it right.
I wrote the following code to allow me to set the speed as a pertcentage:-
def pulse_width(duty_rate): # enter between 1 and 100, although in practice you will probably need to start at about 20
cycle_length = float(1) / frequency
tick_length = float(cycle_length) / 4096
off_tick = 4096 * (duty_rate/100)
if off_tick > 4095:
off_tick = 4095 # make sure the maximum pulse value is not exceeded
return int(off_tick)
Armed with this code I can now control the speed of each motor by just setting the percentage of maximum I would like.
from Adafruit_PWM_Servo_Driver import PWM
power_percent = float(25) # set to 25%
off = pulse_width(power_percent) # send the percentage to get the off tick
pwm = PWM(0x40) # initialize PWM board (this address may vary on your Pi)
pwm.setPWMFreq(50) # sets frequency to 50Hz
pwm.setPWM(15, 0, off) # set channel 15 to go high at tick 0 and to go low at the off tick
High ___
| |
_______________| |
0 4095
At 50Hz 0 to 4096 is one 50th of a second, at 25% the PWM will stay low (output nothing) for three quarters of a cycle and then go high (output a signal) for one quarter of the cycle (one quarter of one 50th of one second)
So if you set the percentage at 100 (100%) the off tick will be 4095 so for each cycle the power will come on at 0 and go off at 4096, this means the power will be on for 100% of each cycle, therefore you get full power, equally 50% will give a pulse that is half of the cycle so you get half power. The power is pulsed 50 times a second (50Hz).
At all the frequencies this board is capable of (40Hz to 1000Hz) you will find that the motors will output a whine due to the frequency of the pulse. I believe that if you want to eliminate this whine you will have to use frequencies that fall outside of the range of human hearing but as this board cannot generate frequencies that high you would need to find another solution.
I hope that my struggles in learning how this works will help others in my position.