#13 Эксперимент “Дистанционное управление”
Сегодня мы будем работать с датчиком, который в своё время можно было встретить практически в любой бытовой технике. Это ИК-приёмник или ИК-датчик. Приемники инфракрасного излучения получили широкое применение в бытовой технике, благодаря доступной цене, простоте и удобству в использовании. Эти устройства позволяют управлять приборами с помощью пульта дистанционного управления и их можно встретить практически в любом виде техники. Но, несмотря на это, bluetooth и w-fi модули набирают всё большую популярность, и постепенно вытесняют ИК-датчики. Несмотря на дешевизну и удобство использования, передача сигнала с помощью ИК-импульсов имеет свои недостатки, например:
- Передатчик и приёмник должны находится в зоне прямой видимости и на расстоянии не менее 10 метров (зачастую, на таком расстоянии, ИК-пульты уже начинают работать некорректно);
- Абсолютная невозможность передачи сигнала даже сквозь тонкие стены;
- Низкая скорость передачи сигнала.
Тем не менее, благодаря тому, что ИК-датчики очень дёшевы, их до сих пор активно применяют там, где не требуется передача больших объёмов данных и не приходится передавать их, например, из другой комнаты. Например, в телевизорах, кондиционерах, автомагнитолах и прочих бытовых приборах.
Перед выполнением эксперимента прочтите:
СБОРКА УСТРОЙСТВА НА МАКЕТНОЙ ПЛАТЕ
Нам понадобятся следующие компоненты:
- Arduino Uno;
- USB-кабель для подключения к компьютеру;
- Беспаечная макетная плата;
- ИК-приёмник;
- Пульт ДУ из набора;
- 3 светодиода любого цвета;
- 3 резистора номиналом 220 Ом;
- 1 трёхцветный светодиод;
- 11 соединительных проводов типа “папа-папа” различных цветов.
Соберите устройство по следующей схеме:
Схема устройства на макетной плате |
Обратите внимание:
- В нашей схеме мы используем модуль трёхцветного светодиода из набора. Это значит, что нам не нужно использовать резисторы на 220 Ом при его подключении. Если у вас нет такого модуля, а имеется лишь сам трёхцветный светодиод, то сигнал на каждую из лапок этого светодиода следует подавать через токоограничительный резистор на 220 Ом.
- Рекомендуется использовать светодиоды именно красного, зелёного и синего цветов, но если у вас таких нет – используйте любые.
ПРОГРАММИРОВАНИЕ
Сначала, давайте разберёмся в принципе работы ИК-передатчика и ИК-приёмника:
- Пульт дистанционного управления, при нажатии на какую-либо из его кнопок, передаёт код этой кнопки, в зашифрованном виде. Делает он это на определённой частоте.
- Если частота работы ИК приёмника совпадает с частотой передачи сигнала пультом ДУ, то приёмник может принять этот сигнал, отфильтровать его от внешних помех, которые издают сами электроприборы и усилить его с помощью встроенного усилителя.
- Далее, этот сигнал в виде цифровых импульсов передаётся на плату Arduino.
Для того, чтобы вручную не работать с такими сигналами, мы будем использовать специальную библиотеку <IRremote>. Давайте установим её:
- Запуститt Arduino IDE, выберите [Скетч] → [Подключить библиотеку] → [Управлять библиотеками];
- В строке поиска введите “IRremote”;
- Установите библиотеку “IRremote by shirriff”.
Теперь мы готовы к следующему шагу. Для того, чтобы управлять какими-либо устройствами с помощью пульта ДУ, необходимо “привязать” то или иное действие к нажатию той или иной кнопки на пульте. При нажатии кнопки на пульте ДУ, он будет передавать код нажатой кнопки. Нам нужно узнать эти коды и привязать к ним нужные нам события в коде нашей программы. Давайте разберёмся как узнать коды кнопок. Загрузите в Arduino следующий скетч:
#include <IRremote.h> // подключаем библиотеку для ИК-приемника IRrecv irrecv(A0); // указываем пин, к которому подключен ИК-приемник decode_results results; // объявляем переменную для хранения полученных кодов void setup() { irrecv.enableIRIn(); // инициализируем прием инфракрасного сигнала Serial.begin(9600); // инициализируем монитор последовательного порта } void loop() // процедура loop { if (irrecv.decode(&results)) // если данные пришли выполняем команды { Serial.println(results.value); // отправляем полученные данные в порт irrecv.resume(); // принимаем следующий сигнал на ИК приемнике } }
После загрузки скетча запустите монитор порта, возьмите пульт ДУ, направьте его передатчик в сторону ИК-приёмника и коротко нажмите на кнопки “1”, “2” и “3” на пульте. При этом, в мониторе порта вы должны увидеть примерно следующую картину:
Это и есть коды кнопок “1”, “2” и “3” на пульте.
Внимание! Сами коды для кнопок вашего пульта могут отличаться от приведённых здесь. Поэтому, для следующих экспериментов вы должны использовать значения именно своих кодов!
Теперь, попробуйте нажимать кнопки “1”, “2” и “3” на вашем пульте с небольшим удержанием. При этом вы должны увидеть примерно следующую картину:
При удержании нажатой кнопки, ИК-приёмник начинает посылать в Aruino другой код. При этом, данный код будет одинаковым для любой кнопки. Будем называть этот код – кодом зажатия. С помощью этого кода мы можем рассказать Arduino, что делать, если кнопка была нажата на небольшой промежуток времени, а что делать, если кнопка была зажата. Кроме этого, эта особенность позволит Arduino не считывать код одной и той же кнопки несколько раз подряд.
Давайте попробуем управлять какой-либо нагрузкой, подключённой к Arduino с помощью этих кодов. Например, привяжем включение 1-го светодиода к кнопке “1”, 2-го к кнопке “2”, а 3-го к кнопке “3”. Для того, чтобы выключить светодиоды, будем использовать любую другую кнопку, например кнопку “0”. Скетч данной программы будет выглядеть следующим образом:
#include <IRremote.h> // подключаем библиотеку для ИК-приемника IRrecv irrecv(A0); // указываем пин, к которому подключен ИК-приемник decode_results results; // объявляем переменную для хранения полученных кодов void setup() { pinMode(11, OUTPUT); // назначаем пины 11, 12, 13 на выход pinMode(12, OUTPUT); pinMode(13, OUTPUT); irrecv.enableIRIn(); // инициализируем прием инфракрасного сигнала Serial.begin(9600); // инициализируем монитор последовательного порта } void loop() // процедура loop { if (irrecv.decode(&results)) // если данные пришли выполняем команды { Serial.println(results.value); // отправляем полученные данные в порт irrecv.resume(); // принимаем следующий сигнал на ИК приемнике if (results.value == 16724175) // если нажата кнопка "1"... { digitalWrite(11, HIGH); // ... включаем светодиод на 11-м пине } if (results.value == 16718055) // если нажата кнопка "2"... { digitalWrite(12, HIGH); // ... включаем светодиод на 12-м пине } if (results.value == 16743045) // если нажата кнопка "3"... { digitalWrite(13, HIGH); // ... включаем светодиод на 14-м пине } if (results.value == 16738455) // если нажата кнопка "0"... { digitalWrite(11, LOW); // ... выключаем все светодиоды digitalWrite(12, LOW); digitalWrite(13, LOW); } } }
Загрузите данный скетч в Arduino и протестируйте его. Попробуйте определить – на каком расстоянии от приёмника, пульт ДУ сможет корректно работать. Управляя светодиодами плавно отходите от приёмника. При этом, наблюдайте что происходит в мониторе порта.
Когда расстояние станет достаточно велико, мы не сможем управлять светодиодами, при этом в мониторе порта мы увидим примерно следующую картину:
Коды “255” означают, что приёмник не смог корректно получить и расшифровать сигнал, т.е. это код ошибки. При желании, такую ошибку можно отображать с помощью дополнительного светодиода, просто привязав его включение к данному коду.
На современных устройствах, одной кнопкой, зачастую, можно как включать, так и выключать какую-либо функцию устройства. Благодаря тому, что ИК-приёмник посылает в Arduino код нажатой кнопки лишь 1 раз за нажатие, мы можем это использовать, чтобы сделать управление нашими светодиодами не только удобнее и проще, но при этом и достаточно сильно укоротить наш код. Итак, напишем скетч, который будет при нажатии на кнопки “1”, “2” и “3” включать светодиоды, а при повторном нажатии на эти кнопки – отключать их:
#include <IRremote.h> // подключаем библиотеку для ИК-приемника IRrecv irrecv(A0); // указываем пин, к которому подключен ИК-приемник decode_results results; // объявляем переменную для хранения полученных кодов void setup() { pinMode(11, OUTPUT); // назначаем пины 11, 12, 13 на выход pinMode(12, OUTPUT); pinMode(13, OUTPUT); irrecv.enableIRIn(); // инициализируем прием инфракрасного сигнала Serial.begin(9600); // инициализируем монитор последовательного порта } void loop() // процедура loop { if (irrecv.decode(&results)) // если данные пришли выполняем команды { Serial.println(results.value); // отправляем полученные данные в порт irrecv.resume(); // принимаем следующий сигнал на ИК приемнике if (results.value == 16724175) // если нажата кнопка "1"... { digitalWrite(11, !digitalRead(11)); // ... изменяем сигнал на 11 пине на противоположный } if (results.value == 16718055) // если нажата кнопка "2"... { digitalWrite(12, !digitalRead(12)); // ... изменяем сигнал на 12 пине на противоположный } if (results.value == 16743045) // если нажата кнопка "3"... { digitalWrite(13,!digitalRead(13)); // ... изменяем сигнал на 13 пине на противоположный } } }
Загрузите данный скетч в Arduino и протестируйте работу устройства.
Создание RGB-светильника
Теперь мы знаем, как управлять какой-либо нагрузкой с помощью кодов кнопок, пришедших с пульта ДУ. Давайте попробуем запрограммировать Arduino таким образом, чтобы сделать из него контроллер RGB-подсветки. Т.е. попробуем управлять RGB-светодиодом, а точнее цветом его свечения. Если вы забыли – как работает и устроен такой светодиод, то обязательно прочтите об этом в памятке:
Вкратце: внутри RGB-светодиода находятся 3 светодиода красного, зелёного и синего цветов. Управляя яркостью каждого из них, т.е. посылая на них аналоговый сигнал в диапазоне [0…255], мы можем добиться нужного нам цвета свечения RGB-светодиода.
Как это реализовать при управлении с пульта? Очень просто:
- Кнопками “1”, “2” и “3” мы будем переключать каналы управления RGB-светодиодом (красный, зелёный и синий);
- Кнопками “+” и “-” пульта мы будем увеличивать и уменьшать значение сигнала, который мы хотим отправить на тот или иной канал светодиода;
Итак, для начала давайте получим коды кнопок “1”, “2”, “3”, “+” и “-” нашего пульта. Для этого запустим монитор последовательного порта и коротко нажмём на каждую кнопку:
Теперь, напишем программы, которая будет управлять нашим RGB-светильником:
#include <IRremote.h> // подключаем библиотеку для ИК-приемника IRrecv irrecv(A0); // указываем пин, к которому подключен ИК-приемник decode_results results; // объявляем переменную для хранения полученных кодов String channel; // переменная для "переключения" каналов управления светодиодом int R=0; // переменные для хранения сигнала канала управления светодиодом int G=0; // и задаём им нулевые значения int B=0; void setup() { pinMode(11, OUTPUT); // назначаем пины 11, 12, 13 на выход pinMode(12, OUTPUT); pinMode(13, OUTPUT); pinMode(6, OUTPUT); // назначаем пины 6, 9, 10 на выход pinMode(9, OUTPUT); pinMode(10, OUTPUT); irrecv.enableIRIn(); // инициализируем прием инфракрасного сигнала Serial.begin(9600); // инициализируем монитор последовательного порта } void loop() // процедура loop { if (irrecv.decode(&results)) // если данные пришли выполняем команды { Serial.println(results.value); // отправляем полученные данные в порт irrecv.resume(); // принимаем следующий сигнал на ИК приемнике if (results.value == 16724175) // если нажата кнопка "1"... { digitalWrite(11, HIGH); // ... включаем индикатор "красного канала" и выключаем остальные digitalWrite(12, LOW); digitalWrite(13, LOW); channel="red"; // выбираем "красный" канал } if (results.value == 16718055) // если нажата кнопка "2"... { digitalWrite(11, LOW); // ... включаем индикатор "зелёного канала" и выключаем остальные digitalWrite(12, HIGH); digitalWrite(13, LOW); channel="green"; // выбираем "зелёный" канал } if (results.value == 16743045) // если нажата кнопка "3"... { digitalWrite(11, LOW); // ... включаем индикатор "синего канала" и выключаем остальные digitalWrite(12, LOW); digitalWrite(13, HIGH); channel="blue"; // выбираем "синий" канал } if (results.value == 16754775) // если нажата кнопка "+" { if (channel=="red") // если выбран "красный" канал { R=R+5; // увеличиваем красный сигнал на 5 единиц } if (channel=="green") // если выбран "зелёный" канал { G=G+5; // увеличиваем зелёный сигнал на 5 единиц } if (channel=="blue") // если выбран "синий" канал { B=B+5; // увеличиваем синий сигнал на 5 единиц } } if (results.value == 16769055) // если нажата кнопка "-" { if (channel=="red") // если выбран "красный" канал { R=R-5; // уменьшаем красный сигнал на 5 единиц } if (channel=="green") // если выбран "зелёный" канал { G=G-5; // уменьшаем зелёный сигнал на 5 единиц } if (channel=="blue") // если выбран "синий" канал { B=B-5; // уменьшаем синий сигнал на 5 единиц } } } analogWrite(6, R); // подаём сигналы всех каналов на наш RGB-светодиод analogWrite(9, G); analogWrite(10, B); }
Подробные комментарии по работе скетча приведены внутри кода. Загрузите скетч в Arduino и проверьте его работоспособность.
Теперь мы можем управлять цветом RGB-светодиода с пульта ДУ.
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОГО ВЫПОЛНЕНИЯ
Задание 1:
Добавьте в схему ещё один красный светодиод, который будет служить “индикатором” ошибки при приёме данных с пульта ДУ. Он должен зажигаться всякий раз, когда с ИК-приёмника придёт код значением “255”, и гаснуть, когда с ИК-приёмника придёт корректный код любой из нажатых кнопок.
Задание 2:
Дополните программу RGB-светильника так, чтобы при нажатии на кнопку “CH+” (или любую другую). Светильник зажигался во всю мощь и светил белым цветом (для этого на каждый из светодиодов светильника нужно подать сигнал [255]). Так же, добавьте кнопку “выключения” светильника, например “CH-” (для выключения всех светодиодов, необходимо подать сигнал [0] на каждый из них).
Задание 3*:
Измените код программы таким образом, чтобы яркость нужного канала плавно увеличивалась при нажатии и удерживании кнопки “+”, и уменьшалась при нажатии и удерживании кнопки “-“.
1 Комментарий
Good