Дистанционное управление с ИК-пульта

В этом уроке

  • Как работает передача данных с помощью инфракрасного света
  • Установка ИК-приёмника на машинку
  • Определение кодов, отправляемых пультом
  • Дистанционное управление машинкой с помощью ИК-пульта

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

Принцип работы инфракрасных пультов

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

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

ИК-пульт (пульт дистанционного управления, инфракрасный пульт) — отправляет сигнал. 

ИК-приёмник (инфракрасный приёмник) — принимает сигнал.

Каждая кнопка на пульте имеет свой уникальный номер — код вида 0xFFxxxx (например, 0xFFA25D). Когда пульт отправляет это номер, приёмник получает его и направляет в контроллер, где мы сравниваем этот код со всеми возможными кодами кнопок пульта. При совпадении кодов выполняется необходимое действие. Таким образом, каждой кнопке можно назначить определённый алгоритм. 

Устанавливаем модуль на машинку

Установите ИК-приёмник на обозначенную колодку при помощи стоек среднего размера, винтов и гаек. Вывод S ИК-приёмника окажется подключенным к 3 выводу Arduino. 

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

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

Рассмотрим функции библиотеки, которые Вам понадобятся для управления машинкой.

Функция check() — проверяет наличие принятых с пульта данных.
Синтаксис: check( [ УДЕРЖАНИЕ ] );
УДЕРЖАНИЕ — параметр реакции на удержание кнопок пульта. Если параметр не указан или равен false, то функция будет реагировать только на НАЖАТИЕ кнопок, а если указать true, то функция реагирует и на НАЖАТИЕ, и на УДЕРЖАНИЕ.

Пример:

if( IR.check() ){ ... }        // Если принимаются данные с пульта при нажатии кнопки
if( IR.check(true) ){ ... }    // Если принимаются данные с пульта при удержании кнопки

В следующем примере переменная data возвращает код кнопки, принятый с пульта.

if( IR.check() ){              // Если код кнопки принят
  Serial.println( IR.data );   // Выводим его в монитор порта
}

Помните, что при смене пульта код кнопки может измениться. Используйте следующий скетч для того, чтобы узнать коды кнопок. Они будут выводиться в «Монитор порта». 

#include <iarduino_IR_RX.h>         // Подключаем библиотеку для работы с ИК-приёмником
iarduino_IR_RX IR(3);               // Объявляем объект IR с указанием вывода, к которому подключён ИК-приёмник
void setup(){
  IR.begin();                       // Инициируем работу с ИК-приёмником
  Serial.begin(9600);               // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек
}                                                                                                                             
void loop(){
  if(IR.check(true)){               // Если в буфере имеются данные, принятые с пульта (кнопка нажата или удерживается)
    Serial.println(IR.data, HEX);   // Выводим код нажатой кнопки
}}

В «Мониторе порта» Вы видите код кнопки. Проверьте, что все коды кнопок Вашего пульта соответствуют кодам кнопок следующего скетча.

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

#include <iarduino_IR_RX.h>              // Подключаем библиотеку для работы с ИК-приёмником
#include <Wire.h>                        // Подключаем библиотеку для работы с шиной I2C
#include <iarduino_I2C_Motor.h>          // Подключаем библиотеку для работы с мотором
iarduino_IR_RX IR(3);                    // Объявляем объект IR с указанием вывода, к которому подключён ИК-приёмник
iarduino_I2C_Motor  mot_R (0x0A);        // Объявляем объект mot_R для правого мотора
iarduino_I2C_Motor  mot_L (0x0B);        // Объявляем объект mot_L для левого мотора

int maxSpeed = 100;                      //  Скорость мотора (% ШИМ - 0...100)     
int pwm_R;                               //  Скорость правого мотора
int pwm_L;                               //  Скорость левого мотора             
long flagTime;                           //  Время нажати кнопки пульта
void setup() {
  IR.begin();                            // Инициируем работу с ИК-приёмником
  mot_R.begin();                         // Инициируем работу с правым мотором
  mot_L.begin();                         // Инициируем работу с левым мотором
  mot_R.setDirection(true);              // Задаём направление вращения правого мотора 
  mot_L.setDirection(false);             // Задаём направление вращения левого мотора 
}
void loop() {
  if (IR.check(true)){                                                                       // Если в буфере имеются данные, принятые с пульта (была нажата кнопка)
    if (IR.data == 0xFFA25D) {flagTime = millis(); pwm_R = maxSpeed; pwm_L = maxSpeed/2;}    // Стрелка вверх-влево
    if (IR.data == 0xFF629D) {flagTime = millis(); pwm_R = maxSpeed; pwm_L = maxSpeed;}      // Стрелка вперёд
    if (IR.data == 0xFFE21D) {flagTime = millis(); pwm_R = maxSpeed/2; pwm_L = maxSpeed;}    // Стрелка вперёд-направо
    if (IR.data == 0xFF22DD) {flagTime = millis(); pwm_R = maxSpeed; pwm_L = -maxSpeed;}     // Стрелка влево
    if (IR.data == 0xFFC23D) {flagTime = millis(); pwm_R = -maxSpeed; pwm_L = maxSpeed;}     // Стрелка вправо
    if (IR.data == 0xFFE01F) {flagTime = millis(); pwm_R = -maxSpeed; pwm_L = -maxSpeed/2;}  // Стрелка назад-влево
    if (IR.data == 0xFFA857) {flagTime = millis(); pwm_R = -maxSpeed; pwm_L = -maxSpeed;}    // Стрелка назад
    if (IR.data == 0xFF906F) {flagTime = millis(); pwm_R = -maxSpeed/2; pwm_L = -maxSpeed;}  // Стрелка назад-вправо
  
    if (IR.data == 0xFF30CF) {if (IR.key_press) maxSpeed = 30;}       // Красная кнопка - 1 скорость
    if (IR.data == 0xFF18E7) {if (IR.key_press) maxSpeed = 70;}       // Зеленая кнопка - 2 скорость
    if (IR.data == 0xFF7A85) {if (IR.key_press) maxSpeed = 100;}      // Фиолетовая кнопка - 3 скорость
  }
  if (flagTime + 200 > millis()){        //  Если кнопка удерживается более 200 мс
    mot_R.setSpeed(pwm_R, MOT_PWM);      //  Запускаем правый мотор
    mot_L.setSpeed(pwm_L, MOT_PWM);      //  Запускаем левый мотор
  }
  else{                                  //  Иначе останавливаем моторы
    mot_R.setSpeed(0, MOT_PWM);          //  Запускаем правый мотор
    mot_L.setSpeed(0, MOT_PWM);          //  Запускаем левый мотор
  }
}

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

1) Попробуйте реализовать управление машинкой с помощью ИК-пульта от телевизора. Например, кнопки увеличения и уменьшения громкости могут изменять скорость машинки, а кнопки навигации (вверх, вниз, вправо, влево) — отвечать за перемещение. 

2) Также Вы можете добавить режимы автоматического движения машинки, например, при нажатии кнопки с номером 1 машинка начинает ездить по квадрату, 2 — по кругу.

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

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

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

В магазин

Обсуждение

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