УПРАВЛЕНИЕ МОТОРОМ С ARDINO
Библиотека подходит для большинства драйверов, построенных по схеме H-мост, на два мотора они обычно имеют 4 входа (по 2 на каждый). Также на сайте есть отдельный подробный урок по работе с коллекторными моторами.
БИБЛИОТЕКА GYVERMOTOR
Библиотека для удобного управления моторчиками через драйвер полного моста для Arduino
- Контроль скорости и направления вращения
- Работа с 10 битным ШИМом
- Программный deadtime
- Отрицательные скорости
- Поддержка двух типов драйверов и реле
- Плавный пуск и изменение скорости
Поддерживаемые платформы: все Arduino (используются стандартные Wiring-функции).
В версии 2.2 добавлена поддержка плат на базе ESP
ДОКУМЕНТАЦИЯ
Инициализация
Библиотека поддерживает три типа драйверов:
- DRIVER2WIRE – двухпроводной драйвер (направление + ШИМ)
- DRIVER2WIRE_NO_INVERT – двухпроводной драйвер, в котором при смене направления не нужна инверсия ШИМ
- DRIVER3WIRE – трёхпроводной драйвер (два пина направления + ШИМ)
- RELAY2WIRE – реле в качестве драйвера (два пина направления)
Инициализация происходит следующим образом:
GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, level);
GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, level);
GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, level);
Где
dig_pin
,dig_pin_A
,dig_pin_B
– любой цифровой пин МКPWM_pin
– любой ШИМ пин МКlevel
– LOW / HIGH – уровень драйвера. Если при увеличении скорости мотор наоборот тормозит – смени уровень
Настройки
setDeadtime(us)
– установка программного deadtime на переключение направления,us
в микросекундах. По умолчанию стоит 0: deadtime отключенsetDirection(dir)
– ГЛОБАЛЬНАЯ смена направления вращения мотора например чтобы FORWARD совпадал с направлением движения “вперёд” у машинки.dir
– REVERSE или NORMAL (умолч.)setLevel(level)
– смена уровня драйвера (аналогично при инициализации). Если при увеличении скорости мотор наоборот тормозит – смени уровень.level
– LOW или HIGHsetMinDuty(duty)
– минимальный сигнал (по модулю), который будет подан на мотор. Автоматически сжимает диапазон регулирования мотора: например minDuty поставили 50, и при сигнале 1 будет на мотор будет подано ~51, максимум останется прежним (диапазон сигнала переведётся в 50.. 255 внутри библиотеки).
Режим работы
У мотора есть 5 режимов работы, устанавливаются при помощи setMode(mode)
, где mode:
FORWARD
– вперёдBACKWARD
– назадSTOP
– холостой (мотор отключен)AUTO
– отдать управление функции setSpeed()
Управление скоростью и направлением
Скорость устанавливается при помощи функции setSpeed(speed)
. Есть два варианта управления скоростью:
- Направление в ручном режиме, скорость 0..255 (0..1023). В этом случае скорость должна быть положительной (
setSpeed(0..255)
), направление вращения задаётся при помощиsetMode()
. При направлении FORWARD частота оборотов растёт по мере увеличенияsetSpeed(speed)
, при направлении BACKWARD частота оборотов растёт в противоположную сторону по мере увеличенияsetSpeed(speed)
. - Направление в автоматическом режиме, скорость -255..255 (-1023..1023 для 10 бит). В этом случае устанавливаем
setMode(AUTO)
и подаём скорость во всём диапазоне. При значении мотор -255 крутится с максимальной скоростью в направлении “назад”, при 255 – в направлении “вперёд”. При значении 0 (ноль) режим автоматически переключается на STOP. Если задан параметр minDuty (при помощиsetMinDuty()
), то режим STOP будет автоматически активирован при значении скорости в пределах (-minDuty, minDuty). Пример: у нас есть мотор, экспериментально установлено, что он начинает вращаться при величине скорости больше 50 (и, соответственно, меньше -50), при меньшем значении он просто “пищит” и стоит на месте. Если мы выставимsetMinDuty(50)
, то в диапазоне -50..50 мотор автоматически будет находиться в режиме STOP и не будет пищать при “шуме” задающего сигнала.
Разрешение ШИМ
setSpeed(speed)
может работать с ШИМ любого разрешения, для этого нужно
- Перевести таймер в режим нужного разрешения. 8 битные таймеры можно запустить только на пониженном разрешении, а 16 битный – например на 10 битах (выводы D9 и D10), смотрите пример в библиотеке и урок по частоте ШИМ. По Arduino MEGA пока что такого готового набора у меня нет.
- Настроить нужный объект класса GMotor на нужное разрешение при помощи
setResolution(bit)
, где bit – разрешение ШИМ в битах (по умолчанию 8). Также не забыть подключить пин драйвера ШИМ к выводу настроенного в первом пункте таймера (смотри пример).
Несколько моторов могут работать на одной плате с разным разрешением, т.е. например 2 мотора на таймере 1 с разрешением 10 бит, и ещё два на таймере 2 с разрешением 8 бит.
Плавное управление скоростью
В библиотеке реализован готовый инструмент для плавного изменения скорости, что может обеспечить плавный пуск и остановку механизмов:
setSmoothSpeed(acc)
– установка скорости изменения скорости (т.е. ускорения) мотораsmoothTick(speed)
– данная функция сама меняет скорость мотора, плавно приближая её к указаннойspeed
. Функция работает по встроенному таймеру на millis() с периодом 50 мс, то есть рекомендуется вызыватьsmoothTick(speed)
не реже, чем каждые 50 мс.
В примере smooth_control можно открыть плоттер и посмотреть, как работает алгоритм.
Работа на esp8266
В esp8266 по умолчанию настроен 10-битный ШИМ, поэтому библиотеку нужно обязательно переключить в режим 10 бит: motor.setResolution(10);
GMotor(driverType type, int8_t param1 = NC, int8_t param2 = NC, int8_t param3 = NC, int8_t param4 = NC); // 4 варианта создания объекта в зависимости от драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW/HIGH) ) // GMotor motor(DRIVER2WIRE_NO_INVERT, dig_pin, PWM_pin, (LOW/HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) // установка скорости 0-255 (8 бит) и 0-1023 (10 бит) void setSpeed(int16_t duty); // сменить режим работы мотора: // FORWARD - вперёд // BACKWARD - назад // STOP - остановить void setMode(workMode mode); // направление вращения // NORM - обычное // REVERSE - обратное void setDirection(dir direction); // установить разрешение ШИМ в битах (по умолч 8) void setResolution(byte bit); // установить deadtime (в микросекундах). По умолч 0 void setDeadtime(uint16_t deadtime); // установить уровень драйвера (по умолч. HIGH) void setLevel(int8_t level); // плавное изменение к указанной скорости void smoothTick(int16_t duty); // скорость изменения скорости void setSmoothSpeed(uint8_t speed); // дать прямую команду мотору (без смены режима) void run(workMode mode, int16_t duty); // внутренняя переменная скважности для отладки int16_t _duty = 0;
ПРИМЕРЫ
/* Пример управления мотором при помощи драйвера полного моста и потенциометра */ #include "GyverMotor.h" GMotor motor(DRIVER2WIRE, 2, 3, HIGH); // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER2WIRE_NO_INVERT, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER2WIRE_NO_INVERT - двухпроводной драйвер, в котором при смене направления не нужна инверсия ШИМ DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { // установка программного deadtime на переключение направления, микросекунды // по умолчанию стоит 0: deadtime отключен // motor.setDeadtime(200); // ГЛОБАЛЬНАЯ смена направления вращения мотора // например чтобы FORWARD совпадал с направлением движения "вперёд" у машинки motor.setDirection(REVERSE); motor.setDirection(NORMAL); // умолч. // смена режима работы мотора motor.setMode(FORWARD); // вперёд motor.setMode(BACKWARD); // назад motor.setMode(STOP); // стоп, холостой (мотор отключен) // смена уровня драйвера (аналогично при инициализации) // Если при увеличении скорости мотор наоборот тормозит - смени уровень motor.setLevel(LOW); motor.setLevel(HIGH); // по умолч. // для работы в 10 бит необходимо также настроить ШИМ на 10 бит!!! // читай тут https://alexgyver.ru/lessons/pwm-overclock/ // motor.setResolution(10); // минимальный сигнал (по модулю), который будет подан на мотор // Избавляет от ситуаций, когда мотор покоится и "пищит" motor.setMinDuty(150); // ключ на старт! motor.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -255.. 255 int val = 255 - analogRead(0) / 2; // установка скорости: // * (0..255) при ручном выборе направления (setMode: FORWARD/BACKWARD) // * (-255..255) при автоматическом (поставить setMode(FORWARD)) // * (0..1023) в режиме 10 бит при ручном выборе направления (setMode: FORWARD/BACKWARD) // * (-1023..1023) в режиме 10 бит при автоматическом (поставить setMode(FORWARD)) motor.setSpeed(val); // в данном случае мотор будет остановлен в среднем положении рукоятки // и разгоняться в противоположные скорости в крайних её положениях delay(10); // задержка просто для "стабильности" }
/* Пример управления мотором при помощи драйвера полного моста на esp8266 */ #include "GyverMotor.h" GMotor motor(DRIVER2WIRE, 2, 3, HIGH); void setup() { // активируем 10-битный режим библиотеки // потому что у esp по умолчанию 10 бит motor.set10bitMode(); // ключ на старт! motor.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -1023.. 1023 int val = 1023 - analogRead(0) * 2; motor.setSpeed(val); // в данном случае мотор будет остановлен в среднем положении рукоятки // и разгоняться в противоположные скорости в крайних её положениях delay(10); // задержка просто для "стабильности" }
/* Пример управления мотором при помощи драйвера полного моста и потенциометра на ШИМ 10 бит */ #include "GyverMotor.h" GMotor motor(DRIVER2WIRE, 2, 9, HIGH); // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { // разгоняем ШИМ на пинах 9 и 10 (atmega328) до 16 кГц 10 бит // читай тут: https://alexgyver.ru/lessons/pwm-overclock/ TCCR1A = 0b00000011; // 10bit TCCR1B = 0b00001001; // x1 fast pwm // активируем 10-битный режим библиотеки motor.setResolution(10); // ключ на старт! motor.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -1023.. 1023 int val = 1023 - analogRead(0) * 2; motor.setSpeed(val); // в данном случае мотор будет остановлен в среднем положении рукоятки // и разгоняться в противоположные скорости в крайних её положениях delay(10); // задержка просто для "стабильности" }
/* Пример управления мотором при помощи драйвера полного моста и потенциометра на разогнанном ШИМе */ #include "GyverMotor.h" GMotor motor(DRIVER2WIRE, 2, 3, HIGH); // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { // разгоняем ШИМ на пинах 3 и 11 (atmega328) до 31 кГц // читай тут: https://alexgyver.ru/lessons/pwm-overclock/ TCCR2B = 0b00000001; // x1 TCCR2A = 0b00000001; // phase correct // ключ на старт! motor.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -255.. 255 int val = 255 - analogRead(0) / 2; motor.setSpeed(val); // в данном случае мотор будет остановлен в среднем положении рукоятки // и разгоняться в противоположные скорости в крайних её положениях delay(10); // задержка просто для "стабильности" }
/* Пример плавного управления мотором при помощи драйвера полного моста и потенциометра */ #include "GyverMotor.h" GMotor motor(DRIVER2WIRE, 2, 3, HIGH); // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { Serial.begin(9600); // установка скорости изменения скорости (ускорения) мотора motor.setSmoothSpeed(20); // ключ на старт! motor.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -255.. 255 int val = 255 - analogRead(0) / 2; // данную функцию рекомендуется вызывать чаще чем каждые 50 мс // (работает по встроенному таймеру) // она будет плавно менять скорость мотора к заданной motor.smoothTick(val); // отладка. Откройте Инструменты/Плоттер по последовательному порту Serial.print(val); // первый график - установленная скорость Serial.print(','); Serial.println(motor._duty); // второй график - реальный сигнал на мотор delay(10); // задержка просто для "стабильности" }
/* Пример управления двумя моторами */ #include "GyverMotor.h" GMotor motor1(DRIVER2WIRE, 2, 3, HIGH); GMotor motor2(DRIVER2WIRE, 4, 11, HIGH); // используем оба ШИМа таймера 2 (пины 3 и 11) // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { // ключ на старт! motor1.setMode(FORWARD); motor2.setMode(FORWARD); } void loop() { // потенциометр на А0 // преобразуем значение в -255.. 255 int val_1 = 255 - analogRead(0) / 2; // потенциометр на А1 // преобразуем значение в -255.. 255 int val_2 = 255 - analogRead(1) / 2; motor1.setSpeed(val_1); motor2.setSpeed(val_2); // в данном случае мотор будет остановлен в среднем положении рукоятки // и разгоняться в противоположные скорости в крайних её положениях delay(10); // задержка просто для "стабильности" }
/* Пример управления двумя моторами при помощи одного джойстика по танковой схеме */ #include "GyverMotor.h" GMotor motorR(DRIVER2WIRE, 2, 3, HIGH); GMotor motorL(DRIVER2WIRE, 4, 11, HIGH); // используем оба ШИМа таймера 2 (пины 3 и 11) // варианты инициализации в зависимости от типа драйвера: // GMotor motor(DRIVER2WIRE, dig_pin, PWM_pin, (LOW / HIGH) ) // GMotor motor(DRIVER3WIRE, dig_pin_A, dig_pin_B, PWM_pin, (LOW/HIGH) ) // GMotor motor(RELAY2WIRE, dig_pin_A, dig_pin_B, (LOW/HIGH) ) /* DRIVER2WIRE - двухпроводной драйвер (направление + ШИМ) DRIVER3WIRE - трёхпроводной драйвер (два пина направления + ШИМ) RELAY2WIRE - реле в качестве драйвера (два пина направления) dig_pin, dig_pin_A, dig_pin_B - любой цифровой пин МК PWM_pin - любой ШИМ пин МК LOW / HIGH - уровень драйвера. Если при увеличении скорости мотор наоборот тормозит - смени уровень */ void setup() { // ключ на старт! motorR.setMode(FORWARD); motorL.setMode(FORWARD); } void loop() { // джойстик на А0 и А1 int signalX = 255 - analogRead(0) / 2; int signalY = 255 - analogRead(1) / 2; // преобразуем по танковой схеме int dutyR = signalY + signalX; int dutyL = signalY - signalX; motorR.setSpeed(dutyR); motorL.setSpeed(dutyL); delay(10); // задержка просто для "стабильности" }
УСТАНОВКА БИБЛИОТЕКИ
Если вы не знаете, как установить библиотеку – читайте отдельный урок по работе с библиотеками!
БАГИ И ОШИБКИ
Если вы нашли баг или ошибку в исходнике или примерах, или у вас есть идеи по доработке библиотеки – пишите пожалуйста на почту alex@alexgyver.ru. В комментарии на страницах я заглядываю очень редко, на форум – ещё реже.
ОСТАЛЬНЫЕ БИБЛИОТЕКИ

У меня есть ещё очень много всего интересного! Смотрите полный список библиотек вот здесь.