Ваша робот-машина проедет свой первый квадрат: прямо, поворот направо на четверть оборота — и так четыре раза, а потом остановится. Вы узнаете, как Uno управляет двумя моторами через драйвер моторов L298N, как широтно-импульсная модуляция (ШИМ) задаёт скорость и почему робот, который только отсчитывает время, никогда не проедет идеальный квадрат. Это проект для начинающих, на него уйдёт около 45 минут.
Что понадобится
Arduino Uno R3Есть в симуляторе× 1Цену смотрите в магазине
Модуль драйвера моторов L298NЕсть в симуляторе× 1Цену смотрите в магазине
Мотор-редуктор TT 1:48 с колесом 65 ммЕсть в симуляторе× 2Цену смотрите в магазине
Батарейный отсек 4 × AAЕсть в симуляторе× 1Цену смотрите в магазинеШаровая опора 20 ммЕсть в симуляторе× 1Цену смотрите в магазине
Набор проводов-перемычек× 1Цену смотрите в магазине
Кабель USB A–B для Arduino Uno× 1Цену смотрите в магазине
Ещё понадобятся четыре батарейки AA и маленькая отвёртка для винтовых клемм L298N. В Маркете эта машина продаётся как набор робот-машины.
Как это работает
Драйвер моторов
Пин Uno может безопасно отдать около 20 мА. Мотору-редуктору TT во время езды нужно около 0,3 А, а когда он заблокирован и не может крутиться — примерно до 1 А. Поэтому Uno только посылает сигналы, а ток батареи на моторы переключает драйвер моторов L298N.
В L298N два H-моста, по одному на каждый мотор. H-мост может подключить мотор к батарее и так, и наоборот, поэтому мотор крутится вперёд или назад. Левым мотором управляют ENA, IN1 и IN2:
| ENA | IN1 | IN2 | Мотор |
|---|---|---|---|
| HIGH или ШИМ | HIGH | LOW | крутится вперёд |
| HIGH или ШИМ | LOW | HIGH | крутится назад |
| HIGH | HIGH | HIGH | тормозит |
| HIGH | LOW | LOW | тормозит |
| LOW | любой | любой | по инерции: вращается свободно |
Правый мотор работает так же, только через ENB, IN3 и IN4.
ШИМ: как задаётся скорость
На пине может быть только HIGH или LOW. Чтобы мотор крутился медленнее, analogWrite() очень быстро включает и выключает пин, который управляет ENA: на D5 и D6 — примерно 980 раз в секунду. Число от 0 до 255 задаёт, какая часть каждого цикла приходится на «включено». При значении 200 мотор получает питание 200/255 всего времени, то есть примерно 78 %, поэтому крутится медленнее. Это и есть ШИМ — широтно-импульсная модуляция, по-английски PWM.
Питание
Четыре батарейки AA дают около 6 В на клемму +12V драйвера L298N. На ней написано +12V, но модуль работает и от 6 В. Внутри L298N теряется около 1,8 В, поэтому на полной скорости моторы получают примерно 4,2 В.
Ещё у L298N есть небольшой стабилизатор на 5 В. С его клеммы +5V питание идёт на пин 5V платы Uno. От четырёх батареек AA стабилизатор выдаёт около 4,4 В: этого хватает, хотя напряжение немного низковато. Две платы соединяет провод GND. Сигналы работают, только когда у обеих плат один и тот же 0 В. Это называется общей землёй (GND).
Поворот с помощью двух колёс
Направление движения машины задают скорости двух её колёс. Когда оба колеса крутятся вперёд, машина едет прямо. Когда левое колесо крутится вперёд, а правое назад, машина разворачивается на месте вправо. Шаровая опора просто катится следом.
Оба мотора одинаковые, но правый установлен зеркально. При таком же подключении сигнал «вперёд» крутил бы его назад. Поэтому его провода специально подключены наоборот: к OUT4 и OUT3.
Почему квадрат никогда не получается идеальным
Скетч ничего не измеряет. Он командует «разворачивайся 450 мс» и надеется, что получится четверть оборота. Управление без измерений называется разомкнутым, или управлением без обратной связи. Вот от чего на самом деле зависит поворот:
- Батарейки. Новые батарейки AA дают около 1,5 В каждая, вместе — около 6 В. Почти разряженные дают около 1,2 В каждая, вместе — около 4,8 В. За вычетом 1,8 В, которые теряются в L298N, моторы получают около 3 В вместо 4,2 В, и каждый поворот становится короче.
- Пол. На гладкой плитке колёса проскальзывают, а на ковре шаровая опора плохо катится.
- Моторы. Двух совершенно одинаковых моторов TT не бывает. Если один крутится чуть быстрее, на прямых сторонах машину уводит в сторону.
- Инерция. Когда скетч переключается с езды прямо на поворот, машина останавливается не сразу. Она ещё немного скользит вперёд.
Поэтому TURN_MS даёт хороший квадрат только на том полу и с теми батарейками, с которыми вы его настраивали. Чтобы двигаться точно, робот должен измерять, что произошло на самом деле. Этим занимаются датчики, и в следующих проектах они появятся.
Сборка
1. Возьмите машину в симуляторе
У Obstacle avoider, машины, которая есть в игре с самого начала, те же ярусы, моторы, колёса, батарейный отсек, Uno и L298N, что и у этой машины. На ней стоит ещё HC-SR04, который в этом проекте не нужен: снимите его в «Сборке» или оставьте, скетч его не читает. Провода у неё подключены не так, как в таблице ниже, поэтому на шаге 2 вы подключите их заново.
В реальной сборке: прикрутите оба мотора TT снизу к нижней пластине (ярусу), наденьте колёса 65 мм и закрепите шаровую опору снизу спереди. Батарейный отсек установите между двумя пластинами. На верхней пластине закрепите плату Uno сзади, а L298N — перед ней. Батарейки пока не вставляйте.
2. Подключите провода
| Откуда | Куда | Зачем |
|---|---|---|
| Батарея + | L298N +12V | Питание моторов: около 6 В от четырёх батареек AA |
| Батарея - | L298N GND | Минус батареи |
| L298N +5V | Uno 5V | Стабилизатор драйвера питает Uno: около 4,4 В |
| L298N GND | Uno GND | Общая земля: сигналам нужен общий 0 В |
| Uno D5 | L298N ENA | Скорость левого мотора (ШИМ); перемычка ENA снята |
| Uno D4 | L298N IN1 | Направление левого мотора |
| Uno D7 | L298N IN2 | Направление левого мотора |
| Uno D8 | L298N IN3 | Направление правого мотора |
| Uno D12 | L298N IN4 | Направление правого мотора |
| Uno D6 | L298N ENB | Скорость правого мотора (ШИМ); перемычка ENB снята |
| Левый мотор M+ | L298N OUT1 | |
| Левый мотор M- | L298N OUT2 | |
| Правый мотор M+ | L298N OUT4 | Переставлено специально: этот мотор стоит зеркально |
| Правый мотор M- | L298N OUT3 | Переставлено специально: этот мотор стоит зеркально |
Симулятор проверяет подключение и показывает проблемы, например отсутствие общей земли или 5 В от L298N на пине VIN вместо 5V.
В реальной сборке: прежде чем подключать D5 и D6, снимите две маленькие перемычки (джамперы) с ENA и ENB. Если перемычки на месте, моторы всегда крутятся на полной скорости. На большинстве модулей рядом с клеммами питания есть ещё одна перемычка. Её не снимайте: она включает стабилизатор на 5 В. Слегка потяните каждый провод в винтовой клемме, чтобы проверить, что он держится.
3. Загрузите скетч
Откройте «Код», вставьте скетч FirstDrive с этой страницы, нажмите «Проверить», а затем «Загрузить».
В реальной сборке: вставьте батарейки и поставьте машину на коробку так, чтобы колёса висели в воздухе. Подключите USB-кабель и загрузите скетч. Когда колёса закрутятся, проверьте их. На прямых сторонах оба колеса крутятся вперёд. На поворотах левое колесо крутится вперёд, а правое — назад.
4. Заезд по квадрату
Запустите заезд на арене. Через секунду машина один раз проедет по квадрату и остановится. На панели показаний в реальном времени видно, что происходит с моторами и батареей.
В реальной сборке: отключите USB-кабель. Поставьте машину на ровный пол, чтобы вокруг было примерно по метру свободного места в каждую сторону, и нажмите кнопку RESET на Uno. Через секунду машина проедет по квадрату. Чтобы повторить, снова нажмите RESET.
5. Настройте поворот
Посмотрите на первый угол. Машина повернула на четверть оборота (90 градусов), больше или меньше?
| Что вы видите | Что изменить |
|---|---|
| Поворот слишком маленький | увеличьте TURN_MS на 20–30 |
| Поворот слишком большой | уменьшите TURN_MS на 20–30 |
| Каждый раз повороты разные | уменьшите SPEED, например до 160, и снова настройте TURN_MS |
| Стороны слишком длинные или слишком короткие | измените STRAIGHT_MS |
Меняйте по одному числу за раз, затем загружайте скетч и проверяйте снова. Для более медленного разворота нужно значение TURN_MS побольше. Не опускайте SPEED ниже примерно 90: при меньших значениях моторы TT могут только гудеть. Потом попробуйте свои числа на настоящей машине, а позже — со старыми батарейками. Квадрат изменится, хотя скетч останется прежним.
Код
// First drive: the robot drives a square once, then stops.
// L298N: ENA -> D5, IN1 -> D4, IN2 -> D7 (left motor, A)
// ENB -> D6, IN3 -> D8, IN4 -> D12 (right motor, B)
// The ENA and ENB jumpers are off: the Arduino sets each motor's speed with PWM.
const byte ENA = 5, IN1 = 4, IN2 = 7;
const byte ENB = 6, IN3 = 8, IN4 = 12;
const int SPEED = 200; // 0..255
const int STRAIGHT_MS = 1200; // one side of the square
const int TURN_MS = 450; // about a quarter turn: tune it for your robot and floor
// speed from -255 (full backwards) to 255 (full forwards); 0 lets the motor coast
void setMotor(byte enablePin, byte inA, byte inB, int speed) {
speed = constrain(speed, -255, 255);
digitalWrite(inA, speed > 0);
digitalWrite(inB, speed < 0);
analogWrite(enablePin, abs(speed));
}
void drive(int left, int right) {
setMotor(ENA, IN1, IN2, left);
setMotor(ENB, IN3, IN4, right);
}
void setup() {
const byte pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
for (byte pin : pins) pinMode(pin, OUTPUT);
delay(1000); // one second to put the robot down
for (int side = 0; side < 4; side++) {
drive(SPEED, SPEED); // straight ahead
delay(STRAIGHT_MS);
drive(SPEED, -SPEED); // spin right on the spot
delay(TURN_MS);
}
drive(0, 0); // done: stop
}
void loop() {
// Nothing here: the square is driven once, in setup().
}Пины и настройки
Первые строки дают имена шести пинам драйвера — как в таблице подключения. Под ними три настройки, которые вы подбираете: SPEED, STRAIGHT_MS и TURN_MS.
setMotor(): один мотор
void setMotor(byte enablePin, byte inA, byte inB, int speed) {
speed = constrain(speed, -255, 255);
digitalWrite(inA, speed > 0);
digitalWrite(inB, speed < 0);
analogWrite(enablePin, abs(speed));
}Скорость меняется от -255 (полный ход назад) до 255 (полный ход вперёд), а constrain() не даёт ей выйти за эти пределы. Для скорости вперёд условие speed > 0 истинно (true), а true означает HIGH. Поэтому на inA будет HIGH, а на inB — LOW: это «вперёд» по таблице драйвера. При скорости назад всё наоборот. При 0 на пине разрешения (enable) тоже LOW, поэтому мотор вращается по инерции. analogWrite() задаёт ШИМ по скорости без знака: abs(-200) равно 200.
drive(): оба мотора
drive(left, right) вызывает setMotor() дважды: для левого мотора на ENA, IN1 и IN2 и для правого — на ENB, IN3 и IN4. Дальше в скетче речь идёт только о скоростях колёс.
setup(): весь квадрат
Сначала шесть управляющих пинов становятся выходами: for (byte pin : pins) вызывает pinMode() для каждого пина из массива. Затем идёт сам квадрат:
delay(1000); // one second to put the robot down
for (int side = 0; side < 4; side++) {
drive(SPEED, SPEED); // straight ahead
delay(STRAIGHT_MS);
drive(SPEED, -SPEED); // spin right on the spot
delay(TURN_MS);
}
drive(0, 0); // done: stopЦикл for выполняет своё тело четыре раза, по разу на каждую сторону. drive() настраивает моторы, а delay() даёт им поработать. Пины сохраняют своё состояние, пока скетч его не изменит. В конце drive(0, 0) останавливает оба мотора. Функция loop() пустая, поэтому квадрат проезжается только один раз. Чтобы проехать его снова, нажмите RESET.
Если что-то не работает
- Колесо крутится не в ту сторону, или машина вертится на месте вместо того, чтобы ехать прямо. Поменяйте местами два провода этого мотора на L298N: OUT1 с OUT2 или OUT3 с OUT4. Проверяйте, когда колёса висят в воздухе, как в шаге 3.
- Ничего не движется. Проверьте батарейки, провода к +12V и GND и провод GND между L298N и Uno. В симуляторе прочитайте, о каких проблемах сообщает проверка подключения.
- Моторы всегда крутятся на полной скорости (в реальной сборке). На ENA и ENB всё ещё стоят перемычки.
- Один мотор не крутится. Проверьте его провод разрешения (D5 к ENA, D6 к ENB) и провода самого мотора.
- Uno не запускается от батареек. Клемма +5V драйвера L298N должна идти на пин 5V платы Uno, а не на VIN. Для VIN нужно 7–12 В, так что 4,4 В там слишком мало.
- Машина начинает квадрат, останавливается и начинает снова. Uno перезагружается. Когда моторы запускаются, напряжение батареи падает, а вместе с ним проседает и питание Uno. Это называется просадкой питания (brown-out). Поставьте новые батарейки и используйте короткие провода питания. Добавьте конденсатор 100–470 мкФ между +12V и GND рядом с драйвером, минусовой ножкой к GND. Подробнее — в статье о том, почему роботы перезагружаются.
Что дальше
У езды по времени есть предел: робот не видит, что у него получилось. В следующем проекте машина получит ультразвуковой датчик, чтобы видеть стену и реагировать на неё: это робот, объезжающий препятствия.
Чтобы узнать больше, прочитайте урок про моторы и L298N, а также статьи про моторы-редукторы TT и о том, какой драйвер моторов выбрать. Если роботы для вас в новинку, начните с урока о том, что такое робот.
Сделайте лучше
- Пусть машина проедет по треугольнику: три стороны и три поворота на 120 градусов. Подберите новое время поворота.
- Сделайте квадрат с поворотами налево: в команде поворота перенесите знак минус на другое колесо.
- Если на прямых сторонах машину уводит в сторону, дайте более быстрому мотору чуть меньшую скорость.
