О сервоприводах
Сервопривод Ардуино (англ. — arduino servo) — устройство с электрическим мотором, которое можно повернуть на определенный угол и оставить в этом положении на определенное время.
Сервомоторы Ардуино по сути своей отличные устройства, которые могут поворачиваться в указанное положение и могут применяться в огромном количестве областей. Особенно сейчас их чаще всего применяют в робототехнике.
Обычно у них есть выходной вал, который может поворачиваться на 180 градусов. Используя Arduino мы можем задать сервомотору определенное положение в которое он перейдет.
Изначально сервоприводы начали использовать еще задолго до появления Ардуино, скажем так, в мире пультов дистанционного управления (RC), как правило, для управления рулевым колесом игрушечных машинок или крыльями самолетов. Со временем они нашли свое применение в робототехнике, автоматизации и, конечно же, в мире Ардуино.
В нашем материале мы увидим как подключить сервопривод Ардуино, а затем как управлять этим полезным механизмом и поворачивать его в определенные положения.
Демонстрационнаяпрограмма приведена ниже, показано, как использовать сервомоторов смикроконтроллером AVR. Работы программы очень проста, она начинается синициализации таймера и PWM.В начале фиксируеться сервопривод на 0 градусов, азатем перемещается на 90 градусов и подождатв некоторое время перемещается на135 градусов, и наконец, на 180градусов. Этот процесс повторяется до тех пор, пока привод подключен к питанию.
Параметрыдля правильной работы программы.
- LOW Fuse = 0xFF иHIGH Fuse = 0xC9
- Частота= 16 МГц.
- Сервомоторклеймо Futaba S3003.
- MCUявляется AtMega32 или однокристальный микроконтроллер ATmega16.
Случайные повороты
Будем поворачивать серводвигатель на случайную величину. Практического смысла немного, но для демонстрации подойдёт.
#include
Servo servo; // создадим объект сервопривода
long randomNumber;
void setup() {
servo.attach(9);
randomSeed( analogRead(A0) );
}
void loop() {
randomNumber = random(0, 181);
servo.write(randomNumber);
delay(500);
}
ТЕОРИЯ
Вы наверняка работали с сервоприводами из под Arduino и знаете, как это выглядит: сервоприводу можно приказать повернуться на угол, и он с максимальной скоростью начнёт поворачиваться на этот угол. Это очень неправильно применять в реальных устройствах, потому что создаются лишние нагрузки и растёт потребление тока (большой стартовый ток). Можно ли крутить серво плавно? Можно! Я сделал библиотеку ServoSmooth, которая в этом поможет.
Зачем это нужно? В реальных устройствах, где нужно сервой повернуть/подвинуть тяжёлый объект, стандартный подход (дать сигнал и ждать поворота) работает на уничтожение редуктора привода, потому что объекты инерционные и быстро их разогнать и остановить невозможно! Ограничив максимальную скорость серво, разгон и торможение мы продлеваем ресурс редуктора в десятки раз, а также потребляем меньший ток за счёт плавности прикладывания момента. И очевидно получаем приятный визуальный эффект – нет резких рывков всей конструкции при разгоне-остановке.
Так как ESC контроллеры используют такой же протокол связи, мы автоматически получаем плавный разгон и торможение для бесколлекторных моторов (в этом случае за ускорение мотора отвечает максимальная скорость, метод setSpeed. Подумайте, это уже производная). И это круто!
[УСТАРЕЛО] Алгоритм работы для любопытных: работает всё на экспоненциальном бегущем среднем, именно оно обеспечивает плавный разгон и торможение. Ограничение скорости делается “дроблением” поворота серво по времени: серво поворачивается на несколько градусов по таймеру.
Старый алгоритм//по таймеру:
_newSpeed = _servoTargetPos — _servoCurrentPos; // расчёт скорости
if (_servoState) {
_newSpeed = constrain(_newSpeed, -_servoMaxSpeed, _servoMaxSpeed); // ограничиваем по макс.
_servoCurrentPos += _newSpeed; // получаем новую позицию
_newPos += (float)(_servoCurrentPos — _newPos) * _k; // и фильтруем её
_newPos = constrain(_newPos, _min, _max); // ограничиваем
_servo.writeMicroseconds(_newPos); // отправляем на серво
}
Новый алгоритм работает по другому, обеспечивая более плавный разгон. Ускорение осуществляется двойным интегрированием позиции: к ней прибавляется скорость, к которой прибавляется ускорение. Торможение начинается с момента, полученного из школьной формулы S=V*V/(2*a). Для любознательных прикреплю алгоритм ниже.
Новый алгоритмfloat err = _targetPos — _currentPos;
if (abs(err) > 0.1) {
bool thisDir = (_speed * _speed / _maxAcceleration / 2.0 >= abs(err)); // пора тормозить
_speed += _maxAcceleration * delta * (thisDir ? -_sign(_speed) : _sign(err));
_speed = constrain(_speed, -_maxSpeed, _maxSpeed);
_currentPos += _speed * delta;
}
Как это работает
Сервоприводы Arduino — это умные устройства. Используя только один входной пин, они получают значения для позиционирования от микроконтроллера и переходят в это положение. Как можно увидеть на рисунке в самом начале статьи внутри они имеют двигатель и цепь обратной связи, которая гарантирует, что вал/рычаг сервопривода достигнет желаемого положения.
Но какой сигнал сервомоторы получают на входе? Это прямоугольная волна, подобная PWM (англ. — pulse-width modulation, широтно-импульсная модуляция). Каждый цикл в сигнале длится 20 миллисекунд, и большая часть времени в значении LOW. В начале каждого цикла значение сигнала становится HIGH на время от 1 до 2 миллисекунд.
При 1 миллисекунде она составляет 0 градусов, а при 2 миллисекундах — 180 градусов, а в промежутке значение от 0 до 180. Это очень хороший и надежный метод. График выше упрощает понимание.
Схема и типы сервоприводов
Принцип работы сервопривода основан на обратной связи с одним или несколькими системными сигналами. Выходной показатель подается на вход, где сравнивается его значение с задающим действием и выполняются необходимые действия – например, выключается двигатель. Самым простым вариантов реализации является переменный резистор, который управляется валом – при изменении параметров резистора меняются параметры питающего двигатель тока.
В реальных сервоприводов механизм управления гораздо сложнее и использует встроенные микросхемы-контроллеры. В зависимости от типа используемого механизма обратной связи выделяют аналоговые и цифровые сервоприводы. Первые используют что-то, похожее на потенциометр, вторые – контроллеры.
Вся схема управления серво находится внутри корпуса, управляющие сигналы и питание подаются, как правило, идут по трем проводам: земля, напряжение питания и управляющий сигнал.
Сервопривод непрерывного вращения 360, 180 и 270 градусов
Выделяют два основных вида серводвигателей – с непрерывным вращением и с фиксированным углом (чаще всего, 180 или 270 градусов). Отличие серво ограниченного вращения заключается в механических элементах конструкции, которые могут блокировать движение вала вне заданных параметрами углов. Достигнув угла 180, вал окажет воздействие на ограничитель, а тот отдаст команду на выключение мотора. У серводвигателей непрерывного вращения таких ограничителей нет.
Материалы шестерней сервопривода
У большинства сервоприводов связующим звеном между валом и внешними элементами является шестеренка, поэтому очень важно, из какого материала она сделана. Наиболее доступных вариантов два: металлические или пластмассовые шестерни. В более дорогих моделях можно найти элементы из карбона и даже титана.
Пластмассовые варианты, естественно, дешевле, проще в производстве и часто используются в недорогих моделях серво. Для учебных проектов, когда сервопривод делает несколько движений, это не страшно. Но в серьезных проектах использование пластмассы невозможно, в виду очень быстрого снашивания таких шестеренок под нагрузкой.
Металлические шестеренки надежнее, но это, безусловно, сказывается как на цене, так и на весе модели. Экономные производители могут сделать часть деталей пластмассовыми, а часть металлическими, это тожно нужно иметь в виду. Ну и, естественно, что в самых дешевых моделях даже наличие металлической шестеренки не является гарантией качества.
Титановые или карбоновые шестерни – самый предпочтительный вариант, если вы не ограничены бюджетом. Легкие и надежные, такие сервоприводы активно используются для создания моделей автомобилей, дронов и самолетов.
Преимущества серводвигателей
Широкое использование сервоприводов связано с тем, что они обладают стабильной работой, высокой устойчивостью к помехам, малыми габаритами и широким диапазоном контроля скорости. Важными особенностями сервоприводов являются способность увеличивать мощность и обеспечение обратной информационной связи. И этого следует, что при прямом направлении контур является передатчиком энергии, а при обратном – передатчиком информации, которая используется для улучшения точности управления.
Отличия серво и обычного двигателя
Включая или выключая обычный электрический двигатель, мы можем сформировать вращательное движение и заставить двигаться колеса или другие предметы, прикрепленные к валу. Движение это будет непрерывным, но для того, чтобы понять, на какой угол повернулся вал или сколько оборотов он сделал, потребуется устанавливать дополнительные внешние элементы: энкодеры. Сервопривод уже содержит все необходимое для получения информации о текущих параметрах вращения и мжет самостоятельно выключаться, когда вал повернется на необходимый угол.
Отличия серво и шагового мотора
Важным отличием серводвигателя от шагового двигателя является возможность работать с большими ускорениями и при переменной нагрузке. Также серводвигатели обладают более высокой мощностью. Шаговые двигатели не обладают обратной связью, поэтому может наблюдаться эффект потери шагов, в серводвигателях потери шагов исключены – все нарушения будут зафиксированы и исправлены. При всех этих явных преимуществах серводвигатели являются более дорогостоящими приборами, чем шаговые двигатели, обладают более сложной системой подключения и управления и требуют более квалифицированного обслуживания. Важно отметить, что шаговые двигатели и сервоприводами не являются прямыми конкурентами – каждое из этих устройств занимает свою определенную сферу применения.
Комплектующие
Нам понадобятся следующие детали:
- Плата Arduino (подключенная к компьютеру через USB), подойдет Arduino Uno;
- Сервопривод;
- Перемычки.
В мире сервомоторов мало известных брендов. Как пример, можно взять Hitec и Futaba, которые являются ведущими производителями сервоприводов для RC-моделей. Но в целом найти подходящий на АлиЭкспресс и подобных сайтах не сложно.
Подключение сервопривода к Ардуино
Схема подключения ниже:
Сервомотор имеет много встроенных деталей: двигатель, цепь обратной связи и, самое главное, драйвер мотора. Ему просто нужно дополнительно питание, земля и один контрольный пин. Ниже шаги для подключения сервопривода к Arduino, но вы можете всегда свериться с изображением выше.
- Подключите Землю к GND Arduino.Сервомотор имеет гнездовой разъем с тремя контактами. Самый темный или даже черный — это обычно земля.
- Подключите кабель питания, который по всем стандартам должен быть красным к 5В на Ардуино.
- Подключите оставшийся контакт разъема сервопривода к цифровому выходу на Arduino.
Также ниже приводим пример подключения двигателя и Arduino Diecimilia. Фото найдено на официальном сайте производителя микроконтроллеров.
Для этого варианта подключение следующее:
- Подключите красный от сервопривода к +5 В на ардуине.
- Подключите черный/коричневый от сервопривода к Gnd на ардуино.
- Подключите белый/оранжевый от сервопривода к аналоговому 0 на arduino.
БИБЛИОТЕКА
ServoSmooth v3.8
GITHUBСКАЧАТЬ
Библиотека для плавного управления сервоприводами
- Является дополнением к стандартной библиотеке Servo
- Поддерживает работу с расширителем серво PCA9685 (начиная с v3.0)
- Настройка максимальной скорости сервопривода
- Настройка ускорения (разгон и торможение) сервопривода
- Плавный пуск из любого положения при запуске программы (начиная с v3.2)
- При использовании ESC и БК мотора получаем “плавный пуск” мотора
- Установка целевой позиции серво по углу (0-180) и длине импульса (500-2400)
- Автоматическое отключение привода по таймауту неактивности и включение при изменении позиции (настраивается)
- Нативная поддержка серво с любым диапазоном по углу (180, 270, 360), см. документацию
Поддерживаемые платформы: все Arduino-совместимые платы (библиотека является дополнением к стандартной библиотеке Servo и PCA9685)
Sweep
Скетч File | Examples | Servo | Sweep постоянно поворачивает насадку на 180 градусов и возвращает её обратно. В примере используется встроенная библиотека Servo.
Общая схема — красный провод идёт к питанию 5V, чёрный или коричневый идёт к GND, а жёлтый или белый к выводу платы (в нашем примере вывод 9).
#include
Servo myservo; // создадим объект сервопривода
int pos = 0; // начальная позиция
void setup() {
myservo.attach(9); // сервопривод на выводе 9
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // от 0 до 180 градусов
// шаг в один градус
myservo.write(pos); // просим повернуться на позицию значения переменной 'pos'
delay(15); // ждём 15ms для достижения позиции
}
for (pos = 180; pos >= 0; pos -= 1) { // от 180 до 0 градусов
myservo.write(pos); // просим повернуться на позицию значения переменной ‘pos’
delay(15); // ждём 15ms для достижения позиции
}
}
ДОКУМЕНТАЦИЯ
Документация
Данная библиотека является «дополнением» к стандартной библиотеке Servo.h и позволяет плавно управлять сервоприводом. Суть работы кроется в методе tick(), который нужно вызывать постоянно в loop (или прерывании таймера), внутри тика находится алгоритм с собственным таймером, который по чуть чуть поворачивает серво к нужному положению. Библиотека дублирует несколько методов из Servo.h (attach имеет расширенную инициализацию):
- write() и writeMicroseconds() — повернут вал серво с максимальной скоростью
- attach() и detach() — подключить и отключить серво от управления
Инициализация
Объект создаётся точно так же, как в Servo.h, без параметров. Также можно передать рабочий угол серво (если не передавать, будет равен стандартному 180 град.)
#include «ServoSmooth.h» // подключили либу
ServoSmooth servo; // создали объект
ServoSmooth servo(270); // создали с указанием макс. угла серво
По инициализации attach() есть несколько вариантов:
- attach(pin); — подключит серво на указанный pin, угол поворота будет установлен на 0 градусов. Длина импульса* мин-макс будет стандартная, 500-2400 мкс
- attach(pin, target); — подключит серво на указанный pin, угол поворота** будет установлен на target градусов. Длина импульса* мин-макс будет стандартная, 500-2400 мкс
- attach(pin, min, max); — подключит серво на указанный pin, угол поворота будет установлен на 0 градусов. Длина импульса* будет установлена min и max соответственно.
- attach(pin, min, max, target); — подключит серво на указанный pin, угол поворота будет установлен на target градусов. Длина импульса* будет установлена min и max соответственно.
*Длина импульса — сервопривод управляется ШИМ сигналом, в котором длина импульса прямо управляет углом поворота, то есть подавая минимальную и максимальную длину мы получаем рабочий угол 180 градусов. По умолчанию мин. и макс. длина установлены 500 и 2400 соответственно, что подходит большинству сервоприводов, но желательно посмотреть и «откалибровать» свой привод так, чтобы он работал на все 180 градусов. Мин. и макс. время импульса отличаются у разных производителей и моделей серво.
**Указание угла поворота при инициализации устанавливает серво на нужный угол сразу при подаче сигнала, а также выставляет текущую и целевую позицию равными этой.
Плавный пуск (new!)
Сервопривод не имеет обратной связи по углу (для программы), поэтому при запуске будет «резко» повёрнут на стартовый угол («в ноль» по умолчанию или на указанный в attach(pin, target). Есть два варианта избежать резких рывков в механизме при запуске программы:
- Заранее знать, на какой угол физически повёрнут привод при запуске и передать его в attach(pin, target). Как узнать? Зависит от конкретной задачи и логики работы программы. Можно запоминать положение сервы в ЕЕПРОМ и восстанавливать при запуске, можно устанавливать серво в один и тот же угол перед выключением/перезагрузкой системы, и т.д.
- Воспользоваться фичей smoothStart(), которая появилась в версии 3.2 данной библиотеки. Работает она очень просто: аттачит и детачит сервопривод с периодом в пару десятков миллисекунд, таким образом привод плавно движется до заданного угла из любого начального положения. Вызывать smoothStart() нужно однократно (при старте программы) сразу после attach(pin, target) в блоке setup(). Внимание! Функция блокирующая, выполнение занимает 900 миллисекунд. Период «рывка» сервопривода выбран минимальный, при котором серво начинает понимать, чего от неё хотят. Период довольно большой, поэтому движение к заданной позиции происходит рывками, но в целом гораздо плавнее, чем без smoothStart(). В массивном механизме рывки практически незаметны!
servo.attach(2, 35); // стартовый угол 35 градусов
servo.smoothStart(); // «плавно» движемся к нему
Управление
Движение серво происходит автоматически в методе tick(), нам нужно всего лишь вызывать его как можно чаще в loop() (tick() имеет встроенный таймер на 20 миллисекунд). Также есть метод tickManual(), который поворачивает серву на следующий «шаг» при каждом вызове (тот же tick(), но не имеет своего таймера). Оба метода tick() возвращают false, пока серво движется, и true, когда серво достигла установленного угла, это можно использовать. Также серво автоматически отключается от управления при достижении заданного угла поворота (это уменьшает жужжание серво в простое). Эту функцию можно отключить, вызвав setAutoDetach(false). Инструменты для управления движением привода:
- setTarget(длина); — устанавливает целевую позицию для серво в величине длина импульса, мкс (~500-2400)
- setTargetDeg(угол); — устанавливает целевую позицию для серво в градусах (0-180)
- setSpeed(скорость); — установка максимальной скорости (больше нуля) в градусах в секунду
- setAccel(ускорение); — установка ускорения (float числа 0.01 — 1.0). Можно больше 1, будет ещё резче. Если установить ускорение 0 — оно будет отключено и серво будет двигаться по профилю постоянной скорости (с бесконечным ускорением)
- Если передавать ускорение в целых числах (с версии 3.7 библиотеки) — ускорение будет установлено в градусах/сек/сек. Рабочий диапазон ускорений 1 — 1500, чем больше — тем резче. При значении 0 ускорение будет отключено.
- start(); — автоматический attach + разрешает работу tick — серво движется к заданной позиции
- stop(); — detach + запрещает работу tick — серво останавливается
Полезные вспомогательные методы для различных ситуаций:
- setDirection(напр); — принимает NORMAL (false) или REVERSE (true), меняет направление серво
- setCurrent(длина); — установка текущей позиции в мкс (500 — 2400). Может пригодиться в ситуации, когда мы знаем реальный угол серво и хотим сообщить о нём программе, чтобы алгоритм не дёргал привод.
- setCurrentDeg(угол); — установка текущей позиции в градусах (0-180). Зависит от min и max.
- getCurrent(); — получение текущей позиции в мкс (500 — 2400)
- getCurrentDeg(); — получение текущей позиции в градусах (0-180). Зависит от min и max
- getTarget(); — получение целевой позиции в мкс (500 — 2400)
- getTargetDeg(); — получение целевой позиции в градусах (0-180). Зависит от min и max
- setMaxAngle(); — установка макс. угла серво, по умолчанию 180. Позволяет удобно работать с разными сервами (на 270 и 360 градусов)
Расширитель серво PCA9685
В версии библиотеки 3 и выше добавлена поддержка драйвера PCA9685, подключать нужно файл #include «ServoDriverSmooth.h»
- ServoDriverSmooth servo; // по умолчанию (адрес 0x40, угол 180)
- ServoDriverSmooth servo(0x40); // с указанием адреса драйвера
- ServoDriverSmooth servo(0x40, 270); // с указанием адреса и макс. угла
Метод attach(pin) принимает номер вывода на драйвере. В остальном всё работает точно так же, как с обычной сервой.
Список функций void write(uint16_t angle); // аналог метода из библиотеки Servo
void writeMicroseconds(uint16_t angle); // аналог метода из библиотеки Servo
void attach(uint8_t pin); // аналог метода из библиотеки Servo
void attach(uint8_t pin, int min, int max); // аналог метода из библиотеки Servo. min по умолч. 500, max 2400
void detach(); // аналог метода detach из библиотеки Servo
void start(); // attach + разрешает работу tick
void stop(); // detach + запрещает работу tick
boolean tick(); // метод, управляющий сервой, должен опрашиваться как можно чаще.
// Возвращает true, когда целевая позиция достигнута.
// Имеет встроенный таймер с периодом SERVO_PERIOD
boolean tickManual(); // метод, управляющий сервой, без встроенного таймера.
// Возвращает true, когда целевая позиция достигнута
void setSpeed(int speed); // установка максимальной скорости (градусы в секунду)
void setAccel(float accel); // установка ускорения (0.05 — 1.0). При значении 1 ускорение максимальное. 0 — отключено
void setAccel(int accel); // установка ускорения в градусах/сек/сек (рабочее от 1 до ~1500). 0 — отключено
void setTarget(int target); // установка целевой позиции в мкс (500 — 2400)
void setTargetDeg(int target); // установка целевой позиции в градусах (0-макс. угол). Зависит от min и max
void setAutoDetach(boolean set); // вкл/выкл автоматического отключения (detach) при достижении угла. По умолч. вкл
void setCurrent(int target); // установка текущей позиции в мкс (500 — 2400)
void setCurrentDeg(int target); // установка текущей позиции в градусах (0-макс. угол). Зависит от min и max
void setMaxAngle(int maxAngle); // установка макс. угла привода
int getCurrent(); // получение текущей позиции в мкс (500 — 2400)
int getCurrentDeg(); // получение текущей позиции в градусах (0-макс. угол). Зависит от min и max
int getTarget(); // получение целевой позиции в мкс (500 — 2400)
int getTargetDeg(); // получение целевой позиции в градусах (0-макс. угол). Зависит от min и max
void smoothStart(); // вызывать сразу после attach(пин, таргет). Смягчает движение серво из неизвестной позиции к стартовой. БЛОКИРУЮЩАЯ НА 1 СЕК!
Наш алгоритм
Алгоритм, разработанный нами, был придуман в процессе работы над этим проектом.
Сигналы для управления сервоприводами формируются один за другим, что приводит к ограничению — на один таймер не более 8 приводов.
Сигналы для нескольких приводов
Принцип формирования следующий:
- Запускаем таймер задав какое-то начального значение для прерывания совпадения.
- Задаем и обнуляем некоторую переменную, которая будет считать такты. Для каждого сервопривода требуется два такта: фронт импульса и спад.
- При первом попадании в прерывании (о чем узнаем по состоянию счетчика) выводим на пин единицу, записываем в регистр совпадения требуемую длительность импульса и увеличиваем счетчик .
- При втором срабатывании прерывания проверяем счетчик, выводим на пин 0, записываем в регистр сколько тиков осталось до начала импульса для второго сервопривода и так далее.
Мы реализовывали алгоритм на микроконтроллере Atmega16. У него на борту имеется 16-ти битный таймер. Тактовая частота в нашем проекте была 8МГц, поэтому таймер мы запустили с делителем 8. В нашем случае требовалось управлять четырьмя приводами, поэтому весь период мы разделили на части по 5000мкс. Углы задаются в основном цикле программы прямо в микросекундах от 700 до 2300.
Скетч для сервопривода Ардуино
Скетч ниже заставит сервопривод переместиться в позицию 0 градусов, подождать 1 секунду, затем повернуться на 90 градусов, подождать еще одну секунду, после повернуться на 180 градусов и перейти в первоначальное положение.
Также дополнительно мы используем библиотеку servo — скачайте ниже или в нашем разделе Библиотеки.
Содержимое zip-файла размещается в папку arduino-xxxx/hardware/liraries.
Скачать библиотеку servo .zip Скачать .ino
Скетч № 1
// Подклоючаем библиотеку Servo
#include
// Пин для сервопривода
int servoPin = 3;
// Создаем объект
Servo Servo1;
void setup() {
// Нам нужно подключить сервопривод к используемому номеру пина
Servo1.attach(servoPin);
}
void loop(){
// 0 градусов
Servo1.write(0);
delay(1000);
// 90 градусов
Servo1.write(90);
delay(1000);
// 180 градусов
Servo1.write(180);
delay(1000);
}
Если сервомотор подключен к другому цифровому контакту, просто измените значение servoPin на значение используемого цифрового вывода.
Помните! Использование библиотеки Servo автоматически отключает функцию PWM для PWM-контактов 9 и 10 на Arduino UNO и аналогичных платах.
Наш код просто объявляет объект и затем инициализирует сервопривод с помощью функции servo.attach(). Мы не должны забывать подключать серво библиотеку. В цикле мы устанавливаем сервопривод на 0 градусов, ждем, а затем устанавливаем его на 90, а затем на 180 градусов.
Скетч № 2
Второй скетч для варианта с Arduino Diecimilia ниже.
Нам достаточно будет скачать и подключить библиотеку из архива:
Скачать servo .zip
Сам код такой:
#include
Servo servo1; Servo servo2;
void setup() {
pinMode(1,OUTPUT);
servo1.attach(14); //analog pin 0
//servo1.setMaximumPulse(2000);
//servo1.setMinimumPulse(700);
servo2.attach(15); //analog pin 1
Serial.begin(19200);
Serial.println(«Ready»);
}
void loop() {
static int v = 0;
if ( Serial.available()) {
char ch = Serial.read();
switch(ch) {
case ‘0’…’9′:
v = v * 10 + ch — ‘0’;
break;
case ‘s’:
servo1.write(v);
v = 0;
break;
case ‘w’:
servo2.write(v);
v = 0;
break;
case ‘d’:
servo2.detach();
break;
case ‘a’:
servo2.attach(15);
break;
}
}
Servo::refresh();
}
Knob
Скетч File | Examples | Servo | Knob управляет сервоприводом при помощи потенциометра. В примере используется встроенная библиотека Servo.
Общая схема: у сервопривода — красный провод идёт к питанию 5V, чёрный или коричневый идёт к GND, а жёлтый или белый к выводу платы (в нашем примере вывод 9). У потенциометра средняя ножка соединяется с аналоговым выходом A0, остальные к питанию и земле.
#include
Servo myservo; // создадим объект сервопривода
int potpin = 0; // аналоговый выход A0 для потенциометра
int val; // значение, получаемое от аналогового выхода
void setup() {
myservo.attach(9); // сервопривод на выводе 9
}
void loop() {
val = analogRead(potpin); // считываем данные с потенциометра (от 0 до 1023)
val = map(val, 0, 1023, 0, 180); // Преобразуем в интервал от 0 до 180
myservo.write(val); // устанавливаем позицию сервопривода
delay(15); // небольшое ожидание, чтобы сервопривод успел выполнить команду
}
Скетч для управления сервоприводом в Arduino
Управление сервоприводом напрямую через изменение в скетче длительности импульсов – достаточно нетривиальная задача, но у нас, к счастью, есть отличная библиотека Servo, встроенная в среду разработки Arduino. Все нюансы программирования и работы с сервоприводами мы рассмотрим в отдельной статье. Здесь же приведем простейший пример использования Servo.
Алгоритм работы прост:
- Для начала мы подключаем Servo.h
- Создаем объект класса Servo
- В блоке setup указываем, к какому пину подключен серво
- Используем методы объекта обычным для C++ способом. Самым популярным является метод write, которому мы подаем целочисленное значение в градусах (для сервопривода 360 эти значения будут интерпретироваться по-другому).
Пример простого скетча для работы с сервоприводом
Пример проекта, в котором мы сразу сначала устанавливаем серводвигатель на нулевой угол, а затем поворачиваем на 90 градусов.
#include
Servo servo; // Создаем объект
void setup() {
servo.attach(9); // Указываем объекту класса Servo, что серво присоединен к пину 9
servo1.write(0); // Выставляем начальное положение
}
void loop() {
servo.write(90); // Поворачиваем серво на 90 градусов
delay(1000);
servo.write(1800);
delay(100);
servo.write(90);
delay(1000);
servo.write(0);
delay(1000);
}
Скетч для двух сервпоприводов
А в этом примере мы работаем сразу с двумя сервоприводами:
#include
Servo servo1; // Первый сервопривод
Servo servo2; // Второй сервопривод
void setup() {
servo1.attach(9); // Указваем объекту класса Servo, что серво присоединен к пину 9
servo2.attach(10); // А этот servo присоединен к 10 пину
}
void loop() {
// Выставялем положения
servo1.write(0);
servo2.write(180);
delay(20);
// Меняем положения
servo2.write(0);
servo1.write(180);
}
Управление сервоприводом с помощью потенциометра
В этом примере поворачиваем серво в зависимости от значения, полученное от потенциометра. Считываем значение и преобразовываем его в угол с помощи функции map:
//Фрагмент стандартного примера использования библиотеки Servo
void loop() {
val = analogRead(A0); // Считываем значение с пина, к которому подключен потенциометр
val = map(val, 0, 1023, 0, 180); // Преобразуем число в диапазоне от 0 до 1023 в новый диапазон — от 0 до 180.
servo.write(val);
delay(15);
}
Стандартные методы серво-библиотеки
attach(int)
Соединение пина и сервопривода. Вызывает pinMode. Возвращает 0 при ошибке.
detach()
Отсоединение пина от сервопривода.
write(int)
Установка угла сервопривода в градусах, от 0 до 180.
read()
Возвращает значение, установленное write(int).
attached()
Возвращает 1, если серво в настоящее время подключен.
Где купить популярные серво SG90, MG995, MG996
Самый доступный вариант сервопривода SG90 1.6KG |
Сервоприводы SG90 и MG90S для Ардуино по цене ниже 70 рублей |
Еще один вариант серво SG90 Pro 9g от проверенного поставщика на Али |
Servo SG90 от надежного поставщика RobotDyn |
Тестер для серво |
Несколько вариантов тестеров сервоприводов |
Защищенные сервопривод с моментом 15 кг |
Серво JX DC5821LV 21KG Full waterproof Core mental gear 1/8 1/10 RC car Scaler Buggy Crawler TRAXXAS RC4WD TRX-4 SCX10 D90 |
Серво MG996R MG996 Servo Metal Gear for Futaba JR |
Серво 13KG 15KG Servos Digital MG995 MG996 MG996R Servo Metal Gear |
Дополнительные примеры скетчей
Следующий код позволяет вам контролировать серводвигатель на пине 2 с помощью потенциометра на аналоговом 0.
#include
SoftwareServo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup()
{
myservo.attach(2); // attaches the servo on pin 2 to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
SoftwareServo::refresh();
}
Следующий код — это поворот (пинг/понг) на выводе A0 с переменной скоростью.
#include
SoftwareServo myservo; // create servo object to control a servo
#define pinServo A0
int speed = 1;
int limits[2] = {30,150}; // set limitations (min/max: 0->180)
boolean refresh = false; // toggle refresh on/off
void setup()
{
Serial.begin(9600);
// attaches the servo on pin to the servo object
myservo.attach(pinServo);
// init angle of servo inbetween two limitations
myservo.write((limits[1]-limits[0])/2);
}
void loop()
{
// refresh angle
int angle = myservo.read();
// change direction when limits
if (angle >= limits[1] || angle <= limits[0]) speed = -speed;
myservo.write(angle + speed);
// set refresh one time / 2
refresh = refresh ? false : true;
if (refresh) SoftwareServo::refresh();
Serial.print("Angle: ");
Serial.println(angle);
}
Управляем через импульсы
Для начала попробуем управлять вручную без библиотек. Считываем показания из Serial Monitor — нужно ввести число от 0 до 9. Эти значения равномерно распределим на 180 градусов и получим 20 градусов на каждую единицу показаний.
int servoPin = 9; // сигнальный провод от серво на порт 9
int val;
void setup()
{
pinMode(servoPin, OUTPUT);
Serial.begin(9600);
Serial.println(«Servo is ready»);
}
void loop()
{
// convert number 0 to 9 to corresponding 0-180 degree angle
val = Serial.read();
if (val >= ‘0’ && val <= '9')
{
val = val - '0'; // convert to numerical variable
val = val * (180 / 9); // convert number to angle
Serial.print("moving servo to ");
Serial.print(val, DEC);
Serial.println();
// giving the servo time
//to rotate to commanded position
for (int i = 0; i <= 50; i++)
{
servoPulse(servoPin, val);
}
}
}
// define a servo pulse function
void servoPulse(int pin, int angle)
{
// convert angle to 500-2480 pulse width
int pulseWidth = (angle * 11) + 500;
digitalWrite(pin, HIGH); // set the level of servo pin as high
delayMicroseconds(pulseWidth); // delay microsecond of pulse width
digitalWrite(pin, LOW); // set the level of servo pin as low
delay(20 - pulseWidth / 1000);
}
Дополнительные возможности
Управление сервоприводами на Ардуино очень простое и мы можем использовать еще несколько интересных фишек.
Контроль точного времени импульса
Ардуино имеет встроенную функцию servo.write(градусы), которая упрощает управление сервомоторами. Однако не все сервоприводы соблюдают одинаковые тайминги для всех позиций. Обычно 1 миллисекунда означает 0 градусов, 1,5 миллисекунды — 90 градусов, и, конечно, 2 миллисекунды означают 180 градусов. Некоторые сервоприводы имеют меньший или больший диапазон.
Для лучшего контроля мы можем использовать функцию servo.writeMicroseconds(микросекунды), которая в качестве параметра принимает точное количество микросекунд. Помните, 1 миллисекунда равна 1000 мкс.
Несколько сервоприводов
Чтобы использовать более одного сервопривода в Ардуино нам нужно объявить несколько серво-объектов, прикрепить разные контакты к каждому из них и обратиться к каждому индивидуально. Итак, нам нужно объявить объекты — столько сколько нам нужно:
// Создаем объекты
Servo Servo1, Servo2, Servo3;
Затем нам нужно прикрепить каждый объект к сервомотору. Помните, что каждый сервопривод использует отдельный пин:
Servo1.attach(servoPin1);
Servo2.attach(servoPin2);
Servo3.attach(servoPin3);
В конце концов, мы должны обращаться к каждому объекту индивидуально:
Servo1.write(0); // Задать для Servo 1 позицию в 0 градусов
Servo2.write(90); // Задать для Servo 2 позицию в 90 градусов
Подключение. Земля сервоприводов идёт на GND Arduino, питание на 5В или VIN (в зависимости от входа). И, в конце концов, каждый привод должен быть подключен к отдельному цифровому выводу.
Вопреки распространенному мнению, сервоприводами не нужно управлять через пины PWM — любой цифровой пин подойдет и будет работать.
Управление мышью
Чтобы управлять серво с помощью мыши, вот простой код:
/**
* Servocontrol (derived from processing Mouse 1D example.)
*
* Updated 24 November 2007
*/
// Use the included processing code serial library
import processing.serial.*;
int gx = 15;
int gy = 35;
int spos=90;
float leftColor = 0.0;
float rightColor = 0.0;
Serial port; // The serial port
void setup()
{
size(720, 720);
colorMode(RGB, 1.0);
noStroke();
rectMode(CENTER);
frameRate(100);
println(Serial.list()); // List COM-ports
//select second com-port from the list
port = new Serial(this, Serial.list()[1], 19200);
}
void draw()
{
background(0.0);
update(mouseX);
fill(mouseX/4);
rect(150, 320, gx*2, gx*2);
fill(180 — (mouseX/4));
rect(450, 320, gy*2, gy*2);
}
void update(int x)
{
//Calculate servo postion from mouseX
spos= x/4;
//Output the servo position ( from 0 to 180)
port.write(«s»+spos);
// Just some graphics
leftColor = -0.002 * x/2 + 0.06;
rightColor = 0.002 * x/2 + 0.06;
gx = x/2;
gy = 100-x/2;
}
Вам не обязательно использовать этот код, вы также можете отправлять команды на плату arduino с серийного монитора Arduino IDE. Позиция сервопривода от 0 до 180 — это команды 0 и 180 сек соответственно.
В основном этот код берет позицию mouseX (от 0 до 720) и делит на 4, чтобы получить угол для сервопривода (0-180). Наконец, значение выводится на последовательный порт с префиксом ‘s’.
Примечание: «s» на самом деле должен быть суффиксом, но поскольку это повторяется, это не имеет значения для результата.
Не забудьте сначала проверить с помощью println(Serial.list ()) COM-порт, который следует использовать.