В этом уроке мы создадим универсальный ИК-пульт дистанционного управления. Шесть кнопок универсального ИК-пульта позволяют запрограммировать себя на передачу команды любого* другого ИК-пульта. Код кнопок сохраняется в энергонезависимую область памяти 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.


Обсуждение