Several years ago, HackSpace magazine put out a book on the Raspberry Pico controller. I’ve been doing several projects for our local model railroad club using the Pico. I have also created some training for the membership to get them up-to-speed on some common interfaces. The next few posts will be about the chapters I have written to extend the material in the Getting started with MicroPython on the Raspberry Pi Pico book. If there are any overlaps in the material covered (either from that book or from some of the previous posts on this site) they have been updated and Americanized. I plan to put out each of the extension chapters and appendices, so others can review them without downloading the entire book I put together for the class. The cod e in these examples are written in MicroPython.
This focuses material on the 9G servo, but the concepts are the same with others. This servo can rotate approximately 180 degrees (90 in each direction). The ‘9G’ means that the servo weighs 9 grams.
What is a servo motor?
A popular hobby market motor, the servo motor can push or rotate an object with great precision and is thus quite useful for projects that require precise control of angular or linear position, velocity, and acceleration. If you need to rotate and object at some specific angles or distance, then you use a servo motor, which in turn is made up of a simple motor running through the servo mechanism. The servo mechanism comprises three parts; first is the controlled device, second is the output sensor and lastly, the feedback system. In this closed loop system, a positive feedback system is used to control motion and the final position of the shaft. The device is controlled by a feedback signal produced by comparing output signal and reference input signal.
The model of your servo is:
Figure 11-1 – Servo wiring diagram
Where the voltage is carried on the red wire, the ground on the brown wire and the PWM (pulse-width modulation) signal is on the orange. Other sizes and brands of servos will have other wiring colors and voltages. A good in-depth overview of PWM is located at: Generating PWM Signals Using the Raspberry Pi Pico another good article is The Pico In MicroPython: PWM (i-programmer.info)
Using a servo motor with a Raspberry Pi Pico
First, we need to wire up the servo as shown in the following illustration:
Figure 11-2 – Servo breadboard diagram
Now we need a short program that will run the servo through its range:
#imports
from machine import Pin,PWM
import utime
#constants
MIN = 1000000
MAX = 3000000
NumberOfSteps = 20
SERVO_GPx=15
#variables
increment = int((MAX-MIN)/NumberOfSteps)
pwm = PWM(Pin(SERVO_GPx))
pwm.freq(50)
#main loop
while True:
x = range(0,NumberOfSteps)
movement = MIN
pwm.duty_ns(MIN)
utime.sleep(1)
for n in x:
movement = movement + increment
print("movement ",movement)
pwm.duty_ns(movement)
utime.sleep(0.02)
You’ll notice there are two constants indicating the minimum (MIN) position, the maximum (MAX) position and the mid position of the servo. We have another constant for the number of steps to divide the range of motion. We then create a pin configured as a PWM and set its initial frequency to 50.
Then in a while True loop, we set its initial position to min. Next, we wait for a second, and increment through the range. There is a pause of 0.02 seconds since it takes a little bit of time for the servo to respond.
Save the program as 11-1 Servo.py and run it.
Lesson challenge – Change the number of positions to a different number and watch what happens. What if you only wanted to move 45 degrees, how would you do that? How about trigger the servo based on a switch being pressed? How could you make a clock?
Using a servo motor and limit switches
Although servos generally rotate the same amount each time, it may be necessary to install a limit switch in your model. This will tell the Pico that its rotation has taken place as far as the servo should go and to stop the rotation. This next program will take rotate the servo until a limit switch is triggered, telling your program to stop the rotation.
In this case, I added a limit switch on the end of the breadboard and held the servo so it would touch the switch before it reached its limit. Remember that since we are using a pull down, we need to connect the switch between the power bus and the pin 14.
Here is the code:
#imports
from machine import Pin,PWM
import utime
#constants
MIN = 1000000
MAX = 3000000
NumberOfSteps = 20
SERVO_GPx=15
LIMIT_GPx=14
#variables
pressed = False
limitSwitch = machine.Pin(LIMIT_GPx, machine.Pin.IN, machine.Pin.PULL_DOWN)
increment = int((MAX-MIN)/NumberOfSteps)
pwm = PWM(Pin(SERVO_GPx))
pwm.freq(50)
# interrupt handler
def limit_handler(pin):
global pressed
if not pressed:
pressed=True
print("limit reached")
#main loop
while True:
x = range(0,NumberOfSteps)
movement = MIN
pwm.duty_ns(MIN)
utime.sleep(1) # let the physical system catch up
pressed = False
limitSwitch.irq(trigger=machine.Pin.IRQ_RISING, handler=limit_handler)
for n in x:
movement = movement + increment
print("movement ",movement)
pwm.duty_ns(movement)
utime.sleep(0.2)
if (pressed):
break
The actual wiring understanding is an exercise for the student.
Lesson challenge – How would you make your servo run based on pressing a button? After all, that is an example what you would do with any animated display. How about a servo with variable resistors to control the lower and upper limit of movement?