Настала пора Arduino поуправлять моторчиками :)
Для этого воспользуемся самым популярным драйвером, используемым для управления моторчиками – микросхемой L293D.
L293D содержит два драйвера для управления электродвигателями небольшой мощности. Имеет две пары входов для управляющих сигналов и две пары выходов для подключения электромоторов. Кроме того, у L293D есть два входа для включения каждого из драйверов. Эти входы используются для управления скоростью вращения электромоторов с помощью
ШИМ (PWM).
Рассмотрим блок-схему L293D, приведённую в datasheet-е (
нумерация для SO-корпуса):
К выходам OUTPUT1 и OUTPUT2 подключается электромотор MOTOR1 (для микросхемы в DIP-корпусе – ножки
3 и 6).
Соответственно MOTOR2 подключается к выходам OUTPUT3 и OUTPUT4 (ножки
11 и 14).
Сигналы, подаваемые на ENABLE1(2) управляют соответствующим драйвером (ножки 1 и 9 соответственно).
Подавая на вход ENABLE1 сигнал HIGH ( или просто соединив с плюсом источника питания +5V) – включаем драйвер 1-го моторчика.
Если при этом на входы INPUT1 и INPUT2 сигналы не подавать, то моторчик вращаться не будет.
Подавая HIGH на INPUT1 и LOW на INPUT2 мы заставим моторчик вращаться. А если теперь поменять сигналы местами и подавать на INPUT1 сигнал LOW, а на INPUT2 сигнал HIGH – мы заставим моторчик вращаться в другую сторону.
Аналогично для второго драйвера.
Выход Vss (ножка
16) отвечает за питание самой микросхемы, а выход Vs (ножка
8) отвечает за питание моторчиков – это обеспечивает разделение электропитания для микросхемы и для управляемых ею двигателей, что позволяет подключить электродвигатели с напряжением питания отличным от напряжения питания микросхемы.
Разделение электропитания микросхем и электродвигателей также необходимо для уменьшения помех, вызванных бросками напряжения, связанными с работой моторов.
Четыре контакта GND (ножки 4, 5, 12,13) нужно соединить с землёй. Так же эти контакты обеспечивают теплоотвод от микросхемы.
Характеристики L293D
напряжение питания двигателей (Vs) от 4,5 до 36В
напряжение питания микросхемы (Vss) 5В
допустимый ток нагрузки 600мА (на каждый канал)
пиковый (максимальный) ток на выходе 1,2A (на каждый канал)
логический "0" входного напряжения до 1,5В
логическая "1" входного напряжения 2,3...7В
скорость переключений до 5 кГц.
Если использовать микросхему
L293E, то допустимый ток нагрузки на каждый канал уже будет 1А (а пиковый ток – 2А),
но придётся использовать внешние защитные диоды, которые у L293D встроены в саму микросхему.
Попробуем смоделировать как Arduino справляется с управлением моторчиками :)
Запускаем Proteus и открываем проект с Arduino :)
Добавим на схему наш драйвер – L293D
Соединим выводы Vss и Vs с положительным полюсом батареи, выводы GND соединим с землёй, а к выводам 3,6 и 11,14 подсоединим моторчики – соответственно MOTOR1 и MOTOR2.
В реальной схеме — параллельно к моторчику нужно припаять конденсатор – он помогает справиться с наводками от работающего электродвигателя ( это распространённая практика — разберите любую игрушку с моторчиком и увидите, что прямо к моторчику припаян керамический конденсатор номиналом где-то в 0,1 мкф )
А как же соединить входы драйверов? Для начала, посмотрим – как вообще это работает на практике :)
Загрузим в МК скетч Blink или Blink_HL, а далее, как показано на рисунке, соединим INPUT1 и ENABLE1 с digital pin 13, к которому подключен светодиод, а INPUT2 соединим с землёй. Запустим симуляцию и увидим, что моторчик одну секунду вращается в одну сторону, а потом останавливается на секунду. Т.е. получили
моторчиковый Blink :)
Итак, получается, что для управления одним моторчиком требуется
три порта(один из них — PWM).
Если скоростью вращения моторчика управлять не требуется, то можно сэкономить на PWM-портах (ENABLE1 и ENABLE2). Тогда, для управления одним моторчиком нужно будет задействовать
два порта.
Итак, определимся с портами (в скобках – соответствующий номер ножки МК из
pin mapping ):
MOTOR1
11 (17) – PWM ENABLE1
12 (18) INPUT2
13 (19) INPUT1
MOTOR2
7 (13) INPUT3
8 (14) INPUT4
9 (15) – PWM ENABLE2
Изменим наш проект в Proteus-е:
А теперь напишем скетч.
Для удобства – будем хранить номера портов не в обычных переменных типа int, а объединим их структурой:
struct MOTOR // структура для хранения номеров pin-ов, к которым подключены моторчики
{
int in1; // INPUT1
int in2; // INPUT2
int enable; // ENABLE1
};
однако, если просто объявить такую структуру в коде скетча, например так:
/*
* тестовый скетч с L293
*/
struct MOTOR // структура для хранения номеров pin-ов, к которым подключены моторчики
{
int in1; // INPUT1
int in2; // INPUT2
int enable; // ENABLE1
};
// определяем порты, к которым подключены моторчики
MOTOR MOTOR1 = { 13, 12, 11 };
MOTOR MOTOR2 = { 7, 8, 9 };
void set_m_pins(MOTOR *m);
void setup()
{
set_m_pins(&MOTOR1);
set_m_pins(&MOTOR2);
Serial.begin(9600);
}
void loop()
{
delay(1000);
}
void set_m_pins(MOTOR *m)
{
if(m)
{
pinMode(m->in1, OUTPUT);
pinMode(m->in2, OUTPUT);
}
}
То при попытке скомпилировать — получим ошибку:
error: variable or field 'set_m_pins' declared void In function 'void setup()':
— дело в том, что дополнительные структуры данных должны объявляться в заголовочных (.h) файлах.
Т.е. нужно создать библиотечный файл и подключиться его к скетчу директивой #include
Однако, тут компилятору не нравится именно обращение к новому типу данных по указателю.
Изменим скетч:
/*
* тестовый скетч с L293
*/
struct MOTOR // структура для хранения номеров pin-ов, к которым подключены моторчики
{
int in1; // INPUT1
int in2; // INPUT2
int enable; // ENABLE1
};
// определяем порты, к которым подключены моторчики
MOTOR MOTOR1 = { 13, 12, 11 };
MOTOR MOTOR2 = { 7, 8, 9 };
void setup()
{
Serial.begin(9600);
pinMode(MOTOR1.in1, OUTPUT); // настраиваем выводы
pinMode(MOTOR1.in2, OUTPUT); // на ВЫВОД
pinMode(MOTOR2.in1, OUTPUT);
pinMode(MOTOR2.in2, OUTPUT);
}
void loop()
{
forward1(); // вращаем оба моторчика вперёд
forward2();
delay(3000);
back2(); // вращаем второй моторчик назад
delay(500);
forward2(); // а теперь опять вращаем второй моторчик вперёд
}
void forward1() // первый вперёд
{
digitalWrite(MOTOR1.in1, HIGH);
digitalWrite(MOTOR1.in2, LOW);
analogWrite(MOTOR1.enable, 254);
}
void forward2() // второй вперёд
{
digitalWrite(MOTOR2.in1, HIGH);
digitalWrite(MOTOR2.in2, LOW);
analogWrite(MOTOR2.enable, 254);
}
void back1() // первый назад
{
digitalWrite(MOTOR1.in1, LOW);
digitalWrite(MOTOR1.in2, HIGH);
analogWrite(MOTOR1.enable, 254);
}
void back2() // второй назад
{
digitalWrite(MOTOR2.in1, LOW);
digitalWrite(MOTOR2.in2, HIGH);
analogWrite(MOTOR2.enable, 254);
}
Три секунды оба моторчика вращаются вперёд, затем пол-секунды второй моторчик вращается назад, а потом снова вперёд.
Перенесём структуру и функции в
нашу библиотеку RoboCraft.
/*
* robocraft.h
*
* RoboCraft - library fo RoboCraft.ru project
* RoboCraft - библиотека для проекта RoboCraft.ru
*
*
* Written by noonv, August 2009.
*/
#ifndef robocraft_h
#define robocraft_h
#include "WProgram.h"
#define _RCDEBUG_ 1
struct MOTOR // структура для хранения номеров pin-ов, к которым подключены моторчики
{
int in1; // INPUT1
int in2; // INPUT2
int enable; // ENABLE1
};
class RoboCraft
{
public:
RoboCraft();
RoboCraft(MOTOR *m1, MOTOR *m2);
void hello();
void motor_forward(int m,int speed=254);
void motor_back(int m, int speed=254);
private:
void set_m_pins(MOTOR *m);
void m_forward(MOTOR *m,int speed=254);
void m_back(MOTOR *m,int speed=254);
MOTOR MOTOR1;
MOTOR MOTOR2;
};
#endif // #ifndef robocraft_h
А скетч тогда будет таким:
#include <robocraft.h>
//
// тестовый скетч с L293
// добавили пробные функции для работы с моторчиками через L293
//
//
// by noonv <http://www.robocraft.ru>
//
MOTOR MOTOR1 = { 13, 12, 11 };
MOTOR MOTOR2 = { 7, 8, 9 };
RoboCraft robot(&MOTOR1, &MOTOR2); // создаём экземпляр нашего класса
void setup()
{
Serial.begin(9600);
robot.hello(); // говорим "Hello" :)
}
void loop()
{
Serial.println("loop");
robot.motor_forward(0,254); // оба полный вперёд :)
delay(3000);
robot.motor_back(2,254); // крутим второй назад
delay(1000);
robot.motor_forward(2,254); // и снова 2-й вперёд!
}
Функции вращения принимают два параметра – номер моторчика(1-2) и скорость вращения (0-255). Если номер отличается от 1-2, то вращение задаётся сразу обоим моторчикам.
У меня под рукой оказалась микросхема L293E – поэтому необходимо использовать защитные диоды (1N4007), которых для двух моторчиков нужно аж 8 штук :)
Так же у L293E не 16, а целых 20 ножек:
Впрочем, для тестирования можно собрать схему только для одного моторчика ;)

Соответственно нужно внести изменения в скетч:
MOTOR MOTOR1 = { 13, 12, 11 };
MOTOR MOTOR2 = { 7, 8, 9 };
RoboCraft robot(&MOTOR1, &MOTOR2); // создаём экземпляр нашего класса
void setup()
{
Serial.begin(9600);
robot.hello(); // говорим "Hello" :)
}
void loop()
{
Serial.println("loop");
robot.motor_forward(0,254); // полный вперёд :)
delay(3000);
robot.motor_back(1,254); // крутим назад
delay(1000);
}
— крутим наш моторчик 3 секунды вперёд, а затем одну секунду назад.

Крутится :)
читать далее
Простой мотор-шилд для Arduino/CraftDuino
Ещё пара слов про L293
L-Motor Shield
Ссылки
ДРАЙВЕР ДВИГАТЕЛЕЙ L293D
http://www.arduino.cc/playground/Code/Struct
Комментарии (49)
RSS свернуть / развернутьsavarez
Другой вопрос что данный драйвер кушает порядка 2х вольт от напряжения питания двигателей, и в низковольтовых конструкциях(5 или 3.3) лучше применять драйвера по современнее например
skystorm
savarez
Драйвер это слово умное такое.Ни к чему не обязывающее.Это просто то что управляет, в данном случае мощной нагрузкой (т.е. поставите оптрон — его тоже можно будет драйвером назвать=)
И кстати оптрон, который будет тянуть 1.5А(как ЭЛЬка) оптроном назвать язык не поворачивается, это уже твердотельное релле, с соотвествующей ценой=))
И, что главное, с одной ЭЛЬкой можно управлять, с реверсом 2я двигателями — подключил и готово. А «оптроном» или транзистором только в одну сторону — без проблем, реверс добавить — повозится придётся.
Не много, но придётся — сложно сказать что это проще=)
Zoltberg
savarez
taraba4
зы: просто задумался о покупке Motor Shield 2, но 800рублей… вот ищу варианты замены…
taraba4
Подробнее про управление сервами можно прочитать здесь:
noonv
2. Если необходим допустимый ток нагрузки 10А?
pepper
2. атут Элькой точно не обойтись=)
А это именно двигатель?
Регулировать скорость надо?
Изменять направление вращения надо?
Zoltberg
2. Да элькой не обойтись =(((
2.1. Двигатель из стеклоподъемника =)10А это ток короткого замыкания(это граница за которую лучше не выходить, а горит он при 28А), рабочий при опускании 0,3-0,6А при подъёме 3-6А. Есть схема через н-мост, но ищу именно микруху.
2.2. Регулировать скорость надо ШИМом.
2.3. Изменять направление вращения надо.
Для чего мне это нужно?
1. Стекло подъёмник =) (требуеться 2.1. и 2.2.)
2. Есть интерестная идея под Ардуино(как сделаю запишу видео и статью)(требуеться 2.1. и 2.3.)
Т.е. можно два разных драйвера первый у которого есть 2.1. и 2.2., а второй соответсвенно 2.1. и 2.3.; а если есть всё в одном то это просто ВЕЛИКОЛЕПНО!!!
pepper
2. Не совсем понял что такое ток короткого замыкания, а тем более — ток при которм горит 0_о… Максимальный ток двигатель потребляет в заторможенном состоянии. И обычно у него вполне конкретное напряжение питания… Например — имеем питание 12в, холостой ход 0,5А, с заторможенным валом 10А, а до бОльших токов его можно разогнать только увеличением питания…
«Микросхем» на 10А незнаю, темболее мостовых… А может без моста и микросхем?=)
Транзистор и перекидное релле?
и ШИМ и реверс, транзистор (полевичок) на такой ток найти легко.
Zoltberg
перекидное реле боюсь не справяться с ШИМом. У реле частота переключений вроде около 10Гц. А вот Н-мост как заменитель микрухи тоже можно расмотреть =)
pepper
Аллах свами! Зачем релёй-то ШИМить???
ШИМ даёт транзистор — дальше через де группы контактов реле на двигатель.
От положения контактов реле зависит направление вращения двигателя.
От ШИМа на транзисторе — скорость вращения.
Zoltberg
XFree
т.к. ток через один пин не должен превышать 40 mA.
Т.о. образом чтобы управлять даже этим маломощным моторчиком нужен «драйвер», которым, например, может выступать ключевой транзистор.
noonv
XFree
oleamm
О чем это сигнализирует?
chiibis
Это сигализируеи о том что он есть(ШИМ=)
Чтобы его не было надо на нагрузке фильтровать, например так:
Или
изучаем библиотеку
Zoltberg
Собрал драйвер с робозона — то же самое на L298, помощнее и перед входами направления поставлена логика для уменьшения числа выходов.
Прошивку использую вашу. Но есть глюк.
Один канал честно регулируется от нуля до 254, второй же — только логический уровень — ноль или пять вольт.
Прошивка вот
Где я дурак?
Shihad
внимательно читаем статью про библиотеку
т.о. или просто пробуем убрать Servo из скетча :)
или используем для управления не 10-й пин, а 3, 5 или 6.
admin
Shihad
die
Помогите пожалуйста разобраться.
Я начинающий и впервые увидел что, кроме void setup и void loop можно назначать какое то свое действо. Так вот. У меня получилось это, но в таком случае я никак не могу поставить условие if… Не пойму в чем дело.
Eldar
Программируя Arduino, вы, фактически,
admin
Eldar
admin
Eldar
Nikolay18
Цепляем MOSFETы к L293!
Tickat
Nikolay18
У меня двигатель на 0,9-1,3В. В посте выше написано:
Т.е. L293D не получится использовать для моего движка? Если нет, то что посоветуете?
oleamm
Можно другие микросхемы(на вскидку не помню), можно на рассыпухе сделать.
Тут больше вводных надо=)
Реверсировать надо ваш двигатель, или только обороты менять?
Ток потребления с заклиненным валом какой?
Питане какое будет использоваться?
Zoltberg
Реверс не нужен, только смена оборотов (регулировать тип вибрации).
Про ток потребления с заклиненным валом ничего сказать не могу, ибо даташита на движки нет (есть только название QX-5A). Померить пока не могу, т.к. преобразователь напряжения еще не собрал, и 1В взять неоткуда.
oleamm
Так что было бы здорово услышать совет как сделать все на простых элементах ( возможно транзистор+резисторы)? А нельзя ли использовать резистивный делитель?
oleamm
А то, что реверсировать не надо — так это вообще упрощает дело=)
Думаю так пойдёт=)
Только надо померить сопротивление обмоток моторчика и рассчитать значение R1.
Тут получается делитель где нижний резистор это ваш мотор.
скажем по результатам замера оказалось Rмотора =23ом, на нём должно быть 1,3В, а питание у нас 5В.
U1/U2=R1/R2, Uпит=U1+U2
R2=23ом
Uпит=5В
U2=1,3В -> U1=3.7В, R1=3.7*23/1.3=65ом
вроде так=)
Zoltberg
Или надо разбирать движок и измерять непосредственно сопротивление обмоток?
Если второе, то страшно представить как это делать на движке размером 10х4 мм =)
oleamm
Zoltberg
По Вашей схеме выше: можно ли вместо резистора использовать ШИМ соответствующей скважности?
Т.е. мотор на 1В, крона дает 9В. Запитаем мотор сразу от кроны (а не от 5В как на рисунке выше). Значит управляем транзистором так:
analogWrite(motor, 28);
Поясню: 28=255/9 (то есть если бы на транзистор подали шим со значением 255, на выходе было бы 9В, но нам надо 1В).
Как к подобным манипуляциям отнесется обмотка двигателя?
oleamm
MAFia
Т.е. для D — только кондёры(не строго обязательно). Диоды (как встроенные так и внешние) нужны для устранения выбросов самоиндукции от мотора.
И по
Zoltberg
MAFia
Begemot911
Диоды, например 1n4007 — оч. популярные=)
Zoltberg
Begemot911
pokatusher
admin
Aqua123
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.