Перейти к содержанию

Servo

Сервопривод — это мотор, который может поворачиваться на заданный угол. В отличие от обычного мотора, он не может свободно вращаться (поэтому из него нельзя сделать вентилятор или колёса для машинки), но с помощью микроконтроллера можно точно задать угол поворота сервопривода с точностью до полуградуса, и он будет удерживать заданное положение.


Базовое использование


Servo(pin) -> Servo

Чтобы создать объект Servo, вызовите Servo(pin).

Аргументы:

  • pin (int) — порт пина (8, 9 или 12)

Возвращает: Возвращает объект Servo для pin.

Внутри серво управляется через ШИМ на частоте 50 Гц (период = 20 мс). Частота выставляется автоматически — настраивать её вручную не нужно.

from pibody import Servo

servo = Servo(9)

.angle(angle | None) -> None | int

Получить или установить угол серво (0–180 градусов).

Аргументы:

  • angle (float) — необязательный параметр, задающий угол серво в диапазоне [0, 180] градусов

Возвращает текущий угол [0, 180] при вызове без аргумента, иначе устанавливает угол и возвращает None.

Геттер возвращает последний установленный через объект угол (а не считанный с железа). Если угол ещё не устанавливался, вернётся None.

from pibody import Servo
from time import sleep

servo = Servo(8)

servo.angle(180)
sleep(1)

print(servo.angle())  # 180

servo.angle(90)
sleep(1)
servo.angle(0)
sleep(1)

print(servo.angle())  # 0

servo(angle | None) -> None | int

Объект Servo можно вызывать как функцию — вызов работает точно так же, как .angle().

Аргументы:

  • angle (float) — необязательный параметр, задающий угол серво в диапазоне [0, 180] градусов

servo(90) устанавливает угол, servo() возвращает текущий угол.

from pibody import Servo

servo = Servo(9)

servo(90)       # то же, что servo.angle(90)
print(servo())  # 90

.on()

Переинициализирует выход ШИМ (включает серво).

servo.on()

.off()

Деинициализирует выход ШИМ (отключает серво).

servo.off()

Прямое управление через PWM

Класс Servo больше не даёт доступ к duty, duty_u16 и freq. Если нужно низкоуровневое управление, создайте PWM-объект напрямую вместо Servo:

from pibody import PWM

servo = PWM(8)
servo.freq(50)  # нужно задать вручную

Положение серво управляется шириной импульса сигнала ШИМ, а не непосредственно коэффициентом заполнения. Например, стандартный сервопривод на 180° ожидает импульс между 0.5 мс (0°) и 2.5 мс (180°), повторяющийся каждые 20 мс (50 Гц).

freq задаёт частоту повторения импульсов — для серво это должно быть 50 Гц (период = 20 мс). duty задаёт, какая часть этого периода сигнал находится в высоком состоянии. Для преобразования угла в значение duty:

pulse_width = (angle / 180) * 2 + 0.5   # 0.5–2.5 мс
duty = pulse_width / SERVO_PERIOD_MS    # часть от 20 мс

В наборе PiBody SERVO_PERIOD_MS = 20 (равно 1000 // freq).

Превышение рекомендуемого диапазона (например, импульс > 2.5 мс для серво на 180°) не повредит сервопривод — большинство моделей просто игнорируют превышение и удерживаются на максимальном угле. Некоторые могут издавать слабое гудение на механическом упоре; это нормально. Значения ниже минимальных 0.5 мс также обрезаются аппаратурой серво до положения 0°.

Методы ниже — это методы pibody.PWM, показанные здесь применительно к серво.


.duty(value | None) -> None | float

Вы можете установить угол через duty. Для управления сначала преобразуйте угол в ширину импульса: pulse_width = (angle / 180) * 2 + 0.5

После этого преобразуйте ширину импульса в коэффициент заполнения: duty = pulse_width / SERVO_PERIOD_MS

Используйте значение int в диапазоне [0.025, 0.125]. Значение 0 отключит серво.

Аргументы:

  • value (float) — необязательный параметр, задающий коэффициент заполнения ШИМ. Может принимать значение в диапазоне [0, 0.125]. По умолчанию: 0

Если value пусто, метод возвращает коэффициент заполнения, использованный ранее.

from pibody import PWM
SERVO_PERIOD_MS = 20

servo = PWM(8)
servo.freq(50)

angle = 90
pulse_width = (angle / 180) * 2 + 0.5  # 1.5

duty = pulse_width / SERVO_PERIOD_MS   # 0.075
servo.duty(duty)

print(servo.duty())  # 0.075

.duty_u16(value | None) -> None | int

То же, что и .duty(), вы можете установить угол через duty_u16. u16 означает 16-битное значение.

Используйте значение int в диапазоне [1638, 8191] Значение 0 отключит серво.

Аргументы:

  • value (int) — необязательный параметр, задающий коэффициент заполнения pibody.PWM. Может принимать значение в диапазоне [1638, 8191]. По умолчанию: 0

Если value пусто, метод возвращает коэффициент заполнения, использованный ранее.

from pibody import PWM
SERVO_PERIOD_MS = 20

servo = PWM(8)
servo.freq(50)

angle = 90
pulse_width = (angle / 180) * 2 + 0.5  # 1.5

duty = pulse_width / SERVO_PERIOD_MS   # 0.075 (нормализованный)
duty_u16 = int(duty * 65535)           # ~4915
servo.duty_u16(duty_u16)

print(servo.duty_u16())  # 4915

.freq(value | None) -> None | int

freq задаёт частоту повторения импульсов — для серво это должно быть 50 Гц (период = 20 мс).

Аргументы:

  • value (int) — необязательный параметр, задающий частоту ШИМ. По умолчанию: 50

Если value пусто, метод возвращает частоту, использованную ранее.

pwm.freq(50)

print(pwm.freq())  # 50