====== Сервоприводы PDM с удержанием угла: особенности применения и примеры кода ======
Сервоприводы PDM с удержанием угла — это моторы, которые управляются сигналом PDM (Pulse Duration Modulation) и способны удерживать заданный угол.
Сервоприводы с удержанием угла используются для моделирования движения различных механизмов: Привод с лёгкостью сможет открывать/закрывать заслонки для создания кормушки домашнему питомцу или для проектирования маленького тайника в квеструме. А ещё такие сервомоторы дадут возможность вашему роботу управлять руками или вращать головой.
===== Список моделей =====
^ Модель ^ Форм-фактор ^ Сигнал управления ^ Обратная связь ^ Назначение ^ Внутренний интерфейс ^ Диапазон вращения ^
| [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FS90]] / [[:products:servo-fs90|Документация]] | Микро | [[articles:servo-pdm-standard|PDM]] | Нет | Удержание угла | Аналоговый | 0–180° |
| [[amp>product/servo-ft90b?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FT90B]] / [[:products:servo-ft90b|Документация]] | Микро | [[articles:servo-pdm-standard|PDM]] | Нет | Удержание угла | Цифровой | 0–180° |
| [[amp>product/servo-fs90-fb?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FS90-FB]] / [[:products:servo-fs90-fb|Документация]] | Микро | [[articles:servo-pdm-standard|PDM]] | Да | Удержание угла | Аналоговый | 0–180° |
| [[amp>product/servo-fs0403-fb?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FS0403-FB]] / [[:products:servo-fs0403-fb|Документация]] | Микро | [[articles:servo-pdm-standard|PDM]] | Да | Удержание угла | Аналоговый | 0–180° |
| [[amp>product/servo-fs5106b?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Feetech FS5106B]] | Стандарт | [[articles:servo-pdm-standard|PDM]] | Нет | Удержание угла | Аналоговый | 0–180° |
| [[amp>product/servo-fs5109m?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Feetech FS5109M]] | Стандарт | [[articles:servo-pdm-standard|PDM]] | Нет | Удержание угла | Аналоговый | 0–180° |
| [[amp>product/servo-fs5519m?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FT5519M]] | Стандарт | [[articles:servo-pdm-continuous-rotation|PDM]] | Да | Удержание угла | Цифровой | 180° |
| [[amp>product/servo-fb5118m?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Feetech FB5118M]] / [[:products:servo-fb5118m|Документация]] | Стандарт | [[articles:servo-pdm-standard|PDM]] | Да | Удержание угла | Цифровой | 0–300° |
| [[amp>product/servo-ft6335m?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Feetech FT6335M]] / [[:products:servo-ft6335m|Документация]] | Стандарт | [[articles:servo-pdm-standard|PDM]] | Нет | Удержание угла | Цифровой | 0–360° |
===== Интерфейс управления =====
В сервоприводах PDM с удержанием угла положение выходного вала зависит от длины импульса. Для управления мотором необходимо подавать особый сигнал PDM (Pulse Duration Modulation) — импульсы постоянной частоты и переменной ширины. При поступлении с внешнего контроллера управляющего импульса начинка сервопривода генерирует мотору свой сигнал, длительность которого определяется датчиком обратной связи. Далее схема сравнивает длительность двух импульсов:
* Если длительность разная → электромотор включается. Направление вала зависит от знака разности импульсов.
* Если длины импульсов равны → электромотор останавливается.
В сигнале PDM частота импульсов постоянна и равна 50 Гц, т. е. период подачи импульсов равен 20 мс. А вот ширина импульса изменяется, и именно от неё зависит выходной угол удержания мотора. Принято считать, что диапазону выходного угла 0–180° соответствует рабочая ширина импульса 544–2400 мкс.
В качестве примера приведём данные для популярного хобби-сервопривода [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo&utm_medium=wiki|Feetech FS90]].
^ Период импульсов ^ Ширина импульса ^ Положение сервопривода ^ Описание ^
| 20 мс | 544 мкс | 0° | Максимальное положение вала по часовой стрелке CW|
| 20 мс | 1540 мкс | 90° | Нейтральное положение вала|
| 20 мс | 2400 мкс | 180° |Максимальное положение вала против часовой стрелки CCW|
{{ :articles:servo-pdm-standard:servo-pdm-standard-info.1.png?nolink |}}
На разных приводах диапазон ширины импульсов и поворота вала может отличатся от стандартного. Например, есть сервоприводы с диапазонами 0–120° и 0–310°. Эти данные можно уточнить в [[#список_моделей|характеристиках]].
Даже в рамках одной и той же модели сервопривода существует погрешность, допускаемая при производстве, которая приводит к тому, что рабочий диапазон длин импульсов отличается. Для точной работы каждый конкретный сервопривод должен быть откалиброван: путём экспериментов необходимо подобрать корректный диапазон, характерный именно для него.
Часто способ управления сервоприводами называют PWM (Pulse Width Modulation) или PPM (Pulse Position Modulation). Это не так, и использование этих способов может даже повредить привод. Корректный термин — PDM (Pulse Duration Modulation) в котором важна длина импульсов, а не частота.
Если ваш сервопривод дребезжит, дёргается или стоит задача управлять несколькими серво, обратите внимание на плату расширения [[amp>product/arduino-multiservo-shield?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Multiservo Shield]].
===== Сервоприводы с обратной связью =====
Среди сервоприводов PDM с удержанием угла также встречаются модели с обратной связью, у которых сигнал внутреннего потенциометра выведен отдельным проводом.
{{ :articles:servo-pdm-standard:servo-pdm-standard-info.2.jpg?nolink |}}
Это пригодится, чтобы строить хитрые петли обратной связи, где фигурирует текущее положение сервопривода. Например, чтобы узнать, достиг ли сервопривод целевого положения или ему что-то помешало.
Обычно наличие сигнала обратной связи явно указывается в [[#список_моделей|характеристиках]] сервопривода.
===== Питание сервопривода =====
Сервопривод можно запитать двумя способами: напрямую от контроллера (если позволяют характеристики) или же от внешнего источника питания.
==== Без внешнего источника питания ====
Если сервопривод питается напряжением 5 вольт и потребляет ток менее 500 мА, есть возможность запитать сервомотор непосредственно от контроллера.
{{ :articles:servo-pdm-standard:servo-pdm-standard-power.1.png?nolink |}}
=== Схема подключения ===
^ Цвет провода ^ Контакт ^ Функция ^ Подключение ^
| Оранжевый / Жёлтый / Белый | S | Пин управления сервоприводом | Подключите к пину ввода-вывода контроллера. |
| Красный | V | Питание | Подключите к питанию контроллера. |
| Коричневый / Чёрный | G | Земля | Подключите к земле контроллера. |
==== С внешним источником питания ====
Если сервопривод питается напряжением свыше 5 вольт или потребляет ток более 500 мА, то ему необходим [[amp>product/power-supply-adapter-robiton-tn2000s?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|внешний источник питания]].
{{ :articles:servo-pdm-standard:servo-pdm-standard-power.2.png?nolink |}}
=== Схема подключения ===
^ Цвет провода ^ Контакт ^ Функция ^ Подключение ^
| Оранжевый / Жёлтый / Белый | S | Пин управления сервоприводом | Подключите к пину ввода-вывода контроллера. |
| Красный | V | Питание | Подключите к внешнему источнику питания с подходящим вольтажом. |
| Коричневый / Чёрный | G | Земля | Подключите к земле внешнего источника питания и земле контроллера. |
===== Примеры работы для Arduino =====
Мозгом для проекта выступит платформа [[amp>product/arduino-uno?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Arduino Uno]].
В качестве тестового сервопривода возьмём [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Feetech FS90]]. Примеры совместимы со всеми серво PDM с удержанием угла, необходимо только внести в программу [[#список_моделей|характеристики]] конкретно вашего мотора.
==== Подключение и настройка ====
Для наглядности схемы мы используем подключение сервопривода напрямую к контроллеру, без внешнего питания. Если вам нужен дополнительный блок питания, сверьтесь со схемами в разделе про [[#питание_сервопривода|питание сервопривода]].
=== Что понадобится ===
* [[amp>product/arduino-uno?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Arduino Uno]]
* [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Сервопривод Feetech FS90]]
* [[amp>product/wire-mm?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Соединительные провода «папа-папа»]]
* [[amp>product/usb-cable?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Кабель USB (A — B)]]
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-arduino-wiring.1.png?nolink |}}
Для быстрой сборки и отладки устройства рекомендуем взять плату расширения [[amp>product/arduino-troyka-shield?utm_source=man&utm_campaign=servo-fs90&utm_medium=wiki|Troyka Shield]], которая надевается сверху на Uno R3 методом бутерброда.{{ :articles:servo-pdm-standard:servo-pdm-standard-arduino-wiring.2.png?nolink |}}
=== Программная настройка ===
* [[:products:arduino-uno|Настройте плату в среде Arduino IDE]].
* Для работы примеров понадобится библиотека {{ :articles:servo-pdm-standard:amperkaservo.zip |AmperkaServo}}, которая является обёрткой штатной библиотеки [[https://www.arduino.cc/reference/en/libraries/servo/|Servo]] с дополнительными методами.
==== Смена положения угла ====
Для старта протестируем мотор в положениях 0, 90 и 180 градусов.
=== Код для Arduino IDE ===
// Библиотека с расширенными функциями для работы с Servo
#include
// Создаём объект для работы с сервомоторами
AmperkaServo servo;
// Задаём имя пина, к которому подключён сервопривод
constexpr uint8_t SERVO_PIN = 9;
void setup() {
// Подключаем сервомотор
// servo.attach(SERVO_PIN);
// Подключаем сервомотор с расширенными параметрами
// Советуем использовать именно этот вариант для точной настройки мотора
// servo.attach(pin, minPulseWidth, maxPulseWidth, minAngle, maxAngle);
// - pin: номер пина, к которому подключён сервопривод
// - minPulseWidth: ширина импульса, соответствующая минимальному углу поворота.
// Опциональный и по умолчанию стоит 544 мкс.
// - maxPulseWidth: ширина импульса, соответствующая максимальному углу поворота.
// Опциональный и по умолчанию стоит 2400 мкс.
// - minAngle: минимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 0°.
// - maxAngle: максимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 180°.
// Данные возьмите из технических характеристик мотора
servo.attach(SERVO_PIN, 544, 2400, 0, 180);
}
void loop() {
// Устанавливаем минимальный угол
servo.writeAngle(servo.getMinAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем среднее положение
servo.writeAngle(servo.getMidAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем максимальный угол
servo.writeAngle(servo.getMaxAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем среднее положение
servo.writeAngle(servo.getMidAngle());
// Ждём 1 секунду
delay(1000);
}
После прошивки устройства вал сервопривода будет поворачиваться на 0, 90 и 180 градусов.{{ :articles:servo-pdm-standard:servo-pdm-standard-example-arduino-switch.gif?nolink |}}
==== Плавная смена положения угла ====
Усложним задачу. Сделаем плавное перемещение вала от 0 до 180 градусов.
=== Код для Arduino IDE ===
// Библиотека с расширенными функциями для работы с Servo
#include
// Создаём объект для работы с сервомоторами
AmperkaServo servo;
// Задаём имя пина к которому подключён сервопривод
constexpr uint8_t SERVO_PIN = 9;
void setup() {
// Подключаем сервомотор
// servo.attach(SERVO_PIN);
// Подключаем сервомотор с расширенными параметрами
// Советуем использовать именно этот вариант для точной настройки мотора
// servo.attach(pin, minPulseWidth, maxPulseWidth, minAngle, maxAngle);
// - pin: номер пина к которому подключён сервопривод
// - minPulseWidth: ширина импульса, соответствующая минимальному углу поворота.
// Опциональный и по умолчанию стоит 544 мкс.
// - maxPulseWidth: ширина импульса, соответствующая максимальному углу поворота.
// Опциональный и по умолчанию стоит 2400 мкс.
// - minAngle: минимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 0°.
// - maxAngle: максимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 180°.
// Данные возьмите из технических характеристик мотора
servo.attach(SERVO_PIN, 544, 2400, 0, 180);
}
void loop() {
// Перебираем значения угла сервы от min до max
for (int pos = servo.getMinAngle(); pos <= servo.getMaxAngle(); pos++) {
// Отправляем текущий угол на серво
servo.writeAngle(pos);
// Ждём 20 мс
delay(20);
}
// Перебираем значения угла сервы от max до min
for (int pos = servo.getMaxAngle(); pos >= servo.getMinAngle(); pos--) {
// Отправляем текущий угол на серво
servo.writeAngle(pos);
// Ждём 20 мс
delay(20);
}
}
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно.
{{ :articles:servo-pdm-standard:servo-pdm-standard-example-arduino-sweep.gif?nolink |}}
==== Смена положения угла двух сервоприводов ====
Добавим к проекту второй сервопривод.
{{ :articles:servo-pdm-standard:servo-pdm-standard-arduino-wiring.3.png?nolink |}}
Будем вращать по очереди вал двух моторов в положения 0, 90 и 180 градусов.
=== Код для Arduino IDE ===
// Библиотека с расширенными функциями для работы с Servo
#include
// Создаём объект для работы с первым сервомотором
AmperkaServo servoOne;
// Создаём объект для работы со вторым сервомотором
AmperkaServo servoTwo;
// Задаём имя пина, к которому подключён первый сервопривод
constexpr uint8_t SERVO_PIN_ONE = 9;
// Задаём имя пина, к которому подключён второй сервопривод
constexpr uint8_t SERVO_PIN_TWO = 11;
void setup() {
// Подключаем первый и второй сервомотор
// servoOne.attach(SERVO_PIN_ONE);
// servoTwo.attach(SERVO_PIN_TWO);
// Подключаем сервомотор с расширенными параметрами
// Советуем использовать именно этот вариант для точной настройки мотора
// servo.attach(pin, minPulseWidth, maxPulseWidth, minAngle, maxAngle);
// - pin: номер пина, к которому подключён сервопривод
// - minPulseWidth: ширина импульса, соответствующая минимальному углу поворота.
// Опциональный и по умолчанию стоит 544 мкс.
// - maxPulseWidth: ширина импульса, соответствующая максимальному углу поворота.
// Опциональный и по умолчанию стоит 2400 мкс.
// - minAngle: минимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 0°.
// - maxAngle: максимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 180°.
// Данные возьмите из технических характеристик мотора
servoOne.attach(SERVO_PIN_ONE, 544, 2400, 0, 180);
servoTwo.attach(SERVO_PIN_TWO, 544, 2400, 0, 180);
// Устанавливаем минимальный угол первого мотора
servoOne.writeAngle(servoOne.getMinAngle());
// Устанавливаем минимальный угол второго мотора
servoTwo.writeAngle(servoTwo.getMinAngle());
}
void loop() {
// Устанавливаем среднее положение первого мотора
servoOne.writeAngle(servoOne.getMidAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем максимальный угол первого мотора
servoOne.writeAngle(servoOne.getMaxAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем среднее положение первого мотора
servoOne.writeAngle(servoOne.getMidAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем минимальный угол первого мотора
servoOne.writeAngle(servoOne.getMinAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем среднее положение второго мотора
servoTwo.writeAngle(servoTwo.getMidAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем максимальный угол второго мотора
servoTwo.writeAngle(servoTwo.getMaxAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем среднее положение второго мотора
servoTwo.writeAngle(servoTwo.getMidAngle());
// Ждём 1 секунду
delay(1000);
// Устанавливаем минимальный угол второго мотора
servoTwo.writeAngle(servoTwo.getMinAngle());
// Ждём 1 секунду
delay(1000);
}
После прошивки устройства вал каждого сервопривода будет по очереди поворачиваться на 0, 90 и 180 градусов.{{ :articles:servo-pdm-standard:servo-pdm-standard-example-arduino-switch-multiple.gif?nolink |}}
==== Считывание угла сервопривода ====
В продолжении считаем текущее положение вала мотора. Важно отметить, что лишь малая часть сервоприводов позволяет считывать данные [[#сервоприводы_с_обратной_связью|обратной связи]] через отдельный провод.
Для теста повторим штатный пример для [[#плавная_смена_положения_угла|плавного перемещения сервопривода от 0 до 180 градусов]] и параллельно будем считывать текущий угол вала мотора.
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-arduino-wiring.4.png?nolink |}}
=== Код для Arduino IDE ===
// Библиотека с расширенными функциями для работы с Servo
#include
// Создаём объект для работы с сервомоторами
AmperkaServo servo;
// Задаём имя пина, к которому подключён сервопривод
constexpr uint8_t SERVO_PIN = 9;
// Задаём имя пина FB, к которому подключён сервопривод
constexpr uint8_t SERVO_PIN_FB = A5;
void setup() {
// Открываем Serial-порт
Serial.begin(9600);
// Подключаем сервомотор
// servo.attach(SERVO_PIN);
// Подключаем сервомотор с расширенными параметрами
// Советуем использовать именно этот вариант для точной настройки мотора
// servo.attach(pin, minPulseWidth, maxPulseWidth, minAngle, maxAngle);
// - pin: номер пина, к которому подключён сервопривод
// - minPulseWidth: ширина импульса, соответствующая минимальному углу поворота.
// Опциональный и по умолчанию стоит 544 мкс.
// - maxPulseWidth: ширина импульса, соответствующая максимальному углу поворота.
// Опциональный и по умолчанию стоит 2400 мкс.
// - minAngle: минимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 0°.
// - maxAngle: максимальный угол поворота сервопривода.
// Опциональный и по умолчанию стоит 180°.
// Данные возьмите из технических характеристик мотора
servo.attach(SERVO_PIN, 544, 2400, 0, 180);
// Подключаем сервомотор к обратной связи
// servo.attachFB(pinFB, voltageFBCW, voltageFBCCW);
// - pinFB: номер пина, к которому подключён сигнал обратной связи от сервопривода
// - voltageFBCW: напряжение обратной связи в крайнем положении по часовой стрелке CW
// - voltageFBCCW: напряжение обратной связи в крайнем положении против часовой стрелки CCW
// Данные возьмите из технических характеристик мотора
servo.attachFB(SERVO_PIN_FB, 2.3, 0.5);
}
void loop() {
// Перебираем значения угла сервы от min до max
for (int pos = servo.getMinAngle(); pos <= servo.getMaxAngle(); pos++) {
// Отправляем текущий угол на серво
servo.writeAngle(pos);
// Ждём 20 мс
delay(20);
// Считываем и выводим текущий угол сервопривода
Serial.println(servo.readAngleFB());
}
// Перебираем значения угла сервы от max до min
for (int pos = servo.getMaxAngle(); pos >= servo.getMinAngle(); pos--) {
// Отправляем текущий угол на серво
servo.writeAngle(pos);
// Ждём 20 мс
delay(20);
// Считываем и выводим текущий угол сервопривода
Serial.println(servo.readAngleFB());
}
}
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно. И параллельно в консоли будет выводиться текущий угол вала.
===== Примеры работы для Espruino =====
Мозгом для проекта выступит платформа из семейства [[amp>collection/espruino?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Espruino]], например [[amp>product/iskra-js?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Iskra JS]].
==== Подключение и настройка ====
Для наглядности схемы мы используем подключение сервопривода напрямую к контроллеру, без внешнего питания. Если вам нужен дополнительный блок питания, сверьтесь со схемами в разделе про [[#питание_сервопривода|питание сервопривода]].
=== Что понадобится ===
* [[amp>product/iskra-js?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Iskra JS]]
* [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Сервопривод Feetech FS90]]
* [[amp>product/wire-mm?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Соединительные провода «папа-папа»]]
* [[amp>product/usb-cable-micro?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Кабель USB (A — Micro USB)]]
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-espruino-wiring.1.png?nolink |}}
Для быстрой сборки и отладки устройства рекомендуем взять плату расширения [[amp>product/arduino-troyka-shield?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Troyka Shield]], которая надевается сверху на Iskra JS методом бутерброда.{{ :articles:servo-pdm-standard:servo-pdm-standard-espruino-wiring.2.png?nolink |}}
=== Программная настройка ===
[[:js:iskra_js|Настройте плату Iskra JS]] в среде Espruino Web IDE.
==== Смена положения угла ====
Для старта протестируем мотор в положениях 0, 90 и 180 градусов.
=== Код для Espruino IDE ===
// Подключаем сервопривод к пину 9 через библиотеку Servo
var servo = require("@amperka/servo").connect(P9);
// Создаём таймер, тикающий каждые 1 секунды
var timerServo = require("@amperka/timer").create(3);
// Задаём минимальный и максимальный угол поворота
var MIN_ANGLE = 0;
var MAX_ANGLE = 180;
var MID_ANGLE = (MIN_ANGLE + MAX_ANGLE) / 2;
// Переменная для хранения текущей позиции сервомотора
var pos = MIN_ANGLE;
// Функция вращения сервопривода
function startServo() {
servo.write(pos);
// Запускаем таймер
timerServo.run();
}
// Подписываемся на событие таймера
timerServo.on("tick", function () {
// Неважно, какое было прошлое состояние угла
// Устанавливаем среднее положение
servo.write(MID_ANGLE);
// Запускаем мотор в противоположную сторону
// От прошлого положения через одну секунду
setTimeout(function () {
if (pos == MIN_ANGLE) {
pos = MAX_ANGLE;
} else if (pos == MAX_ANGLE) {
pos = MIN_ANGLE;
}
startServo();
}, 1500);
});
// Запускаем функцию вращения мотора
startServo();
После прошивки устройства вал сервопривода будет поворачиваться на 0, 90 и 180 градусов.
{{ :articles:servo-pdm-standard:servo-pdm-standard-example-espruino-switch.gif?nolink |}}
==== Плавная смена положения угла ====
Усложним задачу. Сделаем плавное перемещение вала от 0 до 180 градусов.
=== Код для Espruino IDE ===
// Подключаем сервопривод к пину 9 через библиотеку Servo
var servo = require("@amperka/servo").connect(P9);
// Переменная для хранения ID анимации
var idAnimServo;
// Создаём объект анимации
// для плавного изменения параметров вращения мотора
var animServo = require("@amperka/animation")
.create({
// Начальное значение в градусах
from: 0,
// Конечное значение в градусах
to: 180,
// Продолжительность полного перехода
// за 3 секунд мотор пройдёт диапазон значений от 0 до 180
duration: 3,
// Шаг обновления: каждые 20 мс
updateInterval: 0.02,
})
.queue({
// Начальное значение в градусах
from: 180,
// Конечное значение в градусах
to: 0,
// Продолжительность полного перехода
// за 3 секунд мотор пройдёт диапазон значений от 180 до 0
duration: 3,
});
// Запускаем анимацию
idAnimServo = animServo.play();
// Обработчик анимации
animServo.on("update", function (val) {
servo.write(val);
// Если анимация закончилась,
// Запускаем её повторно
if (idAnimServo._intervalID == null) {
idAnimServo = animServo.play();
}
});
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно.
{{ :articles:servo-pdm-standard:servo-pdm-standard-example-espruino-sweep.gif?nolink |}}
==== Считывание угла сервопривода ====
В продолжении считаем текущее положение вала мотора. Важно отметить, что лишь малая часть сервоприводов позволяет считывать данные [[#сервоприводы_с_обратной_связью|обратной связи]] через отдельный провод.
Для теста повторим штатный пример для [[#плавная_смена_положения_угла1|плавного перемещения сервопривода от 0 до 180 градусов]] и параллельно будем считывать текущий угол вала мотора.
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-espruino-wiring.4.png?nolink |}}
=== Код для Espruino IDE ===
// Подключаем сервопривод к пину 9 через библиотеку Servo
var servo = require("@amperka/servo").connect(P9);
// Подключаем сервопривод к пину A5 для считывания данных угла поворота
var sensor = require('@amperka/pot').connect(A5);
// Переменная для хранения ID анимации
var idAnimServo;
// Создаём объект анимации
// для плавного изменения параметров вращения мотора
var animServo = require("@amperka/animation")
.create({
// Начальное значение в градусах
from: 0,
// Конечное значение в градусах
to: 180,
// Продолжительность полного перехода
// за 3 секунд мотор пройдёт диапазон значений от 0 до 180
duration: 3,
// Шаг обновления: каждые 20 мс
updateInterval: 0.02,
})
.queue({
// Начальное значение в градусах
from: 180,
// Конечное значение в градусах
to: 0,
// Продолжительность полного перехода
// за 3 секунд мотор пройдёт диапазон значений от 180 до 0
duration: 3,
});
// Запускаем анимацию
idAnimServo = animServo.play();
// Обработчик анимации
animServo.on("update", function (val) {
servo.write(val);
// Если анимация закончилась,
// Запускаем её повторно
if (idAnimServo._intervalID == null) {
idAnimServo = animServo.play();
}
});
// Каждые 100 мс
// Считываем и выводим текущий угол сервопривода
setInterval(function() {
value = sensor.read();
valueAngle = map(value, 0.11, 0.70, 0, 180);
console.log('Servo value =', Math.round(valueAngle), 'degrees');
}, 100);
// Функция преобразования одного диапазона в другой
function map(x, minIn, maxIn, minOut, maxOut) {
return (x - minIn) * (maxOut - minOut) / (maxIn - minIn) + minOut;
}
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно. И параллельно в консоли будет выводиться текущий угол вала.
===== Примеры работы для Raspberry Pi =====
Мозгом для проекта выступит микрокомпьютер [[amp>product/raspberry-pi-4-model-b-4-gb?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Raspberry Pi 4 Model B]].
==== Подключение и настройка ====
Для наглядности схемы мы используем подключение сервопривода напрямую к контроллеру, без внешнего питания. Если вам нужен дополнительный блок питания, сверьтесь со схемами в разделе про [[#питание_сервопривода|питание сервопривода]].
=== Что понадобится? ===
* [[amp>product/raspberry-pi-4-model-b-4-gb?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Raspberry Pi 4 Model B]]
* [[amp>product/servo-fs90?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Сервопривод Feetech FS90]]
* [[amp>product/wire-fm?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Соединительные провода «папа-мама»]]
* [[amp>product/cable-usb-type-c?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Кабель USB (A — Type-C)]]
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-raspberry-pi-wiring.1.png?nolink |}}
Для быстрой сборки и отладки устройства рекомендуем взять плату расширения [[amp>product/raspberry-pi-troyka-hat?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Troyka HAT]], которая надевается сверху на Raspberry Pi методом бутерброда.
Имена пинов на Troyka HAT относятся к нумерации ''Wiring Pi'', которая отличается от стандартной нумерации ''BCM/GPIO'' одноплатника Raspberry Pi. Подробности смотрите в [[products:raspberry-pi-troyka-hat#распиновка|распиновке Troyka HAT]] и [[https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering|нумерации в библиотеке]].
{{ :articles:servo-pdm-standard:servo-pdm-standard-raspberry-pi-wiring.2.png?nolink |}}
=== Программная настройка ===
- [[:articles:rpi-guide|Заведите Raspberry Pi]].
- [[products:raspberry-pi-troyka-hat|Подключите и настройте плату расширения Troyka HAT]].
- Для работы примеров понадобится модуль [[https://gpiozero.readthedocs.io/en/stable/api_output.html#angularservo|AngularServo]] из штатной библиотеки [[https://gpiozero.readthedocs.io/en/stable/index.html|GPIO Zero]].
==== Смена положения угла ====
Для старта протестируем мотор в положениях 0, 90 и 180 градусов.
=== Код для Python ===
# Библиотека для работы с сервоприводами
from gpiozero import AngularServo
from time import sleep
# Создаём объект для работы с сервоприводом
# - pin: номер пина, к которому подключён сервопривод
# WPIx, нумерация WiringPi, где x — номер пина
# GPIOx, нумерация GPIO/BCM, где x — номер пина
# - min_angle: минимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: -90°
# - min_angle: максимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: 90°
# - min_pulse_width: ширина импульса, соответствующая минимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.001 c = 1000 мкс
# - max_pulse_width: ширина импульса, соответствующая максимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.002 c = 2000 мкс
# Подробности нумерации: https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering
# Каждая модель сервопривода имеет свои характеристики
servo = AngularServo(
"WPI6", min_angle=0, max_angle=180, min_pulse_width=0.000544, max_pulse_width=0.0024
)
while True:
# Устанавливаем положение вала в минимальный угол
servo.angle = 0
# Ждём 1 секунду
sleep(1)
# Устанавливаем положение вала в среднее состояние
servo.angle = 90
# Ждём 1 секунду
sleep(1)
# Устанавливаем положение вала в максимальный угол
servo.angle = 180
# Ждём 1 секунду
sleep(1)
# Устанавливаем положение вала в среднее состояние
servo.angle = 90
# Ждём 1 секунду
sleep(1)
После прошивки устройства вал сервопривода будет поворачиваться на 0, 90 и 180 градусов.
{{ :articles:servo-pdm-standard:servo-pdm-standard-example-raspberry-pi-switch.gif?nolink |}}
==== Плавная смена положения угла ====
Усложним задачу. Сделаем плавное перемещение вала от 0 до 180 градусов.
=== Код для Python ===
# Библиотека для работы с сервоприводами
from gpiozero import AngularServo
from time import sleep
# Создаём объект для работы с сервоприводом
# - pin: номер пина, к которому подключён сервопривод
# WPIx, нумерация WiringPi, где x — номер пина
# GPIOx, нумерация GPIO/BCM, где x — номер пина
# - min_angle: минимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: -90°
# - min_angle: максимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: 90°
# - min_pulse_width: ширина импульса, соответствующая минимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.001 c = 1000 мкс
# - max_pulse_width: ширина импульса, соответствующая максимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.002 c = 2000 мкс
# Подробности нумерации: https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering
# Каждая модель сервопривода имеет свои характеристики
servo = AngularServo(
"WPI6", min_angle=0, max_angle=180, min_pulse_width=0.000544, max_pulse_width=0.0024
)
# Шаг сервопривода
step = 1
while True:
for val in range(servo.min_angle, servo.max_angle, step):
servo.angle = val
sleep(0.02)
for val in range(servo.max_angle, servo.min_angle, -step):
servo.angle = val
sleep(0.02)
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно.
{{ :articles:servo-pdm-standard:servo-pdm-standard-example-raspberry-pi-sweep.gif?nolink |}}
==== Считывание угла сервопривода ====
В продолжении считаем текущее положение вала мотора. Важно отметить, что лишь малая часть сервоприводов позволяет считывать данные [[#сервоприводы_с_обратной_связью|обратной связи]] через отдельный провод.
Для теста повторим штатный пример для [[#плавная_смена_положения_угла2|плавного перемещения сервопривода от 0 до 180 градусов]] и параллельно будем считывать текущий угол вала мотора.
Поскольку в микрокомпьютерах Raspberry Pi отсутствует АЦП, то для работы примера ниже понадобится плата расширения [[amp>product/raspberry-pi-troyka-hat?utm_source=man&utm_campaign=servo-pdm-standard&utm_medium=wiki|Troyka HAT]].
=== Схема устройства ===
{{ :articles:servo-pdm-standard:servo-pdm-standard-raspberry-pi-wiring.4.png?nolink |}}
=== Код для Python ===
# Библиотека для работы с сервоприводами
from gpiozero import AngularServo
# Библиотека для работы с платой Troyka HAT
import troykahat
# Библиотека для работы со временем
from time import sleep
# Создаём объект для работы с сервоприводом
# - pin: номер пина, к которому подключён сервопривод
# WPIx, нумерация WiringPi, где x — номер пина
# GPIOx, нумерация GPIO/BCM, где x — номер пина
# - min_angle: минимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: -90°
# - min_angle: максимальный угол поворота сервопривода
# Опциональный и по умолчанию стоит: 90°
# - min_pulse_width: ширина импульса, соответствующая минимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.001 c = 1000 мкс
# - max_pulse_width: ширина импульса, соответствующая максимальному углу поворота сервопривода
# Опциональный и по умолчанию стоит: 0.002 c = 2000 мкс
# Подробности нумерации: https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering
# Каждая модель сервопривода имеет свои характеристики
servo = AngularServo(
"WPI6", min_angle=0, max_angle=180, min_pulse_width=0.000544, max_pulse_width=0.0024
)
# Назначаем константное имя пину 5 из группы "Analog IO",
# Подключите потенциометр к этому пину.
PIN_AP_SERVO_FEEDBACK = 5
# Создаём объект ap для работы с пинами,
# помеченными как «Analog IO» на плате Troyka HAT.
# Это пины, подключенные к встроенному на плате I²C-расширителю
# на микроконтроллере STM32F030F4P6.
ap = troykahat.analog_io()
# Шаг сервопривода
step_angle_servo = 1
def remap(x, min_in, max_in, min_out, max_out):
return (x - min_in) * (max_out - min_out) / (max_in - min_in) + min_out
# Функция для считывания «сырых» данных положения сервопривода
# и перевода их в угол поворота
def read_position_angle(pin):
position_raw = ap.analogRead(pin)
position_angle = round(remap(position_raw, 0.12, 0.7, 0, 180))
return position_angle
while True:
for val in range(servo.min_angle, servo.max_angle, step_angle_servo):
servo.angle = val
print(f"Servo position = {read_position_angle(PIN_AP_SERVO_FEEDBACK)} degrees")
sleep(0.02)
for val in range(servo.max_angle, servo.min_angle, -step_angle_servo):
servo.angle = val
print(f"Servo position = {read_position_angle(PIN_AP_SERVO_FEEDBACK)} degrees")
sleep(0.02)
После прошивки устройства вал сервопривода будет плавно перемещаться от 0 до 180 градусов и обратно. И параллельно в консоли будет выводиться текущий угол вала.
===== Библиотеки =====
* [[https://www.arduino.cc/reference/en/libraries/servo/|Библиотека Servo для Arduino]]
* {{ :articles:servo-pdm-standard:amperkaservo.zip |Библиотека AmperkaServo для Arduino}}
* [[http://wiki.amperka.ru/js:servo|Библиотека для Espruino]]
* [[https://gpiozero.readthedocs.io/en/stable/api_output.html#angularservo|Библиотека для Raspberry Pi]]
* [[https://pypi.org/project/troykahat/|Библиотека для Troyka HAT]]
===== Полезные статьи =====
* [[articles:servo|Сервоприводы: устройство, принцип работы и основные виды]]
* [[:articles:servo-pdm-continuous-rotation|Сервоприводы PDM постоянного вращения: особенности применения и примеры кода]]
* [[:articles:servo-scs|Сервоприводы SCS: особенности применения и примеры кода]]
* [[:articles:servo-sts|Сервоприводы STS: особенности применения и примеры кода]]