Servos are small motors with gearing that can add a high amount of torque (turning strength), and reliably turn to a precise angle. Servos such as the SG09 are small, cheap, run on low power and can rotate around 180 degrees, or a half circle. This makes them different to a normal motor which will spin round. You can commonly use this for things that need to turn by small amounts, such as a joint in a robotic arm, to lift the arm of a barrier or to steer a radio controlled car.
The SG09 only requires 3 connections two for power and one for data/control, but it does require 4.8v to operate. As the Micro:bit can only produce low current and 3v, an external battery pack is required. In the above wiring, brown is ground, red is +4.8v and orange is control. Connect a 3xAA battery pack to the two power pins and control to one of the Micro:bit pins, as shown below. Note a 4xAA battery pack is shown on the diagram.
There are a number of pages on controlling the SG09 with a Micro:bit, however none of these worked when I tried this. The servo operates by receiving pulses of 50Hz (50 pulses per second). If we divide one second by 50 pulses, we get a time of 20ms between pulses. We start our code by defining this. Next, if we write the analog value 1 to the servo, it will turn all the way to it’s clockwise limit. (If you send a 0, it does nothing.) Sending a high enough value will turn the servo the other way.
If you try a value of 150 or higher, you will feel the servo straining beyond it’s limits and you could damage it. Start with a low value for maxLimit in the following code (say 80) and gradually increase it until the motor just reaches it’s anti-clockwise limit. I found 122 to be a figure which does not strain the servo but reaches the other side.
from microbit import * servo = pin0 # Motor requires a 50 Hz signal. 1 second / 50 gives # a pulse every 20 ms. Set this as the analog period servo.set_analog_period(20) maxLimit = 122 while True: servo.write_analog(0) # Set the servo to 90 degrees - the middle sleep(500) for i in range(10,maxLimit): servo.write_analog(i) # Turn the servo to the clockwise limits, 0 degrees sleep(50)
As the servo moves between 0 and 180 degrees, and values between 1 and 122 causes this movement, we can work out what value to analog write to achieve by dividing the angle we want by 180 then multiplying this by 122. We can wrap this up in a function and then call it to move the servo to a desired angle. The below code moves the servo to its limits and back again, like a windscreen wiper.
from microbit import * servo = pin0 def servoAngle(s, a) : maxLimit = 122 # Set the values into a sensible range # 1 is the smallest value if a < 1 : a = 1 # Max limit is the highest value if a > 180 : a = 180 v = (a/180) * maxLimit s.write_analog(v) # Motor requires a 50 Hz signal. 1 second / 50 gives # a pulse every 20 ms. Set this as the analog period servo.set_analog_period(20) while True: servo.write_analog(1) sleep(1000) #servo.write_analog(122) servoAngle(servo, 180) sleep(1000)
Note that this angle is an approximation and not exact. The design specs of the servo detail exactly what sort of pulses to send for precise control. This gives a very quick and simple way of achieving something close to what we require for a lot of applications.