Перевод статьи Controlling DC Motors with TB6612FNG and ArduinoAmrit Prabhu, Last Minute Engineers.

Задумали собрать собственного двухколёсного робота? Отлично! Один из важнейших шагов на пути к оживлению робота — выбор правильного драйвера двигателей.

Если вы уже успели покопаться в теме, то наверняка натыкались на классические драйверы вроде L293D или L298N. Им уже больше двух десятков лет, но они по-прежнему широко используются — и не зря. Они просты, надёжны и очень дёшевы, поэтому особенно популярны в школах, любительских проектах и наборах для начинающих.

Но есть нюанс: и L293D, и L298N построены на H-мосте из биполярных транзисторов (BJT), а такая схема не очень энергоэффективна. Она рассеивает мощность в виде тепла, требует более высокого напряжения и плохо подходит для проектов на батарейках.

Здесь-то и выходит на сцену драйвер TB6612FNG. Это современный драйвер на MOSFET-транзисторах, у которого есть ряд преимуществ. Он эффективнее, поэтому меньше греется и меньше тратит мощность впустую. Он работает при более низком напряжении, что делает его идеальным для плат с логикой 3,3 В и 5 В. А ещё у него меньше габариты — то что нужно для тесных мест в роботах, дронах и других компактных проектах.

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

Поехали!

Основы управления двигателями#

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

  • H-мост — позволяет управлять направлением вращения двигателя;
  • ШИМ (широтно-импульсная модуляция) — помогает управлять скоростью двигателя постоянного тока.

Управление направлением с помощью H-моста#

Двигатели постоянного тока — самые простые в использовании! Подключите к такому двигателю батарейку — и он завертится в одну сторону. Поменяйте провода местами — завертится в другую. Но нельзя же физически перекидывать провода каждый раз, когда нужно сменить направление. Вот тут и пригодится H-мост!

H-мост — это специальная схема из четырёх электронных ключей, расставленных в форме буквы «H», с двигателем посередине.

Включая и выключая эти ключи в определённом порядке, можно направлять ток через двигатель то в одну сторону, то в противоположную. Этот ловкий приём и позволяет управлять направлением вращения, не перекидывая физически ни одного провода.

Анимация ниже показывает, как работает H-мост.

Анимация работы H-моста: управление направлением вращения двигателя

Как H-мост меняет направление вращения двигателя.

Управление скоростью с помощью ШИМ#

При фиксированном напряжении двигатель постоянного тока крутится с постоянной скоростью. Чтобы изменить скорость, нужно менять напряжение: выше напряжение — быстрее вращение, ниже — медленнее.

Однако постоянно менять напряжение физически неудобно. Вот тут и приходит на помощь ШИМ — широтно-импульсная модуляция.

ШИМ — это остроумный способ управлять средней мощностью, подаваемой на двигатель. Вместо фиксированного напряжения ШИМ очень быстро включает и выключает напряжение короткими импульсами.

«Ширина» каждого импульса включения, которую ещё называют коэффициентом заполнения (duty cycle), определяет, как долго напряжение остаётся включённым в каждом цикле.

  • Если напряжение включено бóльшую часть времени (широкий импульс), двигатель получает более высокое среднее напряжение и крутится быстрее.
  • Если напряжение выключено бóльшую часть времени (узкий импульс), двигатель получает более низкое среднее напряжение и крутится медленнее.

На картинке ниже показано, как разные коэффициенты заполнения влияют на скорость двигателя.

Разные коэффициенты заполнения ШИМ и их влияние на скорость

Чем шире импульс (больше коэффициент заполнения), тем выше среднее напряжение.

Микросхема драйвера TB6612FNG#

TB6612FNG в первую очередь рассчитана на управление индуктивными нагрузками: двигателями постоянного тока, шаговыми двигателями, реле и соленоидами.

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

Микросхема модуля TB6612FNG

Микросхема TB6612FNG на модуле.

В своей основе TB6612FNG содержит два отдельных H-моста. То есть она может управлять сразу двумя разными двигателями постоянного тока. Эти два H-моста можно даже объединить, чтобы управлять биполярным шаговым двигателем.

Питание#

По части питания TB6612FNG довольно гибкая. Она работает в широком диапазоне напряжений — от 4,5 В до 13,5 В — и способна выдавать до 1,2 А продолжительного тока (и до 3,2 А пикового) на канал. Значит, ей по плечу всё: и маленькие любительские моторчики, и более крупные, мощные двигатели.

Встроенные защитные диоды (flyback)#

Одна из важнейших защитных функций TB6612FNG — встроенные защитные диоды (их ещё называют разрядными, обратными или flyback-диодами). Они очень важны при работе с индуктивными нагрузками вроде двигателей.

Когда двигатель резко выключается, его магнитное поле схлопывается. Это может вызвать всплеск напряжения обратно в цепь. Такое обратное напряжение (называемое обратной ЭДС, back EMF) способно повредить микроконтроллер и другие чувствительные компоненты.

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

Тепловая защита#

В TB6612FNG есть и встроенная тепловая защита. Это значит, что при перегреве микросхемы — например, если двигатель тянет слишком большой ток или охлаждение недостаточное — TB6612FNG временно автоматически отключит свои выходы, чтобы не выйти из строя. Как только микросхема остынет до безопасной температуры, она снова начнёт работать сама.

Технические характеристики#

Вот характеристики:

ПараметрЗначение
Напряжение питания двигателей4,5 В – 13,5 В
Напряжение логического входа2,7 В – 5,5 В
Продолжительный ток на канал1,2 А
Пиковый ток на канал3,2 А
Максимальная частота ШИМ100 кГц
Максимальная рассеиваемая мощность0,78 Вт

Подробнее — в даташите TB6612FNG.

Распиновка модуля TB6612FNG#

Всего у модуля TB6612FNG 16 выводов.

Распиновка модуля драйвера TB6612FNG

16 выводов модуля TB6612FNG.

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

Выводы питания#

На модуле TB6612FNG два вывода питания: VM и VCC.

Выводы питания VM и VCC модуля TB6612FNG

Выводы питания: VM и VCC.

VM — основной вход питания для двигателей. Сюда можно подать любое напряжение от 4,5 В до 13,5 В в зависимости от используемого двигателя.

VCC — вход питания для внутренней логики микросхемы. Допустимый диапазон для этого вывода — от 2,7 В до 5,5 В, так что он прекрасно работает и с 3,3-вольтовыми, и с 5-вольтовыми микроконтроллерами. Главное — чтобы поданное сюда напряжение совпадало с логическим уровнем вашего микроконтроллера. Например, Arduino обычно работает с 5-вольтовой логикой, поэтому VCC подключают к источнику 5 В.

Вывод GND — общая земля модуля. И питание двигателей, и микроконтроллер (например, Arduino) должны иметь общую землю через этот вывод.

Выводы для двигателей#

Это выводы, к которым как раз и подключаются двигатели постоянного тока.

Выходные выводы A1, A2, B1, B2 для двигателей

Выходы для двигателей A и B.

Выводы A1 и A2 подключаются к первому двигателю (двигатель A), а выводы B1 и B2 — ко второму (двигатель B). Сюда можно подключить любой двигатель постоянного тока на 5–13 вольт.

Выводы управления направлением#

Эти выводы управляют направлением вращения двигателей, включая и выключая ключи внутреннего H-моста:

Выводы управления направлением AIN1, AIN2, BIN1, BIN2

Выводы управления направлением для двигателей A и B.

У микросхемы по два вывода управления направлением на каждый двигатель. Выводы AIN1 и AIN2 задают направление вращения двигателя A, а BIN1 и BIN2 — двигателя B.

Задавая разные сочетания сигналов HIGH и LOW на этих выводах, можно заставить двигатели вращаться вперёд, назад или остановиться. Таблица ниже показывает, как именно это работает:

Вход 1Вход 2Направление вращения
Low (0)Low (0)Торможение
High (1)Low (0)Вперёд
Low (0)High (1)Назад
High (1)High (1)Торможение

Выводы управления скоростью#

Выводы PWMA и PWMB задают, как быстро крутятся ваши двигатели.

Выводы управления скоростью PWMA и PWMB

Выводы ШИМ: PWMA и PWMB.

По сути эти выводы работают как простые выключатели. Если подтянуть один из них к HIGH, соответствующий двигатель включён и крутится на полной скорости. Если к LOW — двигатель полностью выключен и не крутится вовсе.

Но эти выводы умеют больше, чем просто включать и выключать двигатели. Подавая на PWMA или PWMB сигнал ШИМ с частотой до 100 кГц, можно управлять скоростью каждого двигателя.

ШИМ работает так: он очень быстро, много раз в секунду, включает и выключает двигатель. Скорость зависит от того, как долго двигатель остаётся включённым в каждом цикле (это и есть коэффициент заполнения). Если сигнал включён бóльшую часть времени — двигатель крутится быстрее, если лишь короткое время — медленнее.

Вывод Standby#

Вывод STBY позволяет быстро отключить сразу оба двигателя.

Вывод разрешения выхода Standby модуля TB6612FNG

Вывод STBY отключает оба двигателя разом.

По умолчанию этот вывод подтянут к нулю внутренним резистором на 200 кОм, из-за чего двигатели отключены. Чтобы включить двигатели и разрешить им работать, нужно подтянуть этот вывод к HIGH. Сделать это можно, либо подключив вывод напрямую к VCC, либо подавая на него высокий уровень с выходного вывода микроконтроллера.

Подключение модуля TB6612FNG к Arduino#

Теперь, когда мы разобрались, как работает модуль TB6612FNG, можно приступать к подключению его к Arduino!

Начнём с питания двигателей. В этом эксперименте мы используем TT-моторы — их часто ставят в двухколёсных роботах. Такие двигатели обычно хорошо работают при напряжении от 3 В до 6 В. Поэтому к выводу VM мы подключим внешний источник на 5 В.

Дальше нужно подать питание на внутреннюю логику драйвера. Вывод VCC модуля TB6612FNG ждёт вход 2,7–5,5 В, что совпадает с выходом Arduino на 5 В. Значит, подключаем вывод 5V Arduino к VCC, а GND — к GND.

Теперь займёмся управляющими выводами. У модуля TB6612FNG четыре входа — AIN1, AIN2, BIN1 и BIN2 — для управления направлением двигателей. Подключим их к цифровым выходам 5, 4, 7 и 8 на Arduino.

Для управления скоростью у TB6612FNG есть входы ШИМ, обозначенные PWMA и PWMB. Их нужно подключить к выводам Arduino с поддержкой ШИМ: PWMA — к 3, PWMB — к 9.

Ещё понадобится подтянуть вывод STBY к логической единице, чтобы включить драйвер. В нашей схеме мы просто подключим его напрямую к VCC. Это очень важный шаг: забудете о нём — драйвер останется в дежурном режиме, и двигатели вообще не заработают.

Наконец, подключаем сами двигатели к выходам. Двигатель A идёт на A1 и A2, двигатель B — на B1 и B2. Не переживайте, какой провод двигателя к какому выходу подключать: если двигатель крутится не в ту сторону, провода потом можно просто поменять местами — «правильного» и «неправильного» способа подключения здесь нет.

Вот краткая таблица соединений:

TB6612FNGArduino
VCC5V
STBY5V
GNDGND
PWMA3
AIN24
AIN15
BIN17
BIN28
PWMB9

На картинке ниже показана полная схема подключения для этой сборки.

Схема подключения модуля TB6612FNG к Arduino

Полная схема подключения.

Пример скетча для Arduino#

Вот простой скетч для Arduino, который показывает, как управлять направлением и скоростью двух двигателей постоянного тока с помощью драйвера TB6612FNG и Arduino. Никаких специальных библиотек для него не нужно — используются только базовые встроенные функции Arduino IDE.

Этот пример — отличный способ на практике освоить управление скоростью и направлением двигателей через TB6612FNG. Разобравшись с ним, вы легко соберёте более сложные системы управления двигателями — вроде тех, что стоят в простых роботах или машинках на радиоуправлении.

// Motor A connections
int pwmA = 3;
int Ain1 = 5;
int Ain2 = 4;

// Motor B connections
int pwmB = 9;
int Bin1 = 7;
int Bin2 = 8;

void setup() {
  // Set all the motor control pins to outputs
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(Ain1, OUTPUT);
  pinMode(Ain2, OUTPUT);
  pinMode(Bin1, OUTPUT);
  pinMode(Bin2, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}

void loop() {
  directionControl();
  delay(1000);
  speedControl();
  delay(1000);
}

// This function lets you control spinning direction of motors
void directionControl() {
  // Set motors to maximum speed
  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);

  // Turn on motor A & B
  digitalWrite(Ain1, HIGH);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, HIGH);
  digitalWrite(Bin2, LOW);
  delay(2000);

  // Now change motor directions
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, HIGH);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, HIGH);
  delay(2000);

  // Turn off motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}

// This function lets you control speed of the motors
void speedControl() {
  // Turn on motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, HIGH);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, HIGH);

  // Accelerate from zero to maximum speed
  for (int i = 0; i < 256; i++) {
    analogWrite(pwmA, i);
    analogWrite(pwmB, i);
    delay(20);
  }

  // Decelerate from maximum speed to zero
  for (int i = 255; i >= 0; --i) {
    analogWrite(pwmA, i);
    analogWrite(pwmB, i);
    delay(20);
  }

  // Now turn off motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}

Когда двигатель постоянного тока разгоняется или замедляется, вы можете услышать гудение — особенно на низких значениях ШИМ. Не пугайтесь, это совершенно нормально. Дело в том, что двигателю нужно определённое минимальное напряжение, чтобы начать вращаться, а при малых значениях ШИМ напряжения может не хватать для плавной работы.

Разбор кода#

В начале скетча мы задаём, какие выводы Arduino будут управлять двигателем A и двигателем B.

// Motor A connections
int pwmA = 3;
int Ain1 = 5;
int Ain2 = 4;

// Motor B connections
int pwmB = 9;
int Bin1 = 7;
int Bin2 = 8;

В функции setup() мы настраиваем все шесть управляющих выводов как выходы, потому что сигналы идут от Arduino к TB6612FNG. Заодно убеждаемся, что оба двигателя выключены, установив все выводы управления направлением в LOW. Так двигатели не сорвутся с места при включении питания Arduino.

void setup() {
  // Set all the motor control pins to outputs
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(Ain1, OUTPUT);
  pinMode(Ain2, OUTPUT);
  pinMode(Bin1, OUTPUT);
  pinMode(Bin2, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}

В функции loop() мы с секундной паузой между ними вызываем две собственные функции. Первая — directionControl(), вторая — speedControl().

void loop() {
  directionControl();
  delay(1000);
  speedControl();
  delay(1000);
}

Разберём, что делает каждая из этих функций.

Функция directionControl() показывает, как управлять направлением обоих двигателей. Сначала мы выставляем максимальную скорость, подавая на оба вывода ШИМ уровень HIGH. Затем подаём нужные сигналы на выводы управления направлением, чтобы двигатели A и B закрутились вперёд. Прокрутившись так две секунды, они по нашей команде меняют сигналы на выводах направления и на следующие две секунды меняют направление вращения на обратное. Наконец, мы останавливаем двигатели, установив все выводы управления направлением в LOW.

void directionControl() {
  // Set motors to maximum speed
  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);

  // Turn on motor A & B
  digitalWrite(Ain1, HIGH);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, HIGH);
  digitalWrite(Bin2, LOW);
  delay(2000);

  // Now change motor directions
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, HIGH);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, HIGH);
  delay(2000);

  // Turn off motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}

Функция speedControl() показывает, как управлять скоростью двигателей через ШИМ. Начинаем с того, что выставляем выводы направления так, чтобы оба двигателя крутились в одну сторону. Затем плавно наращиваем скорость, постепенно повышая значение ШИМ от 0 до 255 — так имитируется разгон. Достигнув полной скорости, запускаем обратный процесс: постепенно снижаем значение ШИМ с 255 до 0, из-за чего двигатели плавно замедляются и останавливаются. В конце останавливаем двигатели, установив все выводы управления направлением в LOW.

void speedControl() {
  // Turn on motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, HIGH);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, HIGH);

  // Accelerate from zero to maximum speed
  for (int i = 0; i < 256; i++) {
    analogWrite(pwmA, i);
    analogWrite(pwmB, i);
    delay(20);
  }

  // Decelerate from maximum speed to zero
  for (int i = 255; i >= 0; --i) {
    analogWrite(pwmA, i);
    analogWrite(pwmB, i);
    delay(20);
  }

  // Now turn off motors
  digitalWrite(Ain1, LOW);
  digitalWrite(Ain2, LOW);
  digitalWrite(Bin1, LOW);
  digitalWrite(Bin2, LOW);
}