Mastering MicroPython PWM Servo Control

MicroPython has emerged as a powerful and user - friendly programming language for microcontrollers, enabling rapid prototyping and development of embedded systems. Pulse - Width Modulation (PWM) is a key technique used to control the speed, direction, and position of various devices, and one of the most common applications is servo motor control. A servo motor is a type of motor that can precisely control the angular position. In this blog post, we will explore the fundamental concepts of using MicroPython to control servo motors via PWM, cover usage methods, common practices, and best practices.

Table of Contents#

  1. Fundamental Concepts
  2. Hardware Setup
  3. Usage Methods
  4. Common Practices
  5. Best Practices
  6. Conclusion
  7. References

Fundamental Concepts#

Pulse - Width Modulation (PWM)#

PWM is a technique for getting analog results with digital means. A digital control is used to create a square wave, a signal switched between on and off. The ratio of on - time to the total period of the signal is called the duty cycle. By varying the duty cycle, we can control the average voltage or power delivered to a device.

Servo Motors#

Servo motors are designed to control the angular position. They usually have a control wire that receives a PWM signal. The standard PWM frequency for servo motors is around 50 Hz (a period of 20 ms). The position of the servo is determined by the pulse width of the PWM signal. For most servos, a pulse width of 1 ms corresponds to the minimum angle (usually 0°), 1.5 ms to the middle position (usually 90°), and 2 ms to the maximum angle (usually 180°).

Hardware Setup#

To control a servo motor using MicroPython, you'll need the following components:

  • A microcontroller board that supports MicroPython, such as the Raspberry Pi Pico.
  • A servo motor.
  • Power supply (Servos can draw a significant amount of current, so it's often recommended to use an external power supply rather than powering them directly from the microcontroller).

The typical wiring setup is as follows:

  • Connect the power (usually red wire) of the servo to the positive terminal of the power supply.
  • Connect the ground (usually black or brown wire) of the servo to the negative terminal of the power supply and to the ground of the microcontroller.
  • Connect the control wire (usually orange or yellow) of the servo to a GPIO pin on the microcontroller.

Usage Methods#

Basic MicroPython Code for Servo Control#

from machine import Pin, PWM
import time
 
# Create a PWM object on GPIO pin 0
pwm = PWM(Pin(0))
 
# Set the frequency to 50Hz
pwm.freq(50)
 
# Function to convert angle to duty cycle
def angle_to_duty(angle):
    # Map 0 - 180 degrees to 1 - 2 ms pulse width
    # Duty cycle is from 0 - 65535
    duty_min = 1000
    duty_max = 2000
    angle_min = 0
    angle_max = 180
    return int((angle - angle_min) * (duty_max - duty_min) / (angle_max - angle_min) + duty_min)
 
# Move the servo to 0 degrees
duty = angle_to_duty(0)
pwm.duty_ns(duty * 1000)
time.sleep(1)
 
# Move the servo to 90 degrees
duty = angle_to_duty(90)
pwm.duty_ns(duty * 1000)
time.sleep(1)
 
# Move the servo to 180 degrees
duty = angle_to_duty(180)
pwm.duty_ns(duty * 1000)
time.sleep(1)
 
# Turn off the PWM signal
pwm.deinit()

In this code:

  1. We first import the necessary modules (Pin and PWM from machine and time).
  2. Create a PWM object on a specific GPIO pin and set the frequency to 50 Hz.
  3. Define a function angle_to_duty to convert an angle to the corresponding duty cycle in nanoseconds.
  4. Move the servo to different angles (0°, 90°, 180°) and wait for 1 second between each movement.
  5. Finally, we deinitialize the PWM object to turn off the signal.

Common Practices#

Error Handling#

When working with servos, it's important to handle errors properly. For example, if the servo is blocked or overloaded, it may draw excessive current. You can use try - except blocks in your code to catch exceptions and take appropriate actions.

try:
    # Servo control code here
    pass
except Exception as e:
    print(f"An error occurred: {e}")
    # You can add code here to stop the servo or take other corrective actions

Calibration#

Servos may have slight variations in their response to PWM signals. You may need to calibrate the minimum and maximum pulse widths for your specific servo to achieve accurate positioning.

Best Practices#

Power Management#

As mentioned earlier, servos can draw a significant amount of current. It's best to use an external power supply to avoid overloading the microcontroller. Also, make sure to connect the grounds of the power supply and the microcontroller to ensure proper signal communication.

Code Modularity#

Write modular code. For example, you can create a class to encapsulate the servo control functionality. This makes the code more organized and easier to maintain.

from machine import Pin, PWM
import time
 
class Servo:
    def __init__(self, pin, freq=50, min_duty=1000, max_duty=2000):
        self.pwm = PWM(Pin(pin))
        self.pwm.freq(freq)
        self.min_duty = min_duty
        self.max_duty = max_duty
 
    def angle_to_duty(self, angle):
        angle_min = 0
        angle_max = 180
        return int((angle - angle_min) * (self.max_duty - self.min_duty) / (angle_max - angle_min) + self.min_duty)
 
    def move_to_angle(self, angle):
        duty = self.angle_to_duty(angle)
        self.pwm.duty_ns(duty * 1000)
 
    def deinit(self):
        self.pwm.deinit()
 
 
# Example usage
servo = Servo(0)
servo.move_to_angle(0)
time.sleep(1)
servo.move_to_angle(90)
time.sleep(1)
servo.move_to_angle(180)
time.sleep(1)
servo.deinit()

Conclusion#

Controlling servo motors using MicroPython and PWM is a straightforward yet powerful way to add precise motion control to your embedded projects. By understanding the fundamental concepts of PWM and servo motors, following proper hardware setup, usage methods, common practices, and best practices, you can build reliable and accurate servo - controlled systems. Whether you're working on a robotic arm, a camera pan - tilt mechanism, or any other project that requires angular positioning, MicroPython provides an accessible and efficient way to achieve your goals.

References#