База знаний · Датчики и модули
ИК-пульт и приёмник: управление Arduino с дивана
Любой пульт от телевизора плюс приёмник за 200 рублей: как узнать коды кнопок, включить что-нибудь с пульта и почему tone() глушит приём.
Любой пульт от телевизора, кондиционера или приставки — готовое беспроводное управление для Arduino. Нужен только приёмник за двести рублей и одна библиотека. Пульт шлёт вспышки невидимого инфракрасного света, приёмник превращает их в цифры, а скетч решает, что делать: включить свет, повернуть робота, переключить трек.
Приёмник: три ножки и 38 кГц
Пульт мигает светодиодом не просто так, а с несущей частотой — чаще всего 38 кГц. Приёмник вроде VS1838B или TSOP4838 настроен на неё: он отсекает солнце и лампы, а на вспышки пульта отвечает нулями и единицами на выводе OUT. Отдельный «голый» приёмник стоит несколько десятков рублей, в Trema-модуле тот же VS1838B уже распаян с конденсатором и шлейфом — 194 ₽. Пульт в комплект не входит: подойдёт любой домашний или 21-кнопочный из наборов.
Библиотека IRremote и её новый вид
Стандарт — библиотека IRremote, в каталоге сейчас версия 4.7.1. В 2021 году она сменила кожу: вместо IRrecv irrecv(2) и decode_results из старых уроков теперь один готовый объект IrReceiver, подключается она строкой #include <IRremote.hpp>, а результат лежит в IrReceiver.decodedIRData уже разобранным на протокол, адрес и команду. Старые скетчи библиотека 4.x ещё собирает, но коды в них выглядят иначе: одно 32-битное число вместо адреса и команды, а удержание кнопки даёт FFFFFFFF. Если переписываете урок десятилетней давности, проще перейти на новый вид — он короче.
Шаг 1. Узнать коды своих кнопок
Первый скетч ничего не делает, только печатает, что пришло. На Uno он занимает 8 970 байт.
#include <IRremote.hpp> // IRremote 4.x подключается именно так, с .hpp
const byte IR_PIN = 2; // выход приёмника OUT
void setup() {
Serial.begin(9600);
IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK); // светодиод платы мигнёт на каждый сигнал
Serial.println("Нажимайте кнопки пульта");
}
void loop() {
if (IrReceiver.decode()) {
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
Serial.println("(кнопка удерживается)");
} else {
Serial.print("Протокол: ");
Serial.print(getProtocolString(IrReceiver.decodedIRData.protocol));
Serial.print(" адрес: 0x");
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(" команда: 0x");
Serial.println(IrReceiver.decodedIRData.command, HEX);
}
IrReceiver.resume(); // готовы принимать следующую посылку
}
}
Откройте монитор порта на 9600 и понажимайте кнопки. Для пульта из набора вы увидите что-то вроде Протокол: NEC адрес: 0x0 команда: 0xC — это кнопка «1». Команда и есть номер кнопки, её и запоминаем. Адрес — номер «устройства», у всех кнопок одного пульта он одинаковый; он пригодится, если в комнате два пульта с одинаковыми командами.
Пока держите кнопку, пульт NEC не повторяет код, а шлёт короткий сигнал «всё ещё нажато» — библиотека отмечает его флагом IRDATA_FLAGS_IS_REPEAT, и скетч пишет «кнопка удерживается». Это важно для шага 2: если не отсеивать повторы, одно долгое нажатие переключит свет десять раз.
Шаг 2. Включить что-нибудь с пульта
Впишите коды двух кнопок и получите выключатель. Коды в скетче — от чёрного 21-кнопочного пульта «Car MP3», который кладут в большинство наборов: кнопка «1» — 0x0C, «2» — 0x18. Скетч занимает 7 262 байта.
#include <IRremote.hpp>
const byte IR_PIN = 2;
const byte LED = LED_BUILTIN;
// Коды кнопок узнайте первым скетчем и впишите свои.
const uint16_t CMD_ON = 0x0C; // у 21-кнопочного пульта из наборов это кнопка «1»
const uint16_t CMD_OFF = 0x18; // кнопка «2»
void setup() {
pinMode(LED, OUTPUT);
IrReceiver.begin(IR_PIN); // без подмигивания: светодиод платы занят нами
}
void loop() {
if (IrReceiver.decode()) {
// Удержание кнопки шлёт повторы — на них не реагируем.
if (!(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
uint16_t cmd = IrReceiver.decodedIRData.command;
if (cmd == CMD_ON) {
digitalWrite(LED, HIGH);
} else if (cmd == CMD_OFF) {
digitalWrite(LED, LOW);
}
}
IrReceiver.resume();
}
}
Остальные кнопки этого пульта, чтобы не снимать каждый раз (протокол NEC, адрес 0x0):
| Кнопка | Команда | Кнопка | Команда | Кнопка | Команда |
|---|---|---|---|---|---|
| CH− | 0x45 | CH | 0x46 | CH+ | 0x47 |
| |◀◀ | 0x44 | ▶▶| | 0x40 | ▶|| | 0x43 |
| − | 0x07 | + | 0x15 | EQ | 0x09 |
| 0 | 0x16 | 100+ | 0x19 | 200+ | 0x0D |
| 1 | 0x0C | 2 | 0x18 | 3 | 0x5E |
| 4 | 0x08 | 5 | 0x1C | 6 | 0x5A |
| 7 | 0x42 | 8 | 0x52 | 9 | 0x4A |
Осторожно: у второго ходового пульта — белого, с кнопками POWER, VOL+ и FUNC/STOP — те же числа сидят на других кнопках: 0x40 там «воспроизведение», 0x43 — «вперёд», 0x15 — «тише». Поэтому первый скетч всё равно нужен: пять минут с монитором порта избавят от загадок.
Вместо светодиода на этом же месте может стоять реле, сервопривод или мотор — меняется только то, что делается в ветках if. Дальше по той же схеме собирается MP3-плеер с пультом — он разобран в статье про DFPlayer Mini.
NEC, Sony, RC5: какой пульт у вас
Разных способов кодировать кнопки десятки, IRremote знает основные: NEC (почти все китайские пульты и большинство телевизоров), Sony, Samsung, LG, Panasonic, JVC, RC5 и RC6 (Philips). Вам это знать не обязательно: первый скетч печатает протокол сам, а сравнивать вы всё равно будете команду. Если протокол показан как UNKNOWN — библиотека такого не знает: так бывает с кондиционерами, у которых посылки длинные и не помещаются в буфер, и с рваным сигналом издалека. Управлять всё равно можно: вместо команды сравнивайте decodedIRData.decodedRawData — для неизвестного протокола там лежит хэш посылки, у каждой кнопки свой.
Что ломается
- tone() глушит приёмник. На Uno и Nano IRremote живёт на том же таймере 2, что и
tone(): после первого же писка приём останавливается. Делайте, как в примере библиотеки:IrReceiver.stopTimer(), затемtone(), подождите, пока звук отзвучит, и только потомIrReceiver.restartTimer(). По той же причине не пользуйтесьanalogWrite()на выводах 3 и 11, пока принимаете сигнал. - Одно нажатие — десять срабатываний. Кнопку подержали чуть дольше, и пришла серия повторов с тем же кодом. Проверяйте флаг повтора, как во втором скетче.
- Солнце и лампы. Приёмник у окна или под лампой дневного света ловит помехи и выдаёт случайные протоколы. Уберите его в тень или прикройте трубочкой из чёрной изоленты.
- Ножки наоборот. VCC и GND перепутаны — приёмник греется и молчит. Линзой к себе: OUT, GND, VCC.
- Два пульта — одна команда. Кнопка «1» на пульте телевизора и на пульте из набора может давать одинаковую команду. Сравнивайте ещё и адрес:
decodedIRData.address.
А отправить сигнал?
IRremote умеет и передавать: ИК-светодиод через резистор 100–220 Ом на любой вывод, и IrSender.sendNEC(адрес, команда, повторы) заменит кнопку на телевизоре. Так делают «умные пульты» для кондиционера. Коды для них берут тем же первым скетчем с родного пульта. Отдельно для этого есть и модуль приёмник-передатчик по I²C, который разгружает плату от таймеров.
Частые вопросы
Как узнать коды кнопок своего пульта?
Загрузите скетч из статьи с IrReceiver.printIRResultShort или с выводом адреса и команды, откройте монитор порта на 9600 и нажимайте кнопки: для каждой напечатаются протокол, адрес и команда. Команда — это и есть код кнопки, его вписывают в скетч.
Почему IRremote не собирается: decode_results не объявлен?
Вы взяли скетч под старую IRremote 2.x, а в каталоге стоит 4.x. Подключайте библиотеку строкой #include <IRremote.hpp>, вместо IRrecv и decode_results используйте готовый объект IrReceiver, а результат берите из IrReceiver.decodedIRData.command. Старые примеры библиотека 4.x ещё собирает с заголовком IRremote.h, но коды в них выглядят иначе.
Почему приёмник выдаёт FFFFFFFF или ноль при удержании кнопки?
Пульты NEC при удержании не повторяют код, а шлют короткий сигнал «всё ещё нажато». В IRremote 4.x он помечается флагом IRDATA_FLAGS_IS_REPEAT, в старой 2.x показывался как 0xFFFFFFFF. В скетче такие посылки просто пропускают, иначе одно долгое нажатие сработает много раз.
Как подключить ИК-приёмник VS1838B?
Три ножки, линзой к себе, слева направо: OUT, GND, VCC. OUT — на любой цифровой вывод (в статье — 2), GND — на землю, VCC — на 5V или 3.3V: приёмник работает от 2,7 до 5,5 В. Перепутанные VCC и GND — самая частая причина, почему приёмник греется и молчит.
Почему после tone() пульт перестаёт работать?
На Uno и Nano IRremote и tone() делят один аппаратный таймер — второй. После звука приём останавливается. Вызовите IrReceiver.restartTimer() после tone() или переложите звук на другую библиотеку. По той же причине не используйте analogWrite() на выводах 3 и 11, пока принимаете сигнал.
Можно ли с Arduino управлять телевизором или кондиционером?
Да: ИК-светодиод через резистор 100–220 Ом на любой вывод и IrSender.sendNEC(адрес, команда, повторы) из той же IRremote. Коды снимают с родного пульта первым скетчем статьи. Дальность у одного светодиода небольшая, два-три метра.
Читайте также
Обновлено: 22 октября 2026
