Движение по линии «Вижу трассу!»

В этом уроке

  • Движение по линии 
  • Калибровка бампера
  • Функции работы с бампером и моторами. Инверсия линии трассы
  • Управление поворотниками бампера

Видео версия урока

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

Давайте познакомимся с несколькими очень полезными функциями, которые мы не раз будем использовать далее.

Определение наличия линии под датчиками

Функция getLineDigital() определяет наличие линии под датчиком. Возвращает true, если линия есть, false — если нет. 
Пример использования:
 

bool i = bum.getLineDigital(5); // Если под 5 датчиком есть линия, то i = true

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

Процесс калибровки:

  1. Поместите бампер над линией таким образом, чтобы все датчики находились над линией.  Нажмите кнопку «калибровка».
  2. Поместите бампер таким образом, чтобы все датчики находились над фоном. Нажмите кнопку «калибровка».

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

Калибровку нужно производить, если:
— Сменился цвет линии трассы или фона;

— Существенно изменилась освещенность в комнате.

Бампер запоминает откалиброванное состояние. Это означает, что при очередном включении машинки (или при загрузке нового кода в неё) повторная калибровка не требуется (кроме случаев, описанных выше).

Скетч для движения машинки по линии

Движение машинки по линии можно реализовать многими способами. Один из них Вы видите ниже:

#include <Wire.h>                           //  Подключаем библиотеку для работы с аппаратной шиной I2C
#include <iarduino_I2C_Motor.h>             //  Подключаем библиотеку для работы с мотором I2C-flash
#include <iarduino_I2C_Bumper.h>            //  Подключаем библиотеку для работы с бампером I2C-flash
                                            
iarduino_I2C_Motor  mot_R (0x0A);           //  Объявляем объект mot_R для правого мотора
iarduino_I2C_Motor  mot_L (0x0B);           //  Объявляем объект mot_L для правого мотора
iarduino_I2C_Bumper bum(0x0C);              //  Объявляем объект bum  для работы с бампером I2C-flash, указав адрес модуля на шине I2C
                                             
float val_Speed = 60.0;                     //  Средняя скорость
int v = 0;                                  //  Скорость, которую мы будем добавлять или отнимать от средней скорости при отклонении машинки от центра
                                                                        
void setup(){          
  mot_R.begin();                            //  Инициируем работу с левым  мотором I2C-flash
  mot_L.begin();                            //  Инициируем работу с правым мотором I2C-flash
  bum.begin();                              //  Инициируем работу с бампером I2C-flash
  mot_R.setDirection(true);                 //  Указываем правому мотору, что его вращение должно быть прямым (по часовой стрелке при положительных скоростях)
  mot_L.setDirection(false);                //  Указываем левому мотору, что его вращение должно быть обратным (против часовой стрелки при положительных скоростях)
}                                                                          
void loop(){    
  if (bum.getLineDigital(1)){               //  Если под датчиком с 1-м номером есть линия (bum.getLineDigital(1) == true)
    v = -32;                                //  Устанавливаем скорость 
  }  
  if (bum.getLineDigital(2)){               //  Если под датчиком с 2-м номером есть линия (bum.getLineDigital(2) == true)
    v = -24;                                //  Устанавливаем скорость
  } 
  if (bum.getLineDigital(3)){               //  Если под датчиком с 3-м номером есть линия (bum.getLineDigital(3) == true)
    v = -16;                                //  Устанавливаем скорость
  }
  if (bum.getLineDigital(4)){               //  Если под датчиком с 4-м номером есть линия (bum.getLineDigital(4) == true)
    v = -8;                                 //  Устанавливаем скорость
  }
  if (bum.getLineDigital(5)){               //  Если под датчиком с 5-м номером есть линия (bum.getLineDigital(5) == true)
    v = 0;                                  //  Устанавливаем скорость
  }
  if (bum.getLineDigital(6)){               //  Если под датчиком с 6-м номером есть линия (bum.getLineDigital(6) == true)
    v = 8;                                  //  Устанавливаем скорость
  }
  if (bum.getLineDigital(7)){               //  Если под датчиком с 7-м номером есть линия (bum.getLineDigital(7) == true)
    v = 16;                                 //  Устанавливаем скорость
  }
  if (bum.getLineDigital(8)){               //  Если под датчиком с 8-м номером есть линия (bum.getLineDigital(8) == true)
    v = 24;                                 //  Устанавливаем скорость
  }
  if (bum.getLineDigital(9)){               //  Если под датчиком с 9-м номером есть линия (bum.getLineDigital(9) == true)
    v = 32;                                 //  Устанавливаем скорость
  } 
  
  mot_R.setSpeed(val_Speed - v, MOT_PWM);   //  Устанавливаем моторам скорость: увеличиваем или уменьшаем её.
  mot_L.setSpeed(val_Speed + v, MOT_PWM);   
}

В данном примере мы проверяем, под каким датчиком есть линия. В зависимости от отклонения линии от центра бампера, будем увеличивать или уменьшать скорость вращения каждого из колёс. Важно: чем больше отклонение, тем больше корректировка скорости.

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

Добавляем условие автоматической остановки

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

setSpeed(СКОРОСТЬ, ТИП СКОРОСТИ [, УСЛОВИЕ, ТИП УСЛОВИЯ ]) — устанавливает скорость вращения моторов и добавляет условие остановки.
СКОРОСТЬ — скорость в % от максимальной.
ТИП СКОРОСТИ (в контексте наших уроков это MOT_PWM) — параметр, определяющий, что число, переданное в функцию, — это процент заполнения ШИМ.
УСЛОВИЕ — время в секундах до остановки.
ТИП УСЛОВИЯMOT_SEC указывает, что остановка производится по времени.
Пример использования: 

mot.setSpeed(60, MOT_PWM, 2, MOT_SEC); // Запускаем мотор на скорости 60% с остановкой через 2 секунды

Дополнительное задание.

Реализуйте движение машинки с помощью функции getLineDigital(). Пусть движение производится с разной скоростью, а также производится периодическая остановка по времени.

Инверсия трассы

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

Рассмотренный нами ранее алгоритм движения по линии в такой ситуации не сработает, если не внести некоторые изменения.

Функция setLineType(ТИП) — устанавливает тип линии трассы. Может принимать следующие значения:
BUM_LINE_BLACK
— указать модулю, что трасса использует тёмную линию;
BUM_LINE_WHITE
— указать модулю, что трасса использует светлую линию;
BUM_LINE_CHANGE
— изменить тип линии трассы на противоположный.
Пример использования: 

bum.setLineType(BUM_LINE_CHANGE); // Меняем тип линии трассы

Бампер умеет автоматически перестраиваться при инвертировании цвета. Нужно только задать условие, при котором он будет это делать. Конечная реализация будет выглядеть так:

#include <Wire.h>                           //   Подключаем библиотеку для работы с аппаратной шиной I2C
#include <iarduino_I2C_Bumper.h>            //   Подключаем библиотеку для работы с бампером I2C-flash
iarduino_I2C_Bumper bum;                    //   Объявляем объект bum для работы с функциями и методами библиотеки
void setup(){                                             
     bum.begin();                           //   Инициируем работу с бампером
}                                                                                                            
void loop(){                                               
     if( bum.getLineSum() >= 5 ){           //   Если 5 и более датчиков бампера фиксируют линию
         bum.setLineType(BUM_LINE_CHANGE);  //   Меняем тип линии трассы
     }}

В примере выше мы с помощью функции getLineSum() (8 строка) определили, сколько всего датчиков фиксируют линию. Если их 5 и более, то это означает, что бо́льшая часть датчика находится над линией, и, вероятно, цвет линии и фона поменялись местами. В этом случае меняем тип линии трассы с помощью рассмотренной выше функции.

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

Изначально горят только центральные светодиоды датчиков, которые фиксируют линию. При въезде на инвертированный участок  на мгновение светодиоды вспыхивают — они начинают фиксировать фон как линию. Но тут срабатывает наше условие, происходит инвертирование линии, и вновь горят только центральные светодиоды — теперь за линию принимается белый цвет.

Дополнительное (обязательное) задание.

Реализуйте полноценное движение машинки по трассе с инвертированной линией.

Управление поворотниками

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

Функция setTurnSignal(РЕЖИМ) указывает режим работы поворотников бампера. Может принимать следующие значения:
BUM_TURN_OFF
— поворотники отключены;
BUM_TURN_LEFT
— включён (мигает) левый поворотник;
BUM_TURN_RIGHT
— включён (мигает) правый поворотник;
BUM_TURN_EMERGENCY
— поворотники работают в режиме аварийного сигнала;
BUM_TURN_POLICE
— поворотники работают в режиме полицейской машины;
BUM_TURN_AUTO
— поворотники работают в автоматическом режиме.

Пример использования: 

bum.setTurnSignal(BUM_TURN_AUTO); // Поворотники будут работать автоматически при движении машинки по линии

Дополнительное задание.

Добавьте в скетч движения машинки по линии управление поворотниками. Попробуйте как автоматический, так и ручной режим. 

Поздравляю с изучением данного урока!
Следующий урок:
№17. Знакомство с дисплеем 8х8 .
приступить к изучению

Продукт в магазине

«ROBORACE» — Образовательный набор на базе Arduino

В магазин

Обсуждение

Гарантии и возврат. Используя сайт, Вы соглашаетесь с условиями.