Получаем информацию о знаке «Дети»

В этом уроке: 

  • Устанавливаем знак «Дети» на трассу
  • Учим машинку реагировать на знак

Установка знака на трассу

В прошлом уроке мы научились изменять скорость движения при фиксации знака «Ограничение максимальной скорости», после чего машинка ехала со скоростью 60 км/ч. Давайте установим знак «Дети», ведь наш автомобиль как раз приближается к школе.

В статье о знаке «Дети» содержится инструкция о том, как его запрограммировать. Вернитесь туда, если знак еще не собран или не запрограммирован. После этого возвращайтесь к этому уроку.

Также не забывайте, что установка знака производится в сторону, указанную стрелкой на трассе. 

Реакция машинки на знак

Знак «Дети» предполагает ограничение скорости. Мы ограничим скорость до 20 км/ч

В данном случае отрисовать изображение знака на дисплее затруднительно (ввиду сложного рисунка и низкого разрешения дисплея), поэтому давайте выведем на матрицу текст «Дети» (104 строка). Как это сделать, мы рассматривали в уроке по работе с дисплеем.

  1. if( !strcmp( ir.sign_str, "1.23" ) ){ // Eсли номер знака 1.23 - «Дети»
  2. disp.scrollPos(0); // Переходим к началу бегущей строки
  3. disp.print("Дети"); // Загружаем текст для бегущей строки
  4. disp.autoScroll(245); // Выводим загруженный текст однократно со скоростью 245
  5. speed = min_Speed; // Ограничиваем скорость до ближайшего перекрёстка или нового знака
  6. }

При обнаружении знака «Дети» машинка снизит скорость (106 строка) до ближайшего перекрёстка или знака "Ограничение максимальной скорости". 

Готовый скетч урока

  1. #include <Wire.h> // Подключаем библиотеку для работы с аппаратной шиной I2C
  2. #include <iarduino_I2C_Motor.h> // Подключаем библиотеку для работы с мотором I2C-flash
  3. #include <iarduino_I2C_Bumper.h> // Подключаем библиотеку для работы с бампером I2C-flash
  4. #include <iarduino_I2C_IR.h> // Подключаем библиотеку для работы с Trema модулями: ИК-приёмник/передатчик I2C-flash
  5. #include <iarduino_I2C_Matrix_8x8.h> // Подключаем библиотеку для работы с LED матрицей 8x8 I2C-flash
  6. iarduino_I2C_Motor mot_R (0x0A); // Объявляем объект mot_R для правого мотора, указав адрес модуля на шине I2C
  7. iarduino_I2C_Motor mot_L (0x0B); // Объявляем объект mot_L для правого мотора, указав адрес модуля на шине I2C
  8. iarduino_I2C_Bumper bum (0x0C); // Объявляем объект bum для работы с бампером I2C-flash, указав адрес модуля на шине I2C
  9. iarduino_I2C_Matrix_8x8 disp (0x0D); // Объявляем объект disp для работы с светодиодной матрицей I2C-flash, указав адрес модуля на шине I2C
  10. iarduino_I2C_IR ir(0x09); // Объявляем объект ir для работы с функциями и методами библиотеки iarduino_I2C_IR, указывая адрес модуля на шине I2C
  11. const float min_Speed = 20; // Минимальная скорость движения в км/ч. Используется при движении вблизи школ, а также на опасных участках дороги
  12. const float low_Speed = 40; // Низкая скорость движения в км/ч. Используется при движении по опасным участкам дороги или при соответствующем знаке
  13. const float mid_Speed = 60; // Средняя скорость движения в км/ч. Используется при движении по дорогам
  14. const float max_Speed = 90; // Максимальная скорость движения в км/ч. Используется при движении по скоростным дорогам
  15. float speed = mid_Speed; // Указываем, что изначально скорость равна средней
  16. int8_t val_Turn = 0; // Выбранное направление движения на перекрёстке: 0 прямо, -1 влево, +1 вправо
  17. bool flg_CrossWait = true ; // Флаг ожидания перекрёстка (машина «увидела» светофор или знак, сообщающий о наличии перекрёстка)
  18. bool flg_CrossFind = false; // Флаг обнаружения перекрёстка (бампер заехал на перекрёсток)
  19. bool flg_Turn = false; // Флаг необходимости разворота
  20. // 1.12.1 «Опасные повороты» // Изображение знака «Опасные повороты»
  21. byte Image_1_12_1[8] = { 0b00000000, //
  22. 0b00000010, // #
  23. 0b00100010, // # #
  24. 0b01010010, // # # #
  25. 0b01001010, // # # #
  26. 0b01000100, // # #
  27. 0b01000000, // #
  28. 0b00000000 }; //
  29. void setup() {
  30. mot_R.begin(); // Инициируем работу с левым мотором I2C-flash
  31. mot_L.begin(); // Инициируем работу с правым мотором I2C-flash
  32. bum.begin(); // Инициируем работу с бампером I2C-flash
  33. disp.begin(); // Инициируем работу с светодиодной матрицей I2C-flash
  34. disp.codingDetect("п"); // Выполняем автоопределение кодировки скетча
  35. mot_R.setDirection(true); // Указываем правому мотору, что его вращение должно быть прямым (по часовой стрелке при положительных скоростях)
  36. mot_L.setDirection(false); // Указываем левому мотору, что его вращение должно быть обратным (против часовой стрелки при положительных скоростях)
  37. ir.begin(); // Инициируем работу с ИК-приёмником/передатчиком I2C-flash
  38. ir.setProtocol(IR_IARDUINO); // Указываем протокол для приёма/передачи данных по ИК-каналу
  39. }
  40. void loop() {
  41. // РАЗВОРОТ:
  42. //if (bum.getCross(3, 1000)) flg_Turn = true;// Если обнаружен перекрёсток, устанавливаем флаг разворота
  43. if( flg_Turn ){ // 1 ФАЗА. Если под бампером обнаружен перекрёсток (указываем толщину линии трассы и время на преодоление перекрёстка в мс) ...
  44. // Под бампером обнаружен перекрёсток:
  45. flg_Turn = false; // Сбрасываем флаг разворота
  46. mot_R.setSpeed( convertSpeed(min_Speed), MOT_PWM ); // Устанавливаем скорость правого мотора в %
  47. mot_L.setSpeed(-convertSpeed(min_Speed), MOT_PWM ); // Устанавливаем скорость левого мотора в %
  48. // Ждём завершения манёвра:
  49. while( bum.getLineSum() > 0 ) {;} // 2 ФАЗА. Ждём выхода линии за пределы бампера. Цикл выполняется, пока под бампером есть линия
  50. while( bum.getLineSum() == 0 ){;} // 3 ФАЗА. Ждём появление линии под бампером. Цикл выполняется, пока под бампером нет линии
  51. // Останавливаемся:
  52. mot_R.setStop(); // Останавливаем правое колесо
  53. mot_L.setStop(); // Останавливаем левое колесо
  54. val_Turn = 0; // 4 ФАЗА. Выбираем движение прямо
  55. speed = mid_Speed; // Снимаем наложенные ранее ограничения скорости
  56. }
  57. // ПРОВЕРКА НАЛИЧИЯ ПЕРЕКРЁСТКОВ:
  58. if( bum.getCross(3,1000) ){ // Если под бампером обнаружен перекрёсток (указываем толщину линии трассы и время на преодоление перекрёстка в мс) ...
  59. if( flg_CrossWait ){ // Если ожидается появление перекрёстка ...
  60. flg_CrossWait = false; // Сбрасываем флаг ожидания перекрёстка
  61. flg_CrossFind = true; // Устанавливаем флаг обнаружения перекрёстка
  62. disp.clrScr(); // Чистим экран светодиодной матрицы
  63. }
  64. }
  65. else{ // Если под бампером обычная линия ...
  66. if (flg_CrossFind) { // Если ранее был обнаружен перекрёсток
  67. flg_CrossFind = false; // Сбрасываем флаг обнаружения перекрёстка
  68. val_Turn = 0; // Выбираем движение прямо
  69. speed = mid_Speed; // Снимаем наложенные ранее ограничения скорости
  70. }
  71. }
  72. if( val_Turn == -1 ){ bum.setTurnSignal(BUM_TURN_LEFT ); } // Если поворот будет осуществляться налево, включаем левый поворотник
  73. if( val_Turn == 0 ) { bum.setTurnSignal(BUM_TURN_OFF ); } // Выключаем поворотники, если машинка движется прямо
  74. if( val_Turn == 1 ) { bum.setTurnSignal(BUM_TURN_RIGHT); } // Если поворот будет осуществляться направо, включаем правый поворотник
  75. // ПРОВЕРКА НАЛИЧИЯ ПРИНЯТЫХ ИК-ДАННЫХ:
  76. if( ir.check(true) ){ // Если принят пакет данных от знака
  77. switch (ir.device) {
  78. case MODUL_TLIGHT: // Данные отправлены светофором
  79. // Пока тут пусто, светофор не подключали
  80. break;
  81. case MODUL_SIGN: // Данные отправлены дорожным знаком
  82. if(!strcmp(ir.sign_str, "1.12.1")){ // Если номер знака 1.12.1 - «Опасные повороты»
  83. speed = min_Speed; // Ограничиваем скорость до ближайшего перекрёстка или нового знака
  84. disp.drawImage(Image_1_12_1); // Выводим изображение знака
  85. }
  86. if( !strncmp( ir.sign_str, "3.24", 4) ){ // Обнаружен знак ПДД 3.24 «Ограничение максимальной скорости»:
  87. disp.print(ir.sign[2]); // Выводим цифру скорости
  88. if( ir.sign[2]< 3 ){ speed = min_Speed; }else // ir.sign[2] < 3 значит, на знаке написано меньше «30»
  89. if( ir.sign[2]< 5 ){ speed = low_Speed; }else // ir.sign[2] < 5 значит, на знаке написано меньше «50»
  90. if( ir.sign[2]< 7 ){ speed = mid_Speed; }else // ir.sign[2] < 7 значит, на знаке написано меньше «70»
  91. if( ir.sign[2]!=0 ){ speed = max_Speed; } // ir.sign[2] != 0 значит, на знаке написано «90»
  92. }
  93. if( !strcmp( ir.sign_str, "1.23" ) ){ // Если номер знака 1.23 - «Дети»
  94. disp.scrollPos(0); // Переходим к началу бегущей строки
  95. disp.print("Дети"); // Загружаем текст для бегущей строки
  96. disp.autoScroll(245); // Выводим загруженный текст однократно со скоростью 245
  97. speed = min_Speed; // Ограничиваем скорость до ближайшего перекрёстка или нового знака
  98. }
  99. break;
  100. case MODUL_CAR: // Данные отправлены другим автомобилем
  101. // Пока тут пусто, с другими машинками не взаимодействуем
  102. break;
  103. }
  104. }
  105. // ОПРЕДЕЛЯЕМ ОШИБКУ ЦЕНТРИРОВАНИЯ ЛИНИИ ПОД БАМПЕРОМ:
  106. // Если ожидается перекрёсток: машина должна ехать по центру линии, немного сместившись в сторону поворота
  107. float bum_Error; // Объявляем переменную: ошибка для П-регулятора
  108. if( flg_CrossWait ){ bum_Error = bum.getErrPID()+val_Turn; }else // Получаем ошибку центрирования линии, смещённую на 1 датчик в сторону ожидаемого поворота «val_Turn»
  109. // Если бампер заехал на перекрёсток: // Машина должна ехать по краю линии, выполняя поворот
  110. if( flg_CrossFind ){ bum_Error = bum.getSidePID(val_Turn)*3; }else // Получаем ошибку нахождения на краю линии, со стороны поворота «val_Turn». Умножаем ошибку — это увеличит резкость поворота (актуально для тонких линий трассы)
  111. // Если не ждём перекрёсток и не находимся на нём: // Машина должна ехать по центру линии
  112. { bum_Error = bum.getErrPID(); } // Получаем ошибку центрирования линии
  113. float kP = 3 + 0.125*(convertSpeed(speed)-20); // Коэффициент П-регулятора
  114. float P = bum_Error * kP; // Получаем значение от П-регулятора
  115. mot_R.setSpeed(convertSpeed(speed) - P, MOT_PWM); // Устанавливаем скорость правого мотора
  116. mot_L.setSpeed(convertSpeed(speed) + P, MOT_PWM); // Устанавливаем скорость левого мотора
  117. }
  118. float convertSpeed(float speedLevel){ // Функция преобразования скорости из км/ч в % ШИМ
  119. if (speedLevel == 0) return 0; // Если скорость равна 0, возвращаем 0
  120. else if (speedLevel < 20) return 20; // Если скорость меньше минимальной, устанавливаем минимальное заполнение ШИМ
  121. else if (speedLevel > 90) return 60; // Если скорость больше максимальной, устанавливаем максимальное заполнение ШИМ
  122. else return map(speedLevel, 20, 90, 20, 60); // Преобразование диапазона остальных скоростей
  123. }
Поздравляю с изучением данного урока!
Следующий урок:
№11. Устанавливаем знак «Конец всех ограничений».
приступить к изучению

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

Комплект знаков для базового курса по "Роботраффику" для образования (продолжение ROBORACE)

В магазин

Обсуждение

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