Сервопривод SG90 поворачивает вал на заданный угол и удерживает его. Он нужен для поворотных камер, замков, роботов-манипуляторов и «умных» кормушек. Подключить его к Raspberry Pi проще простого: три провода, но на Raspberry Pi 5 у такого подключения есть нюанс. Обычный программный ШИМ из gpiozero даёт заметное дрожание вала, а привычная библиотека pigpio на этой плате не работает.
В статье подключим SG90 к Raspberry Pi 5, управим им через gpiozero и посмотрим, как избавиться от дрожания с помощью аппаратного ШИМ на GPIO12. Про управление сразу несколькими сервоприводами через модуль PCA9685 есть отдельная статья: SG90 и PCA9685 на Python, а сам модуль описан здесь.
Как управляется сервопривод
Угол вала задаётся шириной импульса на сигнальном проводе. Импульсы идут с частотой 50 Гц (период 20 мс):
| Ширина импульса | Угол вала (SG90) |
|---|---|
| около 0,5 мс | −90° (крайнее положение) |
| около 1,5 мс | 0° (середина) |
| около 2,5 мс | +90° (крайнее положение) |
Это типичные значения для SG90. По документации производителя номинальный диапазон 1–2 мс, а реальные экземпляры допускают чуть больше, и у каждого немного свои границы. Если вал упирается в ограничитель и «гудит», сузьте диапазон (например, до 0,6–2,4 мс).
В процентах заполнения ШИМ на частоте 50 Гц это примерно 2,5 % (−90°), 7,5 % (0°) и 12,5 % (+90°).
Что понадобится
- Raspberry Pi 5 с системой (установка Raspberry Pi OS);
- сервопривод SG90 (или подобный маленький: MG90S);
- три провода «мама–папа» или «мама–мама» (на проводах SG90 гнёзда).
Схема подключения
У SG90 три провода (цвета могут отличаться у разных производителей, но чаще всего такие):
| Провод | Назначение | Контакт Raspberry Pi 5 |
|---|---|---|
| Коричневый (или чёрный) | GND | GND, контакт 6 |
| Красный | Питание 5 В | 5V, контакт 2 |
| Оранжевый (или жёлтый) | Сигнал | GPIO12, контакт 32 |
Сигнал берём с GPIO12: это один из контактов, на которых у Raspberry Pi 5 доступен аппаратный ШИМ (его мы включим ниже). Для первых опытов с gpiozero подойдёт любой GPIO, но удобнее сразу использовать этот.
Питание сервопривода. Один SG90 без нагрузки потребляет немного, но в момент трогания и при упоре вала ток растёт до сотен миллиампер. Для одного-двух маленьких сервоприводов хватает 5 В платы (если блок питания качественный, см. питание и охлаждение). Для нескольких сервоприводов или более мощных (MG996R и т. п.) нужен отдельный источник 5 В, у которого минус соединён с GND Raspberry Pi. Если плата перезагружается при движении сервопривода, это признак просадки питания.
Что на снимке. Так выглядит собранная схема: сервопривод SG90 (синий корпус, белая качалка) и три провода от штыревого разъёма GPIO платы. На плате стоит M.2 HAT+, поэтому провода воткнуты в удлинённые штыри сверху. По фото трудно разобрать, какой провод в каком гнезде: ориентируйтесь на схему выше (питание 5 В, земля GND и сигнал GPIO12). Цвета проводов сервопривода обычно такие: коричневый или чёрный — земля, красный — питание, оранжевый или жёлтый — сигнал.
Способ 1. gpiozero (программный ШИМ)
Самый простой способ: класс AngularServo из gpiozero (библиотека установлена в Raspberry Pi OS, подробнее о ней в статье про GPIO и gpiozero). Создайте файл servo_gpiozero.py:
from time import sleep
from gpiozero import AngularServo
servo = AngularServo(
12,
min_angle=-90,
max_angle=90,
min_pulse_width=0.0005, # 0,5 мс
max_pulse_width=0.0025, # 2,5 мс
)
for angle in (0, 90, 0, -90, 0):
print("Угол:", angle)
servo.angle = angle
sleep(1)
servo.detach() # перестаём подавать импульсы, вал не удерживается
Запуск:
python3 servo_gpiozero.py
Что на снимке. Сервопривод проходит пять углов: в терминале строки Угол: 0, 90, 0, -90, 0 с паузой в секунду, и вал поворачивается следом. Перед ними выведено предупреждение PWMSoftwareFallback: To reduce servo jitter, use the pigpio pin factory. По-русски: «Чтобы уменьшить дрожание сервопривода, используйте фабрику выводов pigpio». Это не ошибка: gpiozero сообщает, что на этой плате формирует ШИМ программно. Совет про pigpio для Raspberry Pi 5 не подходит (эта библиотека на плате не работает, подробнее ниже), а дрожание убирает аппаратный ШИМ из способа 2. Предупреждение можно оставить как есть. Если оно мешает, добавьте в начало программы две строки: import warnings и warnings.simplefilter("ignore").
Запускайте программу обычным python3, без виртуального окружения: gpiozero и драйвер lgpio установлены в системе, и так они видны сразу. Если вы всё-таки работаете в окружении, созданном командой python3 -m venv env, программа остановится с ошибкой:
ModuleNotFoundError: No module named 'gpiozero'
По-русски: «Модуль gpiozero не найден». Обычное окружение изолировано от системных пакетов и не видит gpiozero. Выйдите из него (deactivate) и создайте заново с доступом к системным библиотекам:
deactivate
rm -rf ~/servo/env
python3 -m venv --system-site-packages ~/servo/env
source ~/servo/env/bin/activate
python3 servo_gpiozero.py
Параметр --system-site-packages открывает окружению пакеты python3-gpiozero и python3-lgpio из системы (проверить, что они установлены, можно командой dpkg -l | grep gpiozero). Если их нет, установите: sudo apt install python3-gpiozero python3-lgpio.
Вал должен повернуться на 0°, +90°, снова на 0°, затем на −90° и вернуться в середину. Если крайние положения не доходят до упора, расширьте диапазон min_pulse_width и max_pulse_width; если вал гудит в крайних положениях, сузьте (например, 0,0006 и 0,0024).
Метод detach() отключает сигнал: сервопривод больше не удерживает положение и не греется. Для постоянного удержания (например, поворот камеры) сигнал нужен всегда.
Когда нужно поворачивать от 0 до 180° без «отрицательных» углов, можно задать min_angle=0, max_angle=180: пересчёт диапазона gpiozero сделает сам.
Почему вал дрожит
На Raspberry Pi 5 библиотека gpiozero по умолчанию формирует ШИМ программно: через драйвер lgpio, которым управляет процессор. Импульсы получаются с небольшим разбросом по времени, и SG90 реагирует на это едва заметными подёргиваниями в точке удержания. Для поворота «туда-обратно» это незаметно, а для камеры или точной механики может мешать.
Известная библиотека pigpio с её аппаратно-таймированным ШИМ на Raspberry Pi 5 не работает: плата устроена по-другому (GPIO обслуживает микросхема RP1). Поэтому для точного сигнала используют аппаратный ШИМ.
Способ 2. Аппаратный ШИМ на GPIO12
У Raspberry Pi 5 четыре канала аппаратного ШИМ. Каналы 0 и 1 выведены на GPIO12 и GPIO13, каналы 2 и 3 на GPIO18 и GPIO19. Импульсы формирует сама микросхема, поэтому сигнал получается ровным и без нагрузки на процессор.
Шаг 1. Включаем ШИМ в конфигурации
Откройте файл конфигурации:
sudo nano /boot/firmware/config.txt
В конец добавьте строку (она включает два канала на GPIO12 и GPIO13):
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
Сохраните файл и перезагрузите плату:
sudo reboot
Шаг 2. Определяем номер ШИМ-контроллера
После перезагрузки посмотрите, какие ШИМ-контроллеры есть в системе:
ls /sys/class/pwm
cat /sys/class/pwm/pwmchip*/npwm
Что на снимке. В системе два ШИМ-контроллера, pwmchip0 и pwmchip1, и у каждого по 4 канала (4 и 4). Количество каналов у них одинаковое, поэтому по нему контроллеры не различить. Чтобы понять, какой из них нужен, выведите подробный список:
ls -l /sys/class/pwm
Вывод покажет ссылки вида pwmchip0 -> …/1f00098000.pwm/pwm/pwmchip0. На Raspberry Pi 5 ШИМ создаёт микросхема RP1, и у неё два контроллера по четыре канала: 1f00098000.pwm (PWM0) и 1f0009c000.pwm (PWM1). Контакты GPIO12 и GPIO13 подключены к PWM0, поэтому нам нужен тот pwmchipN, в чьей ссылке есть 1f00098000.pwm. Его номер понадобится в программе.
На Raspberry Pi OS на Debian 13 (ядро 6.18) это pwmchip0, на более старых версиях ядра номер бывает другим (например, pwmchip2). Не подставляйте номер из примера, не проверив его: если ошиться, библиотека выдаст ошибку, которая указывает совсем на другое (см. раздел «Если что-то не так»). Убедиться, что оверлей сработал, можно командой pinctrl get 12,13: в строках должно быть GPIO12 = PWM0_CHAN0 и GPIO13 = PWM0_CHAN1.
Шаг 3. Устанавливаем библиотеку
Библиотеки ставьте в виртуальное окружение (о venv подробнее):
python3 -m venv ~/servo-env
source ~/servo-env/bin/activate
pip install rpi-hardware-pwm
Что на снимке. Первая команда создаёт окружение ~/servo-env, вторая включает его (в начале строки появляется (servo-env)), а pip install скачивает маленькую библиотеку rpi-hardware-pwm с зеркала piwheels.org и сообщает Successfully installed rpi-hardware-pwm-0.3.1. Для этой библиотеки системные пакеты не нужны, поэтому окружение здесь создаётся обычным способом, без --system-site-packages (в отличие от способа 1, где нужен gpiozero).
Шаг 4. Программа
Создайте файл servo_hw.py. Номер контроллера замените на тот, что нашли на втором шаге:
from time import sleep
from rpi_hardware_pwm import HardwarePWM
CHIP = 0 # номер pwmchipN контроллера 1f00098000.pwm (PWM0), см. шаг 2
CHANNEL = 0 # канал 0 = GPIO12
FREQ_HZ = 50 # частота сервопривода
def angle_to_duty(angle):
"""Угол -90..+90 градусов в заполнение ШИМ, %: 2,5 % ... 12,5 %."""
return 7.5 + angle / 90 * 5.0
pwm = HardwarePWM(pwm_channel=CHANNEL, hz=FREQ_HZ, chip=CHIP)
pwm.start(angle_to_duty(0))
try:
for angle in (0, 90, 0, -90, 0):
print("Угол:", angle)
pwm.change_duty_cycle(angle_to_duty(angle))
sleep(1)
finally:
pwm.stop()
Запуск:
python3 servo_hw.py
Что на снимке. В окружении servo-env программа печатает те же пять углов (0, 90, 0, -90, 0) и завершается без ошибок. Предупреждения PWMSoftwareFallback здесь нет: ШИМ формирует сама микросхема, а не gpiozero.
Вал будет поворачиваться так же, как и в первом варианте, но без подёргиваний.
Если крайние положения не достигаются или вал упирается, подстройте формулу: 2,5 и 12,5 % соответствуют импульсам 0,5 и 2,5 мс.
Два сервопривода. Оверлей из примера включает канал 0 на GPIO12 и канал 1 на GPIO13. Второй сервопривод можно подключить к GPIO13 и управлять им отдельным объектом HardwarePWM(pwm_channel=1, hz=50, chip=CHIP). Эти контакты при включённом оверлее заняты под ШИМ и для других целей использовать их не стоит.
Несколько сервоприводов
Для 3–16 сервоприводов удобнее использовать отдельный контроллер на I2C — PCA9685: он берёт на себя формирование импульсов, а Raspberry Pi только отправляет ему углы по шине I2C. Подключение и пример кода в статье SG90 и PCA9685 на Python. Включение I2C описано в статье про I2C, SPI и UART.
Если что-то не так
| Симптом | Что проверить |
|---|---|
| Сервопривод не двигается | Питание на красном проводе (5 В), общая земля, правильность номера GPIO |
ModuleNotFoundError: No module named 'gpiozero' | Вы запустили программу из обычного виртуального окружения. Запускайте вне окружения или пересоздайте его с python3 -m venv --system-site-packages env |
| Вал дрожит | Включите аппаратный ШИМ (способ 2) или питайте сервопривод от отдельного источника |
| Вал гудит в крайних положениях | Сузьте диапазон импульсов: вал упирается в ограничитель |
| Плата перезагружается при движении | Просадка питания: подключите отдельный источник 5 В, объединив земли |
HardwarePWMException: Need to add 'dtoverlay=pwm-2chan' to /boot/config.txt and reboot | Сообщение вводит в заблуждение: библиотека выдаёт его и тогда, когда папки /sys/class/pwm/pwmchip<CHIP> просто нет. Проверьте номер CHIP: он должен совпадать с pwmchipN, у которого в ls -l /sys/class/pwm есть 1f00098000.pwm (на новых версиях ядра это pwmchip0). Только потом проверяйте строку dtoverlay в /boot/firmware/config.txt (не /boot/config.txt) и перезагрузку |
Что дальше
- Датчик HC-SR04 на Raspberry Pi — «парктроник»: сервопривод с дальномером как сканер;
- Камера Raspberry Pi — сервопривод для поворота камеры;
- Веб-интерфейс на Flask для GPIO — управление углом с телефона.
Материалы
- Документация gpiozero: класс AngularServo — gpiozero.readthedocs.io
- Библиотека rpi-hardware-pwm — github.com/Pioreactor/rpi_hardware_pwm
- Сервоприводы через PCA9685 — наша статья









