Программирование Arduino — библиотека Servo


Servo library – библиотека для работы с сервомашинками

Как мы помним – сервомашинка – это мотор-редуктор, с обратной связью, благодаря которой можно повернуть выходной вал на строго определённый угол.
Стандартные рулевые машинки, вертятся от 0 до 180 градусов (также есть сервы постоянного вращения – т.н. Continuous Rotation Servo, чуть позже покажем, как обычную серву можно переделать до такого состояния).

Примечание:
В Arduino IDE 0017 библиотека Servo поддерживает до 12 серв (до 48 на Mega), а в IDE 0016 и ранее работает только на 9 и 10 пинах!

!Обратите внимание:
На платах, отличных от Mega, использование библиотеки отключает возможность использования analogWrite() (PWM) на пинах 9 и 10 (вне зависимости подключены к этим пинам сервы или нет). На платах Mega, до 12 серв могут использоваться без влияния на функциональность PWM, но использование от 12 до 23 сервомашинок отключит PWM на пинах 11 и 12.

Подключение
Схема включения сервомашики очень простая — у неё есть три провода:

— земля (коричневый/черный),
— питание +5 вольт (красный),
— сигнальный (оранжевый/желтый/белый).

Управляющий сигнал можно подавать напрямую с ноги МК, а вот силовое питание (особенно если задействовано более одной-двух серв) нужно подавать от внешнего источника питания (т.е. не от +5В Arduino). В этом случае – нужно не забыть соединить землю Arduino/CraftDuino с минусом внешнего источника питания.

Рассмотрим функции, которые предоставляет библиотека.

uint8_t attach(int pin);
uint8_t attach(int pin, int min, int max);

Описание:
Указываем пин к которому подключён управляющий провод сервы.

Примечание:
Версии Arduino IDE 0016 и младше позволяют подключение только к 9 и 10 пинам.

Синтаксис:

servo.attach(pin); 
servo.attach(pin, min, max);

Параметры:
(servo – объект класса Servo)
pin – номер порта к которому подключена серва

min (опционально) – ширина импульса в микросекундах устанавливающая положение вала сервы в 0 градусов (по-умолчанию 544)

max (опционально) — ширина импульса в микросекундах устанавливающая положение вала сервы в 180 градусов (по-умолчанию 2400)

Пример:

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
} 

void loop() {}

void write(int value);

Описание:
Устанавливаем угол поворота сервы в градусах.
В случае сервы постоянного вращения:
0 – вращение на полной скорости в одну сторону,
180 – вращение на полной скорости в другую сторону,
90 – нет вращения.

Синтаксис:

servo.write(angle);

Параметры:
angle – значение угла для поворота: от 0 до 180

Пример:

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
  myservo.write(90);  // поворачиваем серву на 90 градусов
} 

void loop() {}

void writeMicroseconds(int value);

Описание:
Задаёт значение в микросекундах для длительности управляющего импульса. На стандартных сервах это приведёт к повороту вала на определённый угол ( 1000 — положение полностью против часовой стрелки, 2000 — положение полностью по часовой стрелке, и 1500 — в середине).
Примечание:
Значения могут быть разными на сервах разных производителей. Например, от 700 до 2300. Это можно определить экспериментально – увеличивая значения, пока серва продолжает поворачиваться. Обратите внимание, что попытки управления сервой вне её конечных точек (при этом появляется рычащий звук) приводит к увеличению потребления тока и такого следует избегать.

Синтаксис:

servo.writeMicroseconds(uS);

Параметры:
uS – значение ширины импульса в микросекундах (int)

Пример:

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
  myservo.writeMicroseconds(1500);  // в среднее положение
} 

void loop() {}

int read();

Описание:
Считывает «текущий» угол поворота сервомашинки (значение, переданное в последнем вызове write()).

Синтаксис:

servo.read();

Возвращаемое значение:
Возвращает значение типа int — угол от 0 до 180 градусов.

Примечание:
Аналогично есть функция readMicroseconds();

bool attached();

Описание:
Определяем – есть ли привязка к серве через pin.

Синтаксис:

servo.attached();

Возвращаемое значение:
Возвращает true если есть привязка к pin-у и false – в противном случае.

void detach();

Описание:
Отключение пина от библиотеки Servo. Если все переменные Servo отключены – пины 9 и 10 можно использовать для PWM-вывода через analogWrite().

Синтаксис:

servo.detach();

Возвращаемое значение:
нет.

Рассмотрим пример работы библиотеки на примере Sweep, который поворачивает серву от 0 до 180 градусов и обратно (как-бы подметает).
File – Examples — Servo — Sweep

// Sweep
// by BARRAGAN  

#include <Servo.h> 
 
Servo myservo;  // создаём объект для контроля сервы 

int pos = 0;    // переменная для хранения позиции сервы 
 
void setup() 
{ 
  myservo.attach(9);  // серва подключена к 9-му пину
} 
 
 
void loop() 
{ 
  for(pos = 0; pos < 180; pos += 1)  // от 0 до 180 градусов
  {                                  // с шагом в 1 градус 
    myservo.write(pos);              // 
    delay(15);                       // ждём 15ms пока серва займёт новое положение
  } 
  for(pos = 180; pos>=1; pos-=1)     // от 180 до 0 градусов
  {                                
    myservo.write(pos);               
    delay(15);                       
  } 
}

Существуют и другие библиотеки:
SoftwareServo — http://www.arduino.cc/playground/ComponentLib/Servo — удобна одинаковым названием функций с системной библиотекой Servo
— она не ограничивает количество серв 8-ю, но требует для работы вызова метода
SoftwareServo::refresh()

Пример:

#include <SoftwareServo.h> 

SoftwareServo myservo; // объект сервы

int potpin = 0;  // пин для подключения потенциометра
int val;    	// переменная для хранения значения с аналогового входа

void setup() 
{ 
  myservo.attach(2);  // серва подключена ко 2-му пину
} 

void loop() 
{ 
  val = analogRead(potpin);            // считываем значение с потенциометра (величина от 0 до 1023) 
  val = map(val, 0, 1023, 0, 179);     // переводим в значение от 0 до 180) 
  myservo.write(val);                  // устанавливаем угол сервы 
  delay(15);                           // ждём поворота 

  SoftwareServo::refresh();
}

MegaServo — http://www.arduino.cc/playground/Code/MegaServo
— библиотека для более ранних версий IDE (в 0017 не подгрузится, т.к. она уже входит в состав IDE под именем Servo 🙂 — позволяет контролировать до 12 серв

Читать про сервы:
Сервы
Сервы 2. Взгляд под корпус.
Подключение сервомашинок к Arduino

Cсылки
http://arduino.cc/en/Reference/Servo


18 комментариев на «“Программирование Arduino — библиотека Servo”»

  1. Стандартные рулевые машинки, вертятся от 0 до 180 градусов (также есть сервы постоянного вращения – т.н. Continuous Rotation Servo, чуть позже покажем, как обычную серву можно переделать до такого состояния

    Очень нужно чтоб сервушка крутилась на 360гр. Порылся по моему у вас везде где можно, но не нашёл как это сделать. Подобное в сети очень много но не где не описывается как потом управлять такой переделанной сервой, и тем более с помощью CraftDuino. Если эта статья есть у вас уже на сайте подскажите где её искать. Заранее благодарен.

    • разумеется, можно — Подключение сервомашинок к Arduino:

      если сервы мощные, то стабилизатор питания контроллера будет очень сильно греться и может сгореть.
      Выход — использовать для питания сервомашинки отдельный регулятор напряжения (L7805, КР142ЕН5А и т.п.)

    • Вроде бы понял, поправьте меня, если неправильно.

      То есть, теоретически, к Uno можно подключить 14 (маломощных) серво, создать для них объекты:

      Servo servo0;
      Servo servo1;
      ...
      Servo servo13;

      потом назначить им порты:

      servo0.attach(0);
      servo1.attach(1);
      ...
      servo13.attach(13);

      и управлять ими с помощью:

      servo0.write(foo);
      servo1.write(foo);
      ...
      servo13.write(foo);
    • Вроде бы понял, поправьте меня, если неправильно.

      То есть, теоретически, к Uno можно подключить 14 (маломощных) серво, создать для них объекты:

      в UNO установлен контроллер ATmega8U2(ATmega328), а в библиотеке Servo имеется код:

      // Say which 16 bit timers can be used and in what order
      #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
      #define _useTimer5
      #define _useTimer1 
      #define _useTimer3
      #define _useTimer4 
      typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
      
      #elif defined(__AVR_ATmega32U4__)  
      #define _useTimer3
      #define _useTimer1 
      typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
      
      #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
      #define _useTimer3
      #define _useTimer1
      typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
      
      #elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
      #define _useTimer3
      #define _useTimer1
      typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
      
      #else  // everything else
      #define _useTimer1
      typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;                  
      #endif

      Согласно которому распределяется порядок подключения и количество таймеров в зависимости от модели контроллера, в списке IF-ов нет используемого в UNO контроллера, следовательно применяется ELSE, согласно которому будет задействован 1 таймер — №1. Далее по коду можно обнаружить следующий код:

      #define SERVOS_PER_TIMER       12     // the maximum number of servos controlled by one timer 
      #define MAX_SERVOS   (_Nbr_16timers  * SERVOS_PER_TIMER)

      говорящий что максимальное количество сервов определяется как произведения количества возможный таймеров на константу определяющую максимальное число сервоприводов на один таймер, равную 12 по всей видимости, стантартными приемами используя UNO и библиотеку servo можно включить 12 сервоприводов.

  2. Всем привет, переделал серву для вращения по кругу (360 градусов) подредактировал скетч но она вертится не останавливаясь. если подключая непеределаную серву она поворачивается на каждые 90 градусов. Но мне нужно все 360 а не 180. подскажите что не так.
    вот скетч
    #include <Servo.h>
    Servo myservo;

    void setup()
    {
    // устанавливаем пин как вывод управления сервой
    myservo.attach(10);
    }

    void loop()
    {
    // устанавливаем угол 0°
    myservo.write(0);
    delay(3000);
    // устанавливаем угол 90°
    myservo.write(90);
    delay(3000);
    // устанавливаем угол 180°
    myservo.write(180);
    delay(3000);
    // устанавливаем угол 270°
    myservo.write(270);
    delay(3000);
    }

    • ИМХО всё именно так как должно быть.
      Серву, простыми средствами, не заставить поворачиваться более чем на 180.
      Про устройство — тут.
      только если потенциометр обратной связи менять на многооборотный но тогда точность станет невысокой.
      Не могу знать как переделывали именно вы, но обычно сервы переделывают не столько на «360», сколько на «постоянное вращение» — см подробности.

    • Я убрал фиксатор, вместо потенциометра подпаял 2 резистора по 3,3к. значит невозможно сделать чтобы она останавливалась через каждые 90?

    • Так невозможно — вы же вытащили потенциометр серва теперь ничего не знает о своём текущем положении.
      Таки почитайте.

    • Спасибо, будем довольствоваться поворотом на 180. Попробую шаговый движок прикрутить для своих нужд.

  3. Здравствуйте. Помогите понять почему в новой версии arduino-1.0 при компиляции выдаётся вот такая ошибка:

    In file included from Proverka_pde.cpp:1:
    D:\Program Files\arduino-1.0-windows\arduino-1.0\libraries\SoftwareServo
    /SoftwareServo.h:4:22: error: WProgram.h: No such file or directory.

    Компилировал скетч который в этой статье в последнем примере. Также выдаются такие же ошибки в скетчах, где есть обращение в сторонние библиотеки. Делаю тоже самое в arduino-0022 — всё в порядке… В чём дело? помогите пожалуйста понять.

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение