Для данной статье я рассматриваю схему из статьи Arduino. Управление сервоприводом, на примере SG90. И будет использоваться скетч похожий на скетч и статьи Arduino. Взаимодействие с компьютером через USB порт, по этому некоторые моменты которые я объяснял там, я буду опускать.
Мы используем:
- Плата Arduino. x1
- Компьютер(для написания и загрузке кода, а так же мы будем брать с него электричество и общаться с ним). x1
- Провод для соединения компьютера и платы. x1
- Сервопривод.x1
- Провода. x3-4
- Есть схемы с внешним источником питания, но можно взять питание и с платы.
Схема подключения:
Для чего может понадобится подключение сервопривода без библиотеки Servo.h. Дело в том, что данная библиотека была написана для большинства сервоприводов и её назначение подходить к большинству. Но подключить конкретный сервопривод бывает не просто. К тому же сервопривод может не точно работать с данной библиотекой. Приведу конкретные цифры.
Бибилиотека Servo.h расчитана на следующие параметры:
длина импульса | угол |
---|---|
544 | 0$$^o$$ |
2400 | 180$$^o$$ |
1520 | 90$$^o$$ |
Я потестировал несколько сервопривод SG90 вот результат:
0$$^o$$ | 540 | 540 | 540 | |
---|---|---|---|---|
180$$^o$$ | 2400 | 2700 | 2400 | |
90$$^o$$ | 1400 | 1520 | 1400 |
Видно, что цифры немного различаются. Даже среди одной и той же модели.
Рассмотрим скетч.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
int pos = 0; int incomingByte = 0; int servo=9; void setup() { Serial.begin(9600); pinMode(servo, OUTPUT); } void loop() { digitalWrite(servo, LOW); if (Serial.available() > 0) { incomingByte = Serial.read()-48; if (incomingByte>=0 and incomingByte<=9) { pos=pos*10+incomingByte; Serial.println(pos, DEC); } else { Serial.print("move: ");Serial.println(pos, DEC);Serial.print(" - ");Serial.println(pos, DEC); for (int i=1;i<=180;i++){ digitalWrite(servo, HIGH); delayMicroseconds(pos); digitalWrite(servo, LOW); delayMicroseconds(20000-pos); delay(1); } pos=0; } } } |
Что он делает данный код? мы вводим длину сигнала и сервопривод выставляется в позицию соответствующую его настройкам. Данный скетч иллюстрирует работу серво привода и Arduino. А так же может пригодится для решения «необъяснимых» проблем с библиотекой.
Данный скетч написан со скетча Arduino. Взаимодействие с компьютером через USB порт. поэтому упор будем делать на моментах связанных с управлением сервоприводом.
Сначало объявляем переменные:
1 2 3 |
int pos = 0; int incomingByte = 0; int servo=9; |
В переменной pos мы будем хранить позицию в которую надо поставить сервопривод.
В incomingByte будет содержаться входящие коды символов.
В servo мы будем хранить номер ножки, к которой подключен сервопривод. В нашем случае сервопривод подключён к 9 ножке.
Дальше блок setup:
1 2 |
Serial.begin(9600); pinMode(servo, OUTPUT); |
Здесь мы выставляем скорость общения Arduino с компьютером:
1 |
Serial.begin(9600); |
И устанавливаем ножку с серовприводом в состоянии выхода.
1 |
pinMode(servo, OUTPUT); |
Дальше идёт основной цикл программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
digitalWrite(servo, LOW); if (Serial.available() > 0) { incomingByte = Serial.read()-48; if (incomingByte>=0 and incomingByte<=9) { pos=pos*10+incomingByte; Serial.println(pos, DEC); } else { Serial.print("move: ");Serial.println(pos, DEC);Serial.print(" - ");Serial.println(pos, DEC); for (int i=1;i<=180;i++){ digitalWrite(servo, HIGH); delayMicroseconds(pos); digitalWrite(servo, LOW); delayMicroseconds(20000-pos); delay(1); } pos=0; } } |
Устанавливаем значение сигнала на ножке в состояние LOW
1 |
digitalWrite(servo, LOW); |
1 |
if (Serial.available() > 0) { |
Если есть входящие символы, тогда выполняем код дальше:
1 2 3 4 5 |
incomingByte = Serial.read()-48; if (incomingByte>=0 and incomingByte<=9) { pos=pos*10+incomingByte; Serial.println(pos, DEC); } else { |
Если символ цифра добавляем его в переменную pos. Иначе:
1 2 3 4 5 6 7 8 9 |
Serial.print("move: ");Serial.println(pos, DEC);Serial.print(" - ");Serial.println(pos, DEC); for (int i=1;i<=180;i++){ digitalWrite(servo, HIGH); delayMicroseconds(pos); digitalWrite(servo, LOW); delayMicroseconds(20000-pos); delay(1); } pos=0; |
выводим значение позиции на компьютер.
1 |
for (int i=1;i<=180;i++){ |
В моём случае это можно прочитать, как много раз выполнить следующий код:
Дальше мы формируем сигнал:
1 2 3 4 5 |
digitalWrite(servo, HIGH); delayMicroseconds(pos); digitalWrite(servo, LOW); delayMicroseconds(20000-pos); delay(1); |
Включаем напряжение на ножке.
1 |
digitalWrite(servo, HIGH); |
Ждём заданное количество микроссекунд.
1 |
delayMicroseconds(pos); |
выключаем напряжение на ножке.
1 |
digitalWrite(servo, LOW); |
ждём ещё 20000-pos микросекунд.
1 |
delayMicroseconds(20000-pos); |
Это у нас получился сигнал с «частотой» 50 герц говорить о частоте одиночного сигнала, как то не коректно но мы могли бы после этого закончить код и тогда бы было именно так.
1 |
delay(1); |
Эта строчка родилась после того, как я увидел, что сервопривод двигается не 20 милесикунд(время сигнала), а !какое то! время, поэтому я не стал сильно часто давать на него сигнал, и сделал задержку в одну миллисекунду.
Видео процесса:
Другие статьи по программированию плат Arduino можно посмотреть здесь.
Здравствуйте! поясните, пожалуйста, откуда берется for (int i=1;i<=180;i++){ ?
Если сервопривод управляется одиночным импульсом заданной длины, то зачем повторять этот импульс 180 раз? И почему именно 180, откуда эта цифра?
Здравствуйте.
Боже, это кто то читает 🙂
Это долгая грустная история.
> сервопривод управляется одиночным импульсом заданной длины
Да всё так и есть.. но я потестировал несколько своих сервоприводов и у меня не один не успевал прокрутиться на 180 градусов с одного импульса.
Не знаю с чем это связано… но угол был всегда разный….
поэтому я решил посылать 10 раз импульс подряд, и результат был уже лучше но всё равно иногда глучил..
Ну и я не сильно заморачиваясь начал фигачить 180 раз. Этот импульс… и всё стало со 100% гарантией вставать на нужный угол.
Ну и этот скетч задумывался как записка мне, что бы не забыть как он работает. В жизни я бы наверно заюзал библиотеку… Или давал бы не один и тот же импульс, а двигал бы по 1 градусу с задержкой, что бы он был не таким резким.
Читают-читают) спасибо! Подружил этой логикой IRremote.h и Servo.h убрав нафиг из кода использование библиотеку Servo.h =) Ну никак они не хотели дружить, сколько бы не менял разных вариаций библиотек, таймингов и тому подобное.
Здравствуйте!
Sg90 гудят в любом положении. Моторчик не доворачивает доли градуса.
Что бы Вы могли посоветовать?
Помог бы вариант, если бы после выполнения команды поворота на серву дополнительно посылать значение с чуть меньшей шириной импульса относительно этого поворота, дабы уравнять значения скважности?
Не совсем понимаю, что и где нужно поменять что бы управление было потенциометром