Сервопривод позволяет поворачивать вал двигателя в диапазоне от 0 до 180 градусов. Его часто используют в различных моделях, для поворота рулей. В последнее время их используют в сочленениях роботизированных механизмов. Сервопривод управляется импульсными сигналами (PWM, или ШИМ –сигналами):

Минимальная длительность импульса соответствует углу 0, а максимальная – углу 180 градусов. Но эти значения различаются у различных производителей сервоприводов, а порой меняются и у одинаковых моделей. У наиболее распространённых моделей длительность импульса 544ms соответствует углу 0, а значение 2400ms углу 180 градусов. Но для более точного управления сервоприводами приходится подбирать точные значения минимальной и максимальной длительности импульса. В данном занятии разберём несколько скетчей, которые упрощают подбор этих параметров сервопривода.
Для тестирования сервопривода соберите следующую схему:

Для питания сервопривода требуется отдельно питание, т.к. ток при его вращении, особенно при старте может достигать 1 ампера.
После загрузки следующего скетча можно приступать к тестированию сервопривода.
int pos = 0;
int incomingByte = 0;
int servo_pin = D7; // D7 - GPIO13
void setup() {
Serial.begin(9600);
pinMode(servo_pin, OUTPUT);
}
void loop() {
digitalWrite(servo_pin, LOW);
if (Serial.available() > 0) {
incomingByte = Serial.read() - 48;
if (incomingByte >= 0 and incomingByte <= 9) {
pos = pos * 10 + incomingByte;
Serial.print(incomingByte, DEC);
} else {
Serial.println(".");
Serial.print("Импульс (мс): ");
Serial.println(pos, DEC);
Serial.print(" - ");
Serial.println(pos, DEC);
for (int i = 1; i <= 150; i++) {
digitalWrite(servo_pin, HIGH);
delayMicroseconds(pos);
digitalWrite(servo_pin, LOW);
delayMicroseconds(20000 - pos);
delay(1);
}
pos = 0;
}
}
}
В мониторе порта введите значение длительности импульса в миллисекундах. Начните, например, со значения 540. Сервопривод совершит поворот (если он был повёрнут в нулевой угол, то ничего не произойдёт). Если после поворота мотор гудит и подёргивается, значит 540мс слишком короткий импульс для нулевого угла, надо увеличить это значение. ВНИМАНИЕ! Не спешите во время испытания вводить отправлять из монитора порта следующее значение. Дождитесь, когда в мониторе порта появится сообщение о нулевой длительности импульса. После этого можно вводить следующее тестовое значение.

Максимальный импульс подбирают аналогично, обычно начинают со значения 2400мс. Если мотор гудит, длительность импульса уменьшают.
Чтобы управлять сервоприводом было удобнее, создана специальная библиотека <Servo.h>
. Работать с ней, действительно удобно, но для правильной работы сервопривода требуется в команде servo.attach()
указать три параметра: пин, к которому подсоединён управляющий провод сервопривода, и два необязательных параметра – длительность импульса в миллисекундах соответствующее углу 0 и длительность импульса в миллисекундах соответствующее углу 180 градусов. Если их не задавать, то они принимаются в 544 и 2400мс.
Второй скетч удобнее для подбора параметров сервоприводов и тестирования поворотов. Через монитор порта вводятся цифровые команды. Команда состоит из двух чисел: первое – номер команды, через пробел, второе – значение нужной величины.
• Команда 1 – установить минимальную длительность в миллисекундах соответствующую углу 0 градусов. Пример: 1 544.
• Команда 2 – установить максимальную длительность в миллисекундах соответствующую углу 180 градусов. Пример: 1 2400.
Для выполнения серии из нескольких поворотов устанавливают значения такой серии. Для этого служат команды с 3 по 6.
• Команда 3 – значение стартового угла серии. Пример: 3 30.
• Команда 4 – значение последнего угла серии. Пример: 4 150.
• Команда 5 – значение угла, на который происходит поворот в серии поворотов. Пример: 5 10.
• Команда 6 – длительность паузы в миллисекундах между поворотами в серии поворотов. Пример: 6 30.
• Команда 7 – Выполнение серии поворотов, с параметрами, установленными командами с 3 по 6.
• Команда 8 - поворот вала сервопривода в заданное значение угла. Пример: 7 150.
• Команда 9 - поворот вала сервопривода на заданный угол относительно положения, в котором находится вал сервопривода. Положительное значение соответствует повороту по часовой стрелке, отрицательное – повороту против часовой стрелки. Пример: 9 -15.
#include <Servo.h>
Servo servo;
const int SERVO_PIN = D7; // D7 - GPIO13
// подбираем эти min- и max-значения
int minValue = 544;
int maxValue = 2400;
void setup()
{
servo.attach(SERVO_PIN, minValue, maxValue);
Serial.begin(9600);
printHelp();
}
int minLoopAngle = 45;
int maxLoopAngle = 135;
int loopStep = 1;
int loopSleep = 15;
int angle = 90;
int value;
void loop()
{
while(Serial.available()) {
processInput();
printHelp();
}
}
void processInput() {
int variant = Serial.parseInt();
if (Serial.available()) {
value = Serial.parseInt();
}
Serial.print("Команда "); Serial.print(variant);
Serial.print(" и значение параметра "); Serial.println(value);
switch (variant) {
case 1:
minValue = value;
servo.attach(SERVO_PIN, minValue, maxValue);
servo.write(angle);
break;
case 2:
maxValue = value;
servo.attach(SERVO_PIN, minValue, maxValue);
servo.write(angle);
break;
case 3:
minLoopAngle = value; break;
case 4:
maxLoopAngle = value; break;
case 5:
loopStep = value; break;
case 6:
loopSleep = value; break;
case 7:
for (angle = minLoopAngle; angle <= maxLoopAngle; angle += loopStep) {
servo.write(angle);
// Serial.print("Текущий угол: "); Serial.println(angle);
delay(loopSleep);
}
break;
case 8:
angle = value;
servo.write(angle);
break;
case 9:
angle += value;
servo.write(angle);
break;
default:
Serial.println("Непонятная команда.");
}
}
void printHelp() {
Serial.print("1 - Минимальный импульс мс (Текущее значение "); Serial.print(minValue); Serial.println(")");
Serial.print("2 - Максимальный импульс мс (Текущее значение "); Serial.print(maxValue); Serial.println(")");
Serial.print("3 - Начальный угол цикла ° (Текущее значение "); Serial.print(minLoopAngle); Serial.println(")");
Serial.print("4 - Конечный угол цикла ° (Текущее значение "); Serial.print(maxLoopAngle); Serial.println(")");
Serial.print("5 - Шаг цикла ° (Текущее значение "); Serial.print(loopStep); Serial.println(")");
Serial.print("6 - Пауза цикла мс (Текущее значение "); Serial.print(loopSleep); Serial.println(")");
Serial.println("7 - Запустить цикл");
Serial.print("8 - Повернуть на абсолютный угол ° (Текущее значение "); Serial.print(angle); Serial.println(")");
Serial.print("9 - Повернуть от текущего угла ° (Текущее значение "); Serial.print(angle); Serial.println(")");
Serial.println("Введите команду и через пробел, параметр");
}
После ввода команды через монитор порта (на картинке ниже вводится команда 9 90 – повернуть вал двигателя на 90 градусов по часовой стрелке относительно текущего положения) в мониторе порта будет выведено напоминание о командах и текущих значениях параметров.

Используется одна библиотека во втором скетче
#include <Servo.h>
Этот тест рекомендуется использовать для подбора параметров сервопривода, если вы планируете пользоваться этой библиотекой в своём скетче. Значения длительности импульсов, которые подобраны по командам 1 и 2 используйте в команде servo.attach();
.