В этом уроке мы создадим универсальный ИК-пульт дистанционного управления. Шесть кнопок универсального ИК-пульта позволяют запрограммировать себя на передачу команды любого* другого ИК-пульта. Код кнопок сохраняется в энергонезависимую область памяти Arduino - EEPROM. Это значит, что Вам не придётся программировать кнопки при каждом включении универсального ИК-пульта.
*Универсальный ИК-пульт может воспроизводить сигналы только тех ИК-пультов, которые передают данные одним информационным пакетом не длиннее 32 бит, а также имеют (или нет) одинаковые пакеты удержания (пакеты повторов).
Нам понадобится:
- Arduino Uno х 1шт.
- Trema модуль - ИК-приёмник x 1шт.
- Trema модуль - ИК-передатчик x 1шт.
- Trema модуль - кнопка (синяя) x 7шт.
- Trema модуль - зуммер x 1шт.
- Trema Shield x 1шт.
- Конструктор для создания каркаса.
Для реализации проекта нам необходимо установить библиотеку:
- iarduino_IR для работы с ИК-приёмопередатчиками.
- EEPROM - входит в стандартный набор Arduino IDE.
О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.
Видео:
Схема подключения:
Все используемые в уроке модули, можно подключать к любым выводам Arduino, как цифровым, так и аналоговым. Номера выводов к которым подключены модули, указываются в скетче.
- Trema-кнопки подключены к цифровым выводам 2-8.
- Trema ИК-приёмник подключён к цифровому выводу 9.
- Trema ИК-передатчик подключён к цифровому выводу 10.
- Trema-зуммер подключён к цифровому выводу 11.
- Все модули подключены к Arduino Uno через Trema Shield.
Алгоритм работы:
Отправка команд:
- При нажатии на одну из 6 кнопок универсального ИК-пульта, он отправит команду, соответствующую нажатой кнопке.
- Если нажатой кнопке команда не присвоена, то ИК-пульт издаст звуковой сигнал, сигнализирующий об ошибке.
Назначение команд кнопкам:
- Для назначения команд кнопкам универсального ИК-пульта, нужно выполнить следующие действия:
- Нажать на кнопку "запись команды" и, не отпуская её, нажать на ту кнопку универсального ИК-пульта, которой мы хотим присвоить команду с другого ИК-пульта.
- Универсальный ИК-пульт издаст два коротких звуковых сигнала, сигнализируя о готовности принять данные.
- Нажать на кнопку другого ИК-пульта, код которой мы хотим считать.
- Как только код будет считан, универсальный ИК-пульт издаст короткий звуковой сигнал, сигнализирующий об успешной записи кода. Теперь можно отпустить все кнопки.
- Можно присвоить одной кнопке - код одного пульта, а другой кнопке - код другого пульта. Так как для каждой кнопки, сохраняется не только код, но и протокол передачи данных.
Код программы:
#include <iarduino_IR_RX.h> // Подключаем библиотеку для работы с ИК-приёмником #include <iarduino_IR_TX.h> // Подключаем библиотеку для работы с ИК-передатчиком #include <EEPROM.h> // Подключаем библиотеку для работы с EEPROM (энергонезависимой областью памяти) // Указываем выводы к которым подключены модули: const uint8_t PinButton1= 2; // Объявляем константу с указанием вывода к которому подключена кнопка 1 const uint8_t PinButton2= 3; // Объявляем константу с указанием вывода к которому подключена кнопка 2 const uint8_t PinButton3= 4; // Объявляем константу с указанием вывода к которому подключена кнопка 3 const uint8_t PinButton4= 5; // Объявляем константу с указанием вывода к которому подключена кнопка 4 const uint8_t PinButton5= 6; // Объявляем константу с указанием вывода к которому подключена кнопка 5 const uint8_t PinButton6= 7; // Объявляем константу с указанием вывода к которому подключена кнопка 6 const uint8_t PinButton7= 8; // Объявляем константу с указанием вывода к которому подключена кнопка 7 (запись) iarduino_IR_RX IR_Read ( 9); // Объявляем объект IR_Read с указанием вывода к которому подключён ИК-приёмник iarduino_IR_TX IR_Write (10); // Объявляем объект IR_Write с указанием вывода к которому подключён ИК-передатчик const uint8_t PinBuzzer= 11; // Объявляем константу с указанием вывода к которому подключен зуммер // Объявляем для хранения временных данных: uint8_t ValButton= 0; // Объявляем переменную для хранения номера нажатой кнопки uint32_t ValCode; // Объявляем переменную для хранения кода кнопки char ValProtocol[26]; // Объявляем строку для хранения 25 символов протокола передачи данных + символ конца строки void setup(){ // Инициируем работу с ИК-приёмником и ИК-передатчиком: IR_Read.begin(); // Инициируем работу с ИК-приёмником IR_Write.begin(); // Инициируем работу с ИК-передатчиком // Конфигурируем выводы: pinMode(PinButton1, INPUT); // Конфигурируем вывод с подключенной кнопкой №1 в режим входа pinMode(PinButton2, INPUT); // Конфигурируем вывод с подключенной кнопкой №2 в режим входа pinMode(PinButton3, INPUT); // Конфигурируем вывод с подключенной кнопкой №3 в режим входа pinMode(PinButton4, INPUT); // Конфигурируем вывод с подключенной кнопкой №4 в режим входа pinMode(PinButton5, INPUT); // Конфигурируем вывод с подключенной кнопкой №5 в режим входа pinMode(PinButton6, INPUT); // Конфигурируем вывод с подключенной кнопкой №6 в режим входа pinMode(PinButton7, INPUT); // Конфигурируем вывод с подключенной кнопкой №7 в режим входа pinMode(PinBuzzer, OUTPUT); // Конфигурируем вывод с подключенным зуммером в режим выхода } void loop(){ // Проверяем состояние кнопок: if(digitalRead(PinButton1)){ ValButton=1;}else // Если нажата кнопка 1, записываем число 1 в переменную ValButton if(digitalRead(PinButton2)){ ValButton=2;}else // Если нажата кнопка 2, записываем число 2 в переменную ValButton if(digitalRead(PinButton3)){ ValButton=3;}else // Если нажата кнопка 3, записываем число 3 в переменную ValButton if(digitalRead(PinButton4)){ ValButton=4;}else // Если нажата кнопка 4, записываем число 4 в переменную ValButton if(digitalRead(PinButton5)){ ValButton=5;}else // Если нажата кнопка 5, записываем число 5 в переменную ValButton if(digitalRead(PinButton6)){ ValButton=6;}else // Если нажата кнопка 6, записываем число 6 в переменную ValButton {delay(100); ValButton=0;} // Если кнопки 1-6 не нажаты, записываем число 0 в переменную ValButton и подавляем дребезг // Выполняем действия при нажатии на кнопку: if(ValButton){ // Если нажата кнопка 1-6 // Чтение данных: if(digitalRead(PinButton7)){ // Если нажата кнопка 7 (запись), то ... myTone(100); delay(100); myTone(100); // Выводим два коротких звуковых сигнала, сигнализирующих о готовности считать данные while(digitalRead(PinButton7)){ // Входим в цикл while, пока не будет отпущена кнопка 7 (запись) if(IR_Read.check()){ // Если в буфере имеются данные, принятые с другого пульта // Получаем данные, принятые с пульта strcpy(ValProtocol, IR_Read.protocol()); // Получаем протокол передачи данных пульта в строку ValProtocol ValCode = IR_Read.data; // Получаем код кнопки в переменную ValCode // Записываем принятые данные в EEPROM for(uint8_t i=0; i<30; i++){ // Проходим по 30 байтам в EEPROM if(i<26){EEPROM.write(i+(ValButton-1)*30,ValProtocol[i]);} // Первые 26 байт заполняем данными из строки ValProtocol (это протокол передачи данных) else {EEPROM.write(i+(ValButton-1)*30,uint8_t(ValCode>>((29-i)*8)));} // Последние 4 байта заполняем данными из переменной ValCode (это код кнопки) } myTone(100); // Выводим короткий звуковой сигнал, сигнализирующий об успешной записи } } // Отправка данных: }else{ // Если не нажата кнопка 7, то ... // Читаем протокол передачи данных и код кнопки из EEPROM: for(uint8_t i=0; i<30; i++){ // Проходим по 30 байтам в EEPROM if(i<26){ValProtocol[i] = EEPROM.read(i+(ValButton-1)*30);} // Первые 26 байт записываем в строку ValProtocol (это протокол передачи данных) else {ValCode<<=8; ValCode+=EEPROM.read(i+(ValButton-1)*30);} // Последние 4 байта записываем в переменную ValCode (это код кнопки) } // Отправляем код кнопки с использованием указанного протокола передачи данных: if (IR_Write.protocol(ValProtocol)){ // Устанавливаем прочитанный протокол передачи данных ValProtocol IR_Write.send(ValCode, true); // Передаём прочитанный код кнопки ValCode }else{myTone(500);} // Если строка ValProtocol не является протоколом передачи данных, то выводим звуковой сигнал, сигнализирующий об ошибке } } } // Функция генерирующая звуковой сигнал на выводе PinBuzzer void myTone(uint32_t i){ i+=millis(); while(i>millis()){digitalWrite(PinBuzzer, HIGH); delayMicroseconds(500); digitalWrite(PinBuzzer, LOW); delayMicroseconds(500);} }
Для генерации звука написана функция myTone(), вместо стандартной функции tone(), так как стандартная функция использует 2 аппаратный таймер, который уже используется библиотекой iarduino_IR.
Обсуждение