Skip to content

A library for controlling servos through the PWM interface of the Raspberry Pi Pico microcontroller in MicroPython.

License

Notifications You must be signed in to change notification settings

TTitanUA/micropython_servo_pdm

Repository files navigation

pypi version shield pypi downloads per month shield

Servo PDM Continuous

A library for controlling servos through the PWM interface of the Raspberry Pi Pico microcontroller in MicroPython.

Library features:

  • Rotate by specified angle
  • Smooth change of the angle of rotation
  • Cancel hold angle
  • Ability to use the smooth-servo library to change the smooth start and stop algorithm
  • All pending work happens in the background, with two processing options:
    • Using an asyncio task (recommended)
    • Interrupt timer

If you don't need all the functionality listed above, then you should take a look at the micropython-servo library. It is much smaller and better suited for simple tasks.

The following materials were used in the development of the library:

Compatibility

  • MicroPython 1.19.1
  • Raspberry Pi Pico

On the hardware above the library has been tested and works correctly.

ATTENTION

You use this module at your own risk. I am new to MicroPython programming. So there may be nuances that I did not take into account. If you notice an error or have suggestions for improvement, please write to Issues.

Installation

  • Install the library via pip (Thonny -> Manage Packages) by name micropython-servo-pdm
  • Or manual installation:
    • Download library from GitHub
    • take the micropython_servo_pdm folder from the archive.
    • upload to the root of the microcontroller or to the lib folder.

If you want to play around with the logic of the library, then the 2nd installation option is preferable. :)

Initialization

Initializing the base library

from machine import Pin, PWM
from micropython_servo_pdm import ServoPDM

# create a PWM servo controller (21 - pin Pico)
servo_pwm = PWM(Pin(21))

# Set the parameters of the servo pulses, more details in the "Documentation" section
freq = 50
min_us = 500
max_us = 2500
max_angle = 180
min_angle = 0

# create a servo object
servo = ServoPDM(pwm=servo_pwm, min_us=min_us, max_us=max_us, freq=freq, max_angle=max_angle, min_angle=min_angle)

After that, basic methods of controlling the servo will be available to you, which do not require pending tasks.

To access additional methods that require deferred execution, you need to initialize one of the child classes. Depending on which of the ways you prefer to handle pending tasks:

Using the uasyncio library

This is the best option for most projects.

from machine import Pin, PWM
from micropython_servo_pdm import ServoPDMRP2Async

# create a PWM servo controller (21 - pin Pico)
servo_pwm = PWM(Pin(21))

# Set the parameters of the servo pulses, more details in the "Documentation" section
freq = 50
min_us = 500
max_us = 2500
max_angle = 180
min_angle = 0

# create a servo object
servo = ServoPDMRP2Async(pwm=servo_pwm, min_us=min_us, max_us=max_us, freq=freq, max_angle=max_angle, min_angle=min_angle)

Using timer interrupts

You can read more about timers here For Raspberry Pi Pico here Be careful, although this is the easiest option, it is not optimal. Since the handling of servo events occurs in a timer interrupt, other interrupts will be delayed.

from machine import Pin, PWM
from micropython_servo_pdm import ServoPDMRP2Irq

# create a PWM servo controller (21 - pin Pico)
servo_pwm = PWM(Pin(21))

# Set the parameters of the servo pulses, more details in the "Documentation" section
freq = 50
min_us = 500
max_us = 2500
max_angle = 180
min_angle = 0

# create a servo object
servo = ServoPDMRP2Irq(pwm=servo_pwm, min_us=min_us, max_us=max_us, freq=freq, max_angle=max_angle, min_angle=min_angle)

Documentation

A little about PDM

PDM(pulse-duration modulation) is a process of power control by pulsing the power consumer on and off. By Wikipedia® In our case, it is used to control the servo. By the time of the pulse, you can set the position of the servo shaft. ATTENTION: Unlike PWM, the control is not based on frequency, but on the duration of the pulse. You can read more here (with pictures): wiki.amperka.ru

For the correct operation of the servo, we need to set the following parameters:

  • freq - pulse frequency, for analog servos 50 Hz. For digital 300 Hz or more.
  • min_us - minimum pulse time at which the servo goes to the min_angle point.
  • max_us - maximum pulse time at which the servo goes to the max_angle point.
  • min_angle - minimum servo rotation angle.
  • max_angle - maximum servo rotation angle. It should be noted that the parameters min_angle and max_angle set the working area of the servo. Those. if the servo can rotate from 0 to 180 degrees, then it is not necessary to set min_angle=0, max_angle=180, it could be: min_angle=-90, max_angle=90, min_angle=180, max_angle=0 or so on.

Where can I get these parameters for a specific servo? It all depends on the manufacturer. But in most cases they are specified in the documentation. But there may also be inaccuracies, for example, there is a drive MG90S the documentation states that the minimum pulse time is ~1ms, and the maximum is ~2ms. But in practice it is 0.5ms and 2.5ms (actually 0.35ms and 2.65ms, but these are extreme points outside the operating range of 180 degrees). So I recommend checking these parameters manually using the set_duty method. How to do manual configuration is in the examples folder the file manual_config.py and encoder_config.py.

List of parameters for servos:

  • MG90S - min_us=500, max_us=2500, freq=50, min_angle=0, max_angle=180
  • SG90 - min_us=600, max_us=2500, freq=50, min_angle=0, max_angle=180
  • MG995 - min_us=500, max_us=2400, freq=50, min_angle=0, max_angle=180

PLEASE: If you find parameters for a servo that are not listed, submit them to me via issue.

ServoPDM constructor parameters

ServoPDMRP2Async and ServoPDMRP2Irq inherit it and have the same parameters

Parameter Type Default Description
pwm PWM None PWM controller
min_us int 1000 Minimum pulse time
max_us int 9000 Maximum pulse time
min_angle int 0 Minimum rotation angle
max_angle int 180 Maximum rotation angle
freq int 50 Pulse frequency
invert bool False Direction inversion
  • pwm - PWM controller object.
  • min_us - Minimum pulse time (duty cycle) More.
  • max_us - Maximum pulse time (duty cycle) More
  • min_angle, max_angle - Conditional range of servo operation. You can set any values depending on your tasks and the capabilities of the servo.
  • freq - Pulse frequency, for analog drives it is 50. Digital drives are usually 300 or more.
  • invert - Invert the direction of the servo. If True then the servo will rotate in the opposite direction.

ServoPDM base class methods

  • set_duty(duty_us: int) - Sets an arbitrary value of the pulse duration in microseconds, from 0 to (1000 // freq) * 1000. This method is intended for manual search of the minimum and maximum duty cycle values. More
  • set_angle(angle: int) - Sets the angle of the servo, in the range min_angle < angle < max_angle (or max_angle < angle < min_angle if min_angle > max_angle).
  • release() - Sets the pulse duration to 0, thus disabling position holding by the servo.
  • deinit() - Disables PWM generation.

ServoPDMRP2Async and ServoPDMRP2Irq class methods

Well, one method, to be precise :).

  • move_to_angle(...) - Smoothly moves the servo to the specified angle.
Parameter Type Default Description
angle Int None End angle of rotation
time_ms Int None Move time
start_smoothing type(ServoSmoothBase) SmoothLinear Ease class to be used for movement
callback callable None The function that will be called after the end of the command.

Slowdowns

To control slowdowns, you can use the ServoSmoothBase classes and its descendants. This library only has SmoothLinear linear deceleration, if you need more, install the smooth-servo library. An example of using built-in easing:

from machine import Pin, PWM
from micropython_servo_pdm import ServoPDMRP2Async, SmoothLinear

# create a PWM servo controller (21 - pin Pico)
servo_pwm = PWM(Pin(21))

# Set the parameters of the servo pulses, more details in the "Documentation" section
freq = 50
min_us = 500
max_us = 2500
max_angle = 180
min_angle = 0

# create a servo object
servo = ServoPDMRP2Async(pwm=servo_pwm, min_us=min_us, max_us=max_us, freq=freq, max_angle=max_angle, min_angle=min_angle)

# Повернуть сервопривод до отметки в 50 градусов за 2 секунды используя линейное замедление. После вывести в консоль "callback cv"
servo.move_to_angle(50, 2000, SmoothLinear, callback=lambda: print("callback move_to_angle"))

Details about the parameters and types of slowdowns can be found in the smooth_servo documentation.

Examples

Usage examples can be found in the examples folder.

Bugs and feedback

If you find bugs, create issue The library is open for further development and your pull requests!

About

A library for controlling servos through the PWM interface of the Raspberry Pi Pico microcontroller in MicroPython.

Topics

Resources

License

Stars

Watchers

Forks