====== Сервоприводы 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: особенности применения и примеры кода]]