This guide will help you get started with a PiicoDev® Servo Driver module. We'll take a tour of the module and walk through some examples to drive common servos.
Servo motors are integrated motors that contain their own power circuitry and controller. You just need to provide a stable power supply and a control signal. They're generally available in two flavours:
- Positional (aka. "angular"); these can be set to hold a specific angle and are really useful for creating exact angular movements like opening a gate or as a joint in a robotic arm.
- Continuous Rotation; these behave like a motor with direction and speed control.
Servos have convenient mounting tabs and a splined output shaft that couples to one of the "servo horns" that are often supplied. You can even get special servo wheels! Mount one of these accessories to your servo before starting - it's much easier to see what's going on that way!
Contents:
- Hardware
- Required Hardware
- Connect a Servo to the Servo Driver
- Connect the Servo Driver to your Dev. Board
- Setup Thonny
- Download / Install PiicoDev Modules
- Example: Angular Servo
- Example: Continuous Rotation Servo
- Example: Connecting Multiple Servo Drivers Together
- Conclusion
To get started - select your dev. board below.
Hardware
Required Hardware
To follow along you'll need:
- A Raspberry Pi Pico (with Soldered Headers) or Pico W (with Soldered Headers)
- A PiicoDev Servo Driver
- A PiicoDev Expansion Board for Raspberry Pi Pico
- A PiicoDev Cable
- A power supply with USB-C connector. This could be:
- A complete Power Supply with USB-C connector - I'll use this in this article.
- Portable option: a USB power bank and USB-C cable.
- At least one servo. In this guide I'll use two different models: an FS90 (positional) and FS90R (continuous rotation) servo.
- (Optional) A PiicoDev Platform will keep everything mounted securely.
Connect a Servo to the Servo Driver
Address Switch (ASW)
Each PiicoDev Servo Driver has an Address Switch labelled ASW, ensure both poles of this switch are in the OFF position.
Connect a Servo to Channel 1
The PiicoDev Servo Driver has four servo control channels labelled 1-4. For now we'll connect a servo to Channel 1. Servos usually come with a standard 3-pin connector with connections for Ground, Power, and Signal. On the Servo Driver these are labelled -, + and sig respectively. Make sure you connect your servos correctly as they may be damaged if you plug them in the wrong way around. What's more, many manufacturers use different colours for their servo wires. In general, the darkest colour is the Ground wire. You can also identify the Ground pin on the servo connector - it is indicated by a chamfer (or "notch") on the connector.
Apply Power
Servos are very power-hungry, making the PiicoDev Servo Driver a High Power PiicoDev Module. The regular PiicoDev bus and cables can't provide enough current to drive motors, so we will need to connect an external power supply via one of the USB-C connectors. This supply should be capable of supplying 0.7 Amps per small servo connected, and 2.4 A for a single large servo.
Connect the Servo Driver to your Dev. Board
Plug your Pico into the expansion board. Make sure it is plugged in the correct orientation - Pin 0 on the expansion board should be to the left of the Pico's USB connector.
Connect your Servo Driver to the expansion board with a PiicoDev Cable.
Required Hardware
To follow along you'll need:
- A Raspberry Pi single board computer (Pictured: Raspberry Pi 4 Model B)
- A PiicoDev Servo Driver
- A PiicoDev Adapter for Raspberry Pi
- A PiicoDev Cable (100mm or longer is best for Raspberry Pi)
- A power supply with USB-C connector. This could be:
- A complete Power Supply with USB-C connector - I'll use this in this article.
- Portable option: a USB power bank and USB-C cable.
- At least one servo. In this guide I'll use two different models: an FS90 (positional) and FS90R (continuous rotation) servo.
- (Optional) A PiicoDev Platform will keep everything mounted securely.
Connect a Servo to the Servo Driver
Address Switch (ASW)
Each PiicoDev Servo Driver has an Address Switch labelled ASW, ensure both poles of this switch are in the OFF position.
Connect a Servo to Channel 1
The PiicoDev Servo Driver has four servo control channels labelled 1-4. For now we'll connect a servo to Channel 1. Servos usually come with a standard 3-pin connector with connections for Ground, Power, and Signal. On the Servo Driver these are labelled -, + and sig respectively. Make sure you connect your servos correctly as they may be damaged if you plug them in the wrong way around. What's more, many manufacturers use different colours for their servo wires. In general, the darkest colour is the Ground wire. You can also identify the Ground pin on the servo connector - it is indicated by a chamfer (or "notch") on the connector.
Apply Power
Servos are very power-hungry, making the PiicoDev Servo Driver a High Power PiicoDev Module. The regular PiicoDev bus and cables can't provide enough current to drive motors, so we will need to connect an external power supply via one of the USB-C connectors. This supply should be capable of supplying 0.7 Amps per small servo connected, and 2.4 A for a single large servo.
Connect the Servo Driver to your Dev. Board
Mount the Adapter onto your Pi's GPIO. Make sure it is plugged in the correct orientation - An arrow on the Adapter will point to the Pi's Ethernet connector (on a Pi 3 the Ethernet connector and USB ports are swapped.)
Connect your Servo Driver to the Adapter with a PiicoDev Cable.
Required Hardware
To follow along you'll need:
- A micro:bit v2
- A PiicoDev Servo Driver
- A PiicoDev Adapter for micro:bit
- A PiicoDev Cable
- A power supply with USB-C connector. This could be:
- A complete Power Supply with USB-C connector - I'll use this in this article.
- Portable option: a USB power bank and USB-C cable.
- At least one servo. In this guide I'll use two different models: an FS90 (positional) and FS90R (continuous rotation) servo.
- (Optional) A PiicoDev Platform will keep everything mounted securely.
Connect a Servo to the Servo Driver
Address Switch (ASW)
Each PiicoDev Servo Driver has an Address Switch labelled ASW, ensure both poles of this switch are in the OFF position.
Connect a Servo to Channel 1
The PiicoDev Servo Driver has four servo control channels labelled 1-4. For now we'll connect a servo to Channel 1. Servos usually come with a standard 3-pin connector with connections for Ground, Power, and Signal. On the Servo Driver these are labelled -, + and sig respectively. Make sure you connect your servos correctly as they may be damaged if you plug them in the wrong way around. What's more, many manufacturers use different colours for their servo wires. In general, the darkest colour is the Ground wire. You can also identify the Ground pin on the servo connector - it is indicated by a chamfer (or "notch") on the connector.
Apply Power
Servos are very power-hungry, making the PiicoDev Servo Driver a High Power PiicoDev Module. The regular PiicoDev bus and cables can't provide enough current to drive motors, so we will need to connect an external power supply via one of the USB-C connectors. This supply should be capable of supplying 0.7 Amps per small servo connected, and 2.4 A for a single large servo.
Connect the Servo Driver to your Dev. Board
Plug your micro:bit into the Adapter, making sure the buttons on the micro:bit are facing up.
Connect your Servo Driver to the Adapter with a PiicoDev Cable.
Setup Thonny
Download / Install PiicoDev Modules
To work with PiicoDev hardware, we need to download some drivers. The drivers provide all the functions to easily connect and communicate with PiicoDev hardware. Select your dev board from the options above.
We will need these files to work with the PiicoDev Servo Driver:
- Save the following files to your preferred coding directory - In this tutorial, we save to My Documents > PiicoDev.
- Download the PiicoDev Unified Library: PiicoDev_Unified.py (right-click, "save link as").
- Download the device module: PiicoDev_Servo.py (right-click, "save link as")
- Upload the files to your Pico. This process was covered in the Setup Thonny section.
The PiicoDev Unified Library is responsible for communicating with PiicoDev hardware, and the device module contains functions for driving specific PiicoDev devices.
We will need these files to work with the PiicoDev Servo Driver:
- Save the following files to your preferred coding directory - In this tutorial, we save to My Documents > PiicoDev.
- Download the PiicoDev Unified Library: PiicoDev_Unified.py (right-click, "save link as").
- Download the device module: PiicoDev_Servo.py (right-click, "save link as")
- Upload the files to your micro:bit. This process was covered in the Setup Thonny section.
The PiicoDev Unified Library is responsible for communicating with PiicoDev hardware, and the device module contains functions for driving specific PiicoDev devices.
Example: Angular Servos
This example drives a servo to three angles (0°, 90°, 180°) sequentially, then smoothly sweeps the servo using a for loop.
The controller is first initialised with the PiicoDev_Servo_Driver() initialisation function, which returns a controller object.
Next, the servo is 'attached' to the controller with PiicoDev_Servo() which includes arguments for:
- controller - the controller object to attach a servo to
- channel - the channel number as indicated on the Servo Driver Module
- min_us (optional, default: 600) - the minimum expected pulse width in microseconds
- max_us (optional, default: 2400) - the maximum expected pulse width in microseconds
- degrees (optional, default 180) - the angular range of the servo in degrees. Generally 180°, though some servos may allow for more.
You can choose to omit values for min_us, max_us and degrees. If omitted, generally safe default values will be used.
With the controller initialised and the servo attached, driving the servo is as easy as setting the .angle attribute to some value 0->180.
# Drive an angular servo with generally safe-to-use default properties from PiicoDev_Unified import sleep_ms from PiicoDev_Servo import PiicoDev_Servo, PiicoDev_Servo_Driver # Initialise the Servo Driver Module controller = PiicoDev_Servo_Driver() # Simple setup: Attach a servo to channel 1 of the controller with default properties servo = PiicoDev_Servo(controller, 1) # Customised setup - Attach a servo to channel 1 of the controller with the following properties: # - min_us: the minimum expected pulse length (microsecconds) # - max_us: the maximum expected pulse length (microsecconds) # - degrees: the angular range of the servo in degrees # Uncomment the line below to use customised properties # servo = PiicoDev_Servo(controller, 1, min_us=600, max_us=2400, degrees=180) # Step the servo servo.angle = 0 sleep_ms(1000) servo.angle = 90 sleep_ms(1000) servo.angle = 180 sleep_ms(1000) servo.angle = 0 sleep_ms(2000) # Sweep the servo slowly 0->180° for x in range(0,180,5): servo.angle = x sleep_ms(40)
Example: Continuous Rotation Servos
Continuous rotation servos are set up in a similar fashion to the previous example - we can simply ignore the degrees attribute.
To drive a continuous rotation servo, we use the .speed attribute which accepts values between -1.0 (full-speed reverse) and 1.0 (full-speed forward). A value of 0.0 is stop.
# Drive a Continuous Rotation (a.k.a. 360 degree) servo. from PiicoDev_Unified import sleep_ms from PiicoDev_Servo import PiicoDev_Servo, PiicoDev_Servo_Driver controller = PiicoDev_Servo_Driver() continuous_servo = PiicoDev_Servo(controller, 1, midpoint_us=1500, range_us=1800) # Connect a 360° servo to channel 2 continuous_servo.speed = 1 # fast sleep_ms(1000) continuous_servo.speed = 0.2 # slow sleep_ms(1000) continuous_servo.speed = -0.2 # slow reverse sleep_ms(1000) continuous_servo.speed = -1 # fast reverse sleep_ms(1000) continuous_servo.speed = 0 # stop
Technical Aside: Tuning the Zero-Point
You may notice your servo does not completely stop when .speed=0 - this is normal for continuous rotation servos as they don't have a feedback loop like a positional servo. There are two paths forward here:
Some servos have a tuning potentiometer, adjust this with a screwdriver until the servo stops rotating.
For servos without a tuning pot, you can use some additional arguments: midpoint_us and range_us. These do the same job as min_us and max_us which is to set the pulse range of the servo, it's just a little simpler for tuning continuous servos to think in terms of midpoint.
- midpoint_us will set the midpoint pulse in milliseconds. Try a starting value of 1500 and make adjustments until the servo is stopped when .speed=0
- range_us sets the range of pulse widths to send. It's the same as => max_us - min_us = range_us
Note: Both midpoint and range must be set during initialisation. It is not enough to specify just one.
For example, perhaps a servo does not have a tuning pot and I've found empirically that the midpoint is actually 1520us. The initialisation for this servo could look something like this:
continuous_servo = PiicoDev_Servo(controller, 2, midpoint_us=1520, range_us=1800)
Example: Connecting Multiple Servo Drivers Together
It's possible to connect up to four PiicoDev Servo Driver Modules together on the same PiicoDev bus to drive a total of 16 servos. For this to work we need to satisfy some conditions:
- Each Servo Driver has a unique Address Switch (ASW) setting
- Each Servo Driver is initialised (in code) with its corresponding ASW setting
- Each Servo Driver has an adequate power supply
Address Switch ASW
This is the easy part - use a fine pen or similar to set the 2-position switch to a unique combination. Since there are two switch positions, there are four unique switch combinations.
Initialisation Code
We need to provide the ASW configuration when we initialise the Servo Driver. This is an additional argument asw=[#,#] where we encode the switch positions. For example, to initialise a Servo Driver with the following switch positions ASW:1 = ON, ASW:2 = OFF, we would use:
controller_B = PiicoDev_Servo_Driver( asw=[1,0] )
Power Supply
Each Servo Driver needs adequate power to drive its connected servos. The amount of power depends on the number of servos that will be running at the same time, their size, and how much torque they're expected to produce. A rule of thumb is that each small servo needs about 0.8A when moving, and larger servos need as much as 2.5A to move. Depending on your project, you may only need a single servo active at any one time, or all four channels firing at the same time - and this will drastically change how you power each servo module. For projects with multiple Servo Drivers but no simultaneous servo activity, you may daisy-chain power between Servo Modules using a USB-C cable. For high-power projects, it might be more appropriate to power each Servo Driver individually.
We found that even though this example is driving eight servos, the hardware only draws about 1.1A, since the servos are not delivering high torque and are turning very slowly.
Controlling Eight Servos across Two Servo Drivers
The demonstration shown towards the end of the tutorial video shows off a nice wavy demonstration using eight servos connected to two servo drivers. The complete code is listed below for reference. Of course, this example can be picked apart and repurposed as you see fit.
# Drive eight angular servos with generally safe-to-use default properties # This requires two PiicoDev Servo Drivers # Set all the ASW switches OFF on the first Driver (controller_A) # Set ASW:1 ON, ASW:2 OFF for on the second Driver (controller_B) from math import sin from PiicoDev_Unified import sleep_ms from PiicoDev_Servo import PiicoDev_Servo, PiicoDev_Servo_Driver # Initialise the Servo Driver Module controller = PiicoDev_Servo_Driver() # Initialise the Servo Driver Module controller_A = PiicoDev_Servo_Driver(asw=[0,0]) controller_B = PiicoDev_Servo_Driver(asw=[1,0]) # Setup four servos, each on a different channel of controller_A servo1 = PiicoDev_Servo(controller_A, 1) servo2 = PiicoDev_Servo(controller_A, 2) servo3 = PiicoDev_Servo(controller_A, 3) servo4 = PiicoDev_Servo(controller_A, 4) # Setup four more servos, each on a different channel of controller_B servo5 = PiicoDev_Servo(controller_B, 1) servo6 = PiicoDev_Servo(controller_B, 2) servo7 = PiicoDev_Servo(controller_B, 3) servo8 = PiicoDev_Servo(controller_B, 4) # Create a list we can loop through servos = [servo1, servo2, servo3, servo4, servo5, servo6, servo7, servo8] theta=0 # the control variable that drives all the servos offset = 0.5 # difference between each servo while True: for i in range(len(servos)): x = 90 + 90*sin(theta - (i+1)*0.25) # Compute a unique angle for each servo servos[i].angle = x theta += 0.1 # incrementing theta will move the servos a small amount on the next loop sleep_ms(20)
Conclusion
Motion makes a project pretty exciting, and the PiicoDev Servo Driver can bring a lot of motion. We've seen how to control angular and continuous-rotation servos, how to drive multiple servos, and how to daisy chain multiple drivers together. From here it's up to you! Perhaps you're interested in making a wheeled robot with continuous servos... Perhaps you want to add a grabby claw to your robot using angular servos! Whatever you make, show it off in the comments below!
Happy Making!