«Тело» нашего сумо-робота готово и отдельные его компоненты «мозг» — микроконтроллерная плата, «глаза» — сенсоры расстояния и черного/белого, «сильные ноги» — двигатели и драйвер управления ими, «кровь и регулятор давления крови» — батарея и преобразователь напряжения DC-DC, «кровеносная система» — провода и макетные платы, скелет – база, отвал, бампер, крепежные элементы – нормально функционируют.
Функционируют отдельно друг от друга.
Что сделает робота «человеком»?
Божественный Замысел.
Безусловно, в человеческом понимании этого сложного философского понятия. J
Этим Замыслом будет программа действий робота в «мире» робота – на ринге (дохё) для соревнований роботов-сумо.
Что он должен будет сделать в краткий миг своего «просыпания» на поле боя перед новым «сном» после выключения кнопки питания – все зависит от Вас – вашей Идеи, воплощенной в программу действий робота.
Чем более точно Вы продумали поведение робота – тем более он будет успешен в своей «жизни». Какие «знания» вы ему дали, чему Вы его обучили – только это он постарается воплотить в жизнь.
От лирики перейдем к практике. J
Давайте начнем с простого замысла – Вашему роботу надо будет просто «в лоб» вытолкнуть соперника с ринга сразу после старта поединка.
Для того, чтобы трансформировать эту идею в программу надо разобраться с окружающими Вашего робота обстоятельствами и его поведением в этих обстоятельствах.
Начнем разбираться. По правилам проведения поединков RobotChallenge.org сумо роботы устанавливаются в пределах указанной при жеребьевке четверти ринга задней частью робота по направлению друг к другу.
Обратите внимание на правила боя – это фактически «законы физики» для робота. Их нельзя нарушать.
Итак, что должен наш сумо-робот сделать при такой расстановке (предположим он стоит в левой нижней четверти ринга)?
- Сразу после старта поединка повернуться направо примерно на 135 градусов
- Увидеть соперника передним датчиком расстояния.
- Если увидел, то начать движение на него и вытолкнуть с ринга.
Для простоты сейчас не рассматриваем случаи, когда расстановка роботов отличается от вышеприведенной (другие четверти ринга, роботы ближе или дальше друг от друга).
С пунктом номер один все примерно понятно. Крутим левый двигатель вперед, правый одновременно назад. Время работы двигателей экспериментально подбираем так, чтобы робот повернулся примерно на 135 градусов.
Второй пункт с задачей увидеть соперника давайте разбирать подробнее. Первое – на каком расстоянии будем искать соперника? Помним, что ринг для минисумо имеет диаметр 77 сантиметров и выбранные нами датчики отлично измеряют расстояние от 10 до 50 сантиметров. Итак вывод простой – с учетом расстановки роботов противника лучше искать на расстоянии до 30 сантиметров от себя – будет меньше ошибок поиска.
Третий пункт также непрост. Итак – нашли и выталкиваем соперника – с этим все понятно. А если не увидели его на этом месте (он начал движение и ушел на другую позицию пока мы поворачивали робота предположим) – что будем делать? Давайте попробуем повернуться направо на небольшой угол и еще раз поискать соперника. Все эти действия будем делать если датчики черного/белого не выехали на белое поле.
Создадим блок схему программы поведения робота:
Разберем блок-схему.
Начало программы – момент, когда Вы включили питание робота.
Ожидание 5 секунд – для того, чтобы вы с соперником смогли отойти от ринга перед началом действий робота. В професссиональных соревнованиях роботы включаются по команде с пульта судьей с использованием специального стартового модуля.
Затем начинаем исполнять логику, которую с Вами разобрали чуть ранее. На блок схеме желтый ромб означает оператор условия (if(условияе){если условие выполнено}else{если условие не выполнено}), прямоугольник – оператор исполнения.
Обратите внимание – робот едет вперед при обнаружении противника 0.1 секунды, затем проверяет – не выкатился ли за пределы ринга и затем опять идет на оператор проверки – видит ли фронтальный датчик соперника.
Также обратим внимание, что робот будет искать соперников до момента его выключения кнопкой (переключателем) – из постоянного цикла нет программного выхода.
Итак, соберем программно нашего робота в единое целое – глаза, моторы и задуманное блок схемой поведение.
Скетч программы:
//Скетч для простого выталкивания соперника с ринга
//робот сразу после старта поворачивает на 135 градусов
//и если не находит соперника, то крутится направо
//подключаем «ноги»
//определяем соответствие контактов микроконтролера
//и контакам драйвера двигателей TB6612FNG
#define PWMA 3
#define AIN1 1
#define AIN2 0
#define BIN1 2
#define BIN2 7
#define PWMB 9
//включаем «глаза» для поиска соперника
//объявляем переменные, содержащие значения
//аналоговых портов микроконтроллера, подключаемых
//к ИК датчикам Sharp
int front_eye = A0;
int left_eye = A1;
int right_eye = A8;
//включем «глаза» для определения, на ринге мы находимся
//или выехали за него
//объявляем переменные, содержащие значения
//аналоговых портов, подключенных к датчикам
//QTR-1A
int left_bw = A6;
int right_bw = A11;
//процедура инициации портов
void setup()
{
//инициируем переменные моторов
pinMode(PWMA,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(BIN2,OUTPUT);
//ждем 5 секунд
delay(5000);
// делаем повопрот на 135 градусов
//левый мотор по направлению движения робота
//(против часовой стрелки)
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
//Правый мотор против направления движения робота
//(против часовой стрелки)
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMB, 255);
delay(100); // длительность задержки определяет
//угол поворота робота
//и подбирается экспериментально в зависимости
//от веса робота, моторов и колес
//останавливаем моторы
digitalWrite(AIN1,HIGH);
digitalWrite(AIN2,HIGH);
digitalWrite(PWMA,LOW);
digitalWrite(BIN1,HIGH);
digitalWrite(BIN2,HIGH);
digitalWrite(PWMB,LOW);
delay(10);
}
void loop()
{
//проверяем наличие препятствия фронтальным датчиком
//на расстоянии ближе 40 см
//(значение analogRead() — 333 по таблице)
if(analogRead(front_eye) > 333){
//левый мотор по направлению движения робота
//(против часовой стрелки)
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
//Правый мотор по направления движения робота
//(по часовой стрелке)
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, LOW);
analogWrite(PWMB, 255);
delay(100); // длительность задержки 0.1 секунда
}
else if(analogRead(left_eye) > 333){// если соперник
//не найден спереди то проверяем слева
//если соперник слева найден поворачиваем налево
//на 90 градусов
//левый мотор против направлению движения
//робота (по часовой стрелки)
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
analogWrite(PWMA, 255);
//Правый мотор по направлению движения
//робота (по часовой стрелки)
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, LOW);
analogWrite(PWMB, 255);
delay(60); // длительность задержки
//определяет угол поворота робота
//и подбирается экспериментально в
//зависимости от веса робота, моторов и колес
}
else if(analogRead(right_eye) > 333){// если
//соперник не найден спереди и слева то проверяем справа
//если соперник справа найден поворачиваем
//направо на 90 градусов
//левый мотор по направлению движения робота
//(против часовой стрелки)
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
//Правый мотор против направления движения робота
//(против часовой стрелки)
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMB, 255);
delay(30); // длительность задержки определяет
//угол поворота робота
//и подбирается экспериментально в зависимости
//от веса робота, моторов и колес
}
else
{// если не соперник не найден спереди и слева
//и справа то поворачиваем направо на 5 градусов
//левый мотор по направлению движения робота
//(против часовой стрелки)
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
//Правый мотор против направления движения
//робота (ппротив часовой стрелки)
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMB, 255);
delay(10); // длительность задержки определяет
//угол поворота робота
//и подбирается экспериментально в зависимости
//от веса робота, моторов и колес
//останавливаем моторы
digitalWrite(AIN1,HIGH);
digitalWrite(AIN2,HIGH);
digitalWrite(PWMA,LOW);
digitalWrite(BIN1,HIGH);
digitalWrite(BIN2,HIGH);
digitalWrite(PWMB,LOW);
delay(30);
}
//проверяем что робот не выскочил за пределы ринга
//оба датчика на черном поле
if((analogRead(left_bw) > 400)&&(analogRead(right_bw) > 400)){
//ничего не делаем
}
else // выехали на белое поле одним или обоими датчиками
{
//Отъезжаем на 5 сантиметров
//левый мотор против направления движения робота
//(по часовой стрелки)
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
analogWrite(PWMA, 255);
//Правый мотор против направления движения робота
//(против часовой стрелки)
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMB, 255);
delay(100); // длительность задержки определяет
//расстояние отъезда назад
//и подбирается экспериментально в зависимости
//от веса робота, моторов и колес
// разворачиваемся на 180 градусов в правую сторону
//левый мотор по направлению движения робота
//(против часовой стрелки)
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
analogWrite(PWMA, 255);
//Правый мотор против направления движения робота
//(против часовой стрелки)
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
analogWrite(PWMB, 255);
delay(130); // длительность задержки определяет
//угол поворота робота
//и подбирается экспериментально в зависимости
//от веса робота, моторов и колес
}
//конец цикла loop — идем на начало цикла и проверяем расстояние спереди
}
Все операторы в данном скетче нами уже изучались, поэтому трудностей в его понимании, надеюсь, не возникнет.
Приведем фотографии, сделанные из видеозаписи поединка с неподвижным соперником, с использованием данной программы поведения робота.
Начальная позиция.
Робот начинаем поворачиваться на 135 градусов направо (красная черта – начало отсчета, белая черта – текущее положение).
Продолжение поворота
Окончание поворота.
Обнаружен соперник. Движение вперед.
Соперник утерян из вида при движении вперед.
Начало движения направо.
Продолжение движения направо.
При продолжении движения направо соперник найден левым ИК датчиком (желтая линия).
Разворот налево на 90 градусов.
Соперник обнаружен передним ИК датчиком.
Движемся вперед к сопернику.
Врезаемся в него.
Пытаемся вытолкнуть.
Вопросы для проверки:
- Программа действий робота. Почему важно продумать все ньюансы программы?
- Правила боев роботов сумо. Какие важные детали Вы запомнили?
- Блок схема программы. Какие элементы блок схем Вы знаете? Удобно ли Вам использовать блок схему для отработки программы действий робота?
- Подумайте, как можно оптимизировать скетч? Какие одинаковые блоки операторов в программе Вы увидели?