БИБЛИОТЕКА GYVERMOTOR

Библиотека для удобного управления моторчиками через драйвер полного моста для Arduino

  • Контроль скорости и направления вращения
  • Работа с 10 битным ШИМом
  • Программный deadtime
  • Отрицательные скорости
  • Поддержка двух типов драйверов и реле
  • Плавный пуск и изменение скорости

Поддерживаемые платформы: все Arduino (используются стандартные Wiring-функции).

Библиотека подходит для большинства драйверов, построенных по схеме H-мост, на два мотора они обычно имеют 4 входа (по 2 на каждый)

ДОКУМЕНТАЦИЯ


Инициализация


Библиотека поддерживает три типа драйверов:

  • DRIVER2WIRE – двухпроводной драйвер (направление + ШИМ)
  • 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 – любой ШИМ пин МК
  • levelLOW / HIGH – уровень драйвера. Если при увеличении скорости мотор наоборот тормозит – смени уровень

Настройки


  • setDeadtime(us) – установка программного deadtime на переключение направления, us в микросекундах. По умолчанию стоит 0: deadtime отключен
  • setDirection(dir) – ГЛОБАЛЬНАЯ смена направления вращения мотора например чтобы FORWARD совпадал с направлением движения “вперёд” у машинки. dirREVERSE или NORMAL (умолч.)
  • setLevel(level) – смена уровня драйвера (аналогично при инициализации). Если при увеличении скорости мотор наоборот тормозит – смени уровень. levelLOW или HIGH
  • setMinDuty(duty) – минимальный сигнал (по модулю), который будет подан на мотор, то есть либо ноль, либо он. Избавляет от ситуаций, когда мотор покоится и “пищит”, а также позволяет сделать “мёртвую зону” в управлении

Режим работы


У мотора есть 5 режимов работы, устанавливаются при помощи setMode(mode), где mode:

  • FORWARD – вперёд
  • BACKWARD – назад
  • STOP – холостой (мотор отключен)
  • BRAKE – активное торможение
  • 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 и не будет пищать при “шуме” задающего сигнала.

10-битная скорость


setSpeed(speed) может работать с 10-битной скоростью (0..1023 в одном направлении или -1023..1023  в обоих). Для этого нужно:

  • Перевести таймер в режим 10 бит. На Arduino Nano/UNO так может только первый таймер (выводы D9 и D10), смотрите пример в библиотеке и урок по частоте ШИМ. По Arduino MEGA пока что такого готового набора у меня нет.
  • Настроить нужный объект на режим 10 бит при помощи set10bitMode(), также не забыть подключить ШИМ к выводу настроенного в первом пункте таймера (смотри пример).

Несколько моторов могут работать на одной плате с разным разрешением, т.е. например 2 мотора на таймере 1 с разрешением 10 бит, и ещё два на таймере 2 с разрешением 8 бит.

Плавное управление скоростью


В библиотеке реализован готовый инструмент для плавного изменения скорости, что может обеспечить плавный пуск и остановку механизмов:

  • setSmoothSpeed(acc) – установка скорости изменения скорости (ускорения) мотора
  • smoothTick(speed) – данная функция сама меняет скорость мотора, плавно приближая её к указанной speed. Функция работает по встроенному таймеру на millis() с периодом 50 мс, то есть рекомендуется вызывать smoothTick(speed) не реже, чем каждые 50 мс.

В примере smooth_control можно открыть плоттер и посмотреть, как работает алгоритм.

GMotor(driverType type, int8_t param1 = NC, int8_t param2 = NC, int8_t param3 = NC, int8_t param4 = NC);
// три варианта создания объекта в зависимости от драйвера:
// 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) )

// установка скорости 0-255 (8 бит) и 0-1023 (10 бит)
void setSpeed(int16_t duty);			

// сменить режим работы мотора:	
// FORWARD - вперёд
// BACKWARD - назад
// STOP - остановить
// BRAKE - активное торможение
void setMode(workMode mode);

// направление вращения	
// NORM - обычное
// REVERSE - обратное
void setDirection(dir direction);

// установить выход в 8 бит
void set8bitMode();		

// установить выход в 10 бит
void set10bitMode();					

// установить 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(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() {
  // установка программного deadtime на переключение направления, микросекунды
  // по умолчанию стоит 0: deadtime отключен
  // motor.setDeadtime(200);

  // ГЛОБАЛЬНАЯ смена направления вращения мотора
  // например чтобы FORWARD совпадал с направлением движения "вперёд" у машинки  
  motor.setDirection(REVERSE);
  motor.setDirection(NORMAL);   // умолч.

  // смена режима работы мотора
  motor.setMode(FORWARD);   // вперёд
  motor.setMode(BACKWARD);  // назад
  motor.setMode(STOP);      // холостой (мотор отключен)
  motor.setMode(BRAKE);     // активное торможение

  // смена уровня драйвера (аналогично при инициализации)
  // Если при увеличении скорости мотор наоборот тормозит - смени уровень
  motor.setLevel(LOW);
  motor.setLevel(HIGH);     // по умолч.
  
  // setSpeed в режиме 8-бит (активно по умолчанию)
  // motor.set8bitMode();

  // setSpeed в режиме 10-бит
  // для работы в 10 бит необходимо также настроить ШИМ на 10 бит!!!
  // читай тут https://alexgyver.ru/lessons/pwm-overclock/
  // motor.set10bitMode();


  // ключ на старт!
  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);  // задержка просто для "стабильности"
}
/*
  Пример управления мотором при помощи драйвера полного моста и потенциометра
  на ШИМ 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() {
  // разгоняем ШИМ на пинах 9 и 10 (atmega328) до 16 кГц 10 бит
  // читай тут: https://alexgyver.ru/lessons/pwm-overclock/
  TCCR1A = 0b00000011;  // 10bit
  TCCR1B = 0b00001101;  // x1024 fast pwm

  // активируем 10-битный режим библиотеки
  motor.set10bitMode();

  // ключ на старт!
  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. В комментарии на страницах я заглядываю очень редко, на форум – ещё реже.

ОСТАЛЬНЫЕ БИБЛИОТЕКИ

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