В этом уроке
- Движение по линии
- Калибровка бампера
- Функции работы с бампером и моторами. Инверсия линии трассы
- Управление поворотниками бампера
Видео версия урока
Пришло время научить наш автомобиль двигаться по трассе. Пока что мы сделаем это одним из самых простых способов, но через несколько уроков вернёмся к данной задаче.
Давайте познакомимся с несколькими очень полезными функциями, которые мы не раз будем использовать далее.
Определение наличия линии под датчиками
Функция getLineDigital() определяет наличие линии под датчиком. Возвращает true, если линия есть, false — если нет.
Пример использования:
bool i = bum.getLineDigital(5); // Если под 5 датчиком есть линия, то i = true
После загрузки скетча, содержащего эту функцию, необходимо выполнить калибровку
бампера. Ведь оттенок или даже цвет линии может быть разным, и бампер не знает, какие получаемые с его датчиков значения интерпретировать как линию, а какие — как фон.
Процесс калибровки:
- Поместите бампер над линией таким образом, чтобы все датчики находились над линией. Нажмите кнопку «калибровка».
- Поместите бампер таким образом, чтобы все датчики находились над фоном. Нажмите кнопку «калибровка».
При успешной калибровке загорится зеленая подсветка. В случае неудачи она несколько раз моргнёт. После калибровки можете поставить машинку на линию и посмотреть на зеленые светодиоды. Они будут обозначать датчики, которые зафиксировали линию.
Калибровку нужно производить, если:
— Сменился цвет линии трассы или фона;
— Существенно изменилась освещенность в комнате.
Бампер запоминает откалиброванное состояние. Это означает, что при очередном включении машинки (или при загрузке нового кода в неё) повторная калибровка не требуется (кроме случаев, описанных выше).
Скетч для движения машинки по линии
Движение машинки по линии можно реализовать многими способами. Один из них Вы видите ниже:
#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); // Поворотники будут работать автоматически при движении машинки по линии
Дополнительное задание.
Добавьте в скетч движения машинки по линии управление поворотниками. Попробуйте как автоматический, так и ручной режим.
Обсуждение