Урок 1.6. Управление сервоприводом

Базовый курс "Программирование микроконтроллеров"
Модуль 1. Введение в Arduino. Работа с цифровым и аналоговым сигналом

Сервопривод

Наряду с контроллером и сенсорами, активаторы являются важным составляющим всех без исключения роботов. Они вращают колеса робота, позволяя ему перемещаться в пространстве, и приводят в действие мощные манипуляторы, которыми он хватает предметы.

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

Внутренне сервопривод устроен следующим образом:

Микромотор обладает большой скоростью вращения, но низким крутящим моментом;
Редуктор понижает скорость вращения мотора и увеличивает его крутящий момент;
Выходной вал соединен с потенциометром и через редуктор с мотором;
Потенциометр соединённый с выходным валом фиксирует угол поворота сервопривода. Так как потенциометр имеет ограниченный угол поворота, то и сервопривод ограничен углом поворота потенциометра;
Плата-контроллер считывает показания потенциометра – таким образом она понимает угол поворота сервопривода.

Управление сервоприводом с потенциометра

Соберем небольшой проект по управлению сервоприводом с помощью потенциометра. 

По сути, мы соберем проект электроусилителя, управлять углом поворота большой нагрузки мы будем с помощью потенциометра, управление которого требует небольших усилий пальцев. Примерами таких устройств могут служить электроусилитель руля, тяжелые клапаны управления потоком чего либо на заводах и прочее.

Соберем следующую схему:

Начнём с того, что научимся управлять сервоприводом, для этого подключим специальный программный блок называемый библиотекой. 

Библиотека — это набор модулей или функционала. Дело в том, что для управления и работы с некоторыми устройствами и модулями может быть довольно сложным и требовать в процессе разработки написать не один десяток строк кода. Библиотека упрощает разработку тем, что она содержит упакованный в простые функции сложный код, которым мы можем пользоваться.

Для того, что бы подключить библиотеку, мы должны прокликать следующие пункты меню Arduino IDE:
Скетч -> Подключить библиотеку -> Servo

Напишем код:

// Подключение библиотеки для работы с сервоприводом
#include <Servo.h>
// Создание объекта сервопривода 
Servo servo;
#define servo_pin 3

void setup() 
{
  Serial.begin(9600);
  // привязка сервопривода с именем servo к пину 3
  servo.attach(servo_pin);
}

void loop() {
// команда сервоприводу занять положение 0 градусов
servo.write(0);
delay(1000);
// команда сервоприводу занять положение 90 градусов
servo.write(90);
delay(1000);
// команда сервоприводу занять положение 180 градусов
servo.write(180);
delay(1000);
}

Загрузим программу и понаблюдаем за работой сервопривода.

Обратите внимание: во время работы сервопривода крайне не рекомендуется пытаться удержать его руками или другой нагрузкой - от больших нагрузок может выйти из строя мотор или редуктор сервопривода!

Теперь добавим в нашу программу управление сервоприводом ручкой потенциометра:

// Подключение библиотеки для работы с сервоприводом
#include <Servo.h>
// Создание объекта сервопривода 
Servo servo;
#define servo_pin 3
#define pot A0
// переменная для записи угла поворота
int angle = 0;

void setup() 
{
  Serial.begin(9600);
  // привязка сервопривода с именем servo к пину 3
  servo.attach(servo_pin);
  pinMode(pot,INPUT);
}

void loop() {
int val = analogRead(pot);
// масштабируем показания потенциометра в угол поворота сервопривода
angle = map(val,0,1023,0,180);
// команда сервоприводу занять положение angle градусов
servo.write(angle);
delay(10);
}

Загрузим программу и понаблюдаем как будет меняться положение вала сервопривода при вращении ручки потенциометра!

Управление сервоприводом с помощью кнопок

Теперь возьмём задачку посложнее, соберем кнопочный пульт управления сервоприводом.

Напишем и загрузим код для проверки всех компонентов:

// Подключение библиотеки для работы с сервоприводом
#include <Servo.h>
// Создание объекта сервопривода 
Servo servo;
#define servo_pin 3
#define btnUp 4
#define btnDown 5
// переменная для записи угла поворота
int angle = 0;
// переменная для записи состояний кнопок
byte stateUp = 0;
byte stateUpLast = 0;
byte stateDown = 0;
byte stateDownLast = 0;

void setup() 
{
  Serial.begin(9600);
  // привязка сервопривода с именем servo к пину 3
  servo.attach(servo_pin);
  pinMode(btnUp,INPUT);
  pinMode(btnDown,INPUT);
}

void loop() {
// считываем состояние кнопок
stateUp = digitalRead(btnUp);
stateDown= digitalRead(btnDown);
// выводим состояния кнопок в монитор порта
Serial.println("BTN UP = " + String(stateUp) + "  BTN DOWN = " + String(stateDown));
// проверяем работу сервопривода
servo.write(0);
delay(500);
servo.write(180);
delay(500);
}

Откроем монитор порта и прокликаем кнопки – мы должны увидеть, что в мониторе порта состояние кнопок изменяется корректно и сервопривод вращается.

Далее добавим отслеживание нажатий кнопок, и в зависимости от того, какая кнопка нажата – туда будет вращаться сервопривод.

// Подключение библиотеки для работы с сервоприводом
#include <Servo.h>
// Создание объекта сервопривода
Servo servo;
#define servo_pin 3
#define btnUp 4
#define btnDown 5
// переменная для записи угла поворота
int angle = 90;
// переменная для записи состояний кнопок
byte stateUp = 0;
byte stateUpLast = 0;
byte stateDown = 0;
byte stateDownLast = 0;

void setup() {
  Serial.begin(9600);
  // привязка сервопривода с именем servo к пину 3
  servo.attach(servo_pin);
  pinMode(btnUp, INPUT);
  pinMode(btnDown, INPUT);
}

void loop() {
  // считываем состояние кнопок
  stateUp = digitalRead(btnUp);
  stateDown = digitalRead(btnDown);
  if (stateUp) {
    angle++;
  }
  if (stateDown) {
    angle--;
  }
  // обрезаем значения угла поворота не входящих в диапазон от 0 до 180
  angle = constrain(angle, 0, 180);
  // поворачиваем вал сервопривода
  servo.write(angle);
  Serial.println("Angle = " + String(angle));
}

Как Вы можете заметить, в данном коде мы использовали новую функцию – constrain.

Синтаксис

result = constrain(x, a, b);

Параметры

x: переменная, значение которой необходимо ограничить, любой тип данных
a: нижний предел, любой тип данных
b: верхний предел, любой тип данных

Возвращаемые значения

x: если x лежит в пределах между a и b
a: если x меньше a
b: если x больше b

Строчка:

angle = constrain(angle, 0, 180);

эквивалента записи:

if (angle > 180)
    angle = 180;
else if (angle < 0)
    angle = 0;

Изменим наш код так, что бы сервопривод поворачивался на 10 градусов при каждом клике по кнопке:

// Подключение библиотеки для работы с сервоприводом
#include <Servo.h>
// Создание объекта сервопривода
Servo servo;
#define servo_pin 3
#define btnUp 4
#define btnDown 5
// переменная для записи угла поворота
int angle = 90;
// переменная для записи состояний кнопок
byte stateUp = 0;
byte stateUpLast = 0;
byte stateDown = 0;
byte stateDownLast = 0;

void setup() {
  Serial.begin(9600);
  // привязка сервопривода с именем servo к пину 3
  servo.attach(servo_pin);
  pinMode(btnUp, INPUT);
  pinMode(btnDown, INPUT);
}

void loop() {
  // считываем состояние кнопок
  stateUp = digitalRead(btnUp);
  stateDown = digitalRead(btnDown);
  if (stateUp && !stateUpLast) {
    angle = angle + 10;
  }
  if (stateDown && !stateDownLast) {
    angle = angle - 10;
  }
  // обрезаем значения угла поворта не вхлжящих в жиапозон от 0 до 180
  angle = constrain(angle, 0, 180);
  // поворачиваем вал сервопривода
  servo.write(angle);
  Serial.println("Angle = " + String(angle));
  stateUpLast = stateUp;
  stateDownLast = stateDown;
}

Отлично, Вы выполнили все задачи!