Родной пульт — расходник: сенсорные плёнки протираются, корпуса трескаются, кнопки залипают. Для гаража мне нужен был пульт, который переживёт пыль, замасленные руки и падение с полки: крупные тактовые кнопки на макетке, батарейка на месяцы, никакого сенсора. Так родился этот урок — пульт как прибор, а не как стенд: диод с правильным током, кадр с правильным адресом, повторы при удержании и одна ловушка, о которой туториалы молчат, потому что никто не вешает приёмник на плату передатчика.
Раздел уже выкладывал кирпичи по одному: выбор диода, резистора и ток — в уроке про передатчик 940 нм, сам вызов sendNEC с адресом и командой — в уроке про IrSender.sendNEC, пульт из трёх кнопок — в уроке про свой пульт из Arduino. Здесь я собираю кирпичи в один прибор и разбираю то, чего там не было: где честно хватает тока пина, как строятся повторы при удержании и почему приёмник на той же плате слышит собственные кадры. Адреса в примерах — мои, снятые сниффером; у вашей техники они свои.
Три решения, которые определят всё остальное, принимаются до кода: сколько миллиампер отдать диоду, какой адрес занять и как передатчик будет жить с приёмниками, которые его слышат. Каждое разбираю отдельно — они не зависят друг от друга, и порядок можно менять. Единственное, что стоит выбрать заранее, — корпус: тактовые кнопки на голой макетке живут до первого падения, и если пульт для гаража, посадите их на общую планку, а батарейный отсек — на липучку. Половина надёжности прибора делается до первой строки кода, и это не про эстетику, а про контакты.
Диод, резистор, кадр: пульт как прибор
Диод на 940 нанометров вешается на пин через 100–150 Ом: от пяти вольт это (5 − 1,2)/150 ≈ 25 мА через 150 Ом и около 38 мА через 100 Ом, при потолке пина в 40 мА. Звучит страшно, пока не вспомнишь режим: кадр NEC живёт около 68 миллисекунд, внутри него несущая 38 кГц гонит диод лишь треть времени, а между нажатиями он отдыхает секундами — средний ток не дотягивает до десятка миллиампер, и кристалл холодный. Постоянно держать такие токи нельзя: у передатчика непрерывного света диод на 100 Ом грелся у меня до неприятных температур, и тот же расчёт среднего тока в импульсе спасает и здесь — пульт жмут секунды, а не минуты подряд.
Кадр, который уходит из sendNEC, несёт 32 бита: адрес, инверсию адреса, команду, инверсию команды — раскладку по байтам я не пересказываю, она разобрана в уроке про 32 бита NEC. Вызов sendNEC(адрес, команда, повторы) в четвёртой версии берёт эти поля отдельно, а третьим аргументом — число коротких кадров-повторов, которые библиотека вставит после полного кадра с шагом 110 миллисекунд, как у родного пульта при удержании. Громкости просят два-три повтора, команды-переключатели вроде mute — ноль, иначе второй кадр перевернёт состояние обратно.
IrSender.begin() на Uno и Nano садится с несущей на пин 3 — это выход второго таймера, и если на той же плате живёт приёмник, роли дерутся за один ресурс: правило раздельных плат со ссылкой на разбор таймера 2 ещё пригодится ниже, в ловушке эха. Свои адреса держу константами с комментарием, кому они принадлежат: через полгода в доме три самодельных пульта, и книга адресов в шапке скетча окупается каждый раз, когда приборов становится больше двух.
// Пульт: одна кнопка VOL+. Фронт - кадр, удержание - повтор каждые 110 мс#include <IRremote.hpp> const int BUTTON_PIN = 2;const uint16_t ADDR = 0x0102; // свой адрес: в книге адресов шапкиconst uint8_t CMD = 0x15; // VOL+ bool lastLevel = HIGH; // подтяжка: покой - HIGHunsigned long lastShot = 0; void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); IrSender.begin(); // на Uno несущая сама встанет на пин 3 Serial.begin(9600); Serial.println("pult gotov: VOL+");} void loop() { bool level = digitalRead(BUTTON_PIN); if (level == LOW) { if (lastLevel == HIGH) { // фронт: один кадр на нажатие IrSender.sendNEC(ADDR, CMD, 0); // ноль повторов: шаг громкости lastShot = millis(); Serial.println("VOL+"); } else if (millis() - lastShot >= 110) { // удержание: новый кадр // у родного пульта тут короткий кадр-повтор без заголовка; // поток полных кадров каждые 110 мс приёмники понимают так же, // эфир чуть грязнее - для своего прибора это не проблема IrSender.sendNEC(ADDR, CMD, 0); lastShot = millis(); } } lastLevel = level;}Лесенка дальности складывается из тока и конуса свечения, и считать её честнее от своих стен. Диод напрямую с пина на 25 мА доезжает на метр-полтора прямым лучом — для ночника в шаге от кровати этого хватает с запасом. Для комнаты нужен транзистор: база через 330 Ом, коллектор на катод, ток диода 60–100 мА — и четыре-пять метров стоят стабильно, пятый плавает от того, ровно ли смотрит диод. Родные пульты с их выверенной оптикой и узким конусом бьют на пять-восемь метров по прямой, а отражение от белой стены съедает примерно половину — через два угла кадр доходит уже в лотерейном режиме.
И всё же не стоит гнаться за восемью метрами, если пульт предназначен для одной комнаты. Каждая ступень тока стоит деталей: транзистор, пара резисторов, аккуратная земля. Мой гаражный пульт с транзистором честно бьёт через весь бокс, но пользуюсь им только у ворот — остальное время работают первые полтора метра, на которых хватит и диода с пина. Путь упрощения здесь честнее пути усиления: сначала посчитайте, где пульт реально будет лежать, и только потом решайте, нужен ли ему транзистор вообще.
Метрику я держу не на глаз, а на счёте кадров: скетч шлёт пачку из десяти команд с паузой в треть секунды, отходишь и считаешь дошедшие. До трёх метров мои стенды приносили все десять, на четырёх — семь, на пяти — парочка; одиночный успех на пределе — лотерея, а не метрика, потому что рука в момент отправки всегда подыгрывает. Подробная геометрия приёмника по углам и высотам — в уроке про дальность и геометрию, здесь беру из него одно: чистая линия видимости стоит дороже любого тока.
| Вариант передачи | Пик тока | Дальность | Когда хватает |
|---|---|---|---|
| диод напрямую с пина, 150 Ом | ≈25 мА | 1–1,5 м прямым лучом | стенд и ночник в шаге от кровати |
| диод напрямую с пина, 100 Ом | ≈38 мА | до 2 м, пин на пределе 40 мА | временно; надолго — только через транзистор |
| транзистор, резистор 47–68 Ом | 60–100 мА | 4–5 м стабильно | комната: колонка, люстра, гаражные ворота |
| родной пульт, узкий конус | 50–100 мА | 5–8 м по прямой | эталон: у него выверена вся оптика |
Эхо: приёмник слышит свой же пульт
Ловушка подстерегает там, где хочется сэкономить плату. Допустим, передатчик на Uno, а рядом на той же макетке — приёмник для проверки кадров: вы жмёте кнопку, и в мониторе честно печатается адрес и команда. Проблема в том, что печатает он их на свои же кадры: приёмник декодирует всё, что прилетело в конус, и не знает, что отправитель сидит в десяти сантиметрах. Дальше хуже: если на этой плате живёт логика управления — реле, свет, счётчик — она честно выполняет собственные команды. Прибор щёлкает сам с собой, а вы ищете помехи там, где виновато эхо; у меня такой макет-трансивер неделю переключал собственное реле каждой своей командой, пока я не разнёс роли по платам.
У эха три честных решения, и все три проверены на своих стендах. Первое — раздельные платы: передатчику своё, приёмнику своё, и конфликт второго таймера заодно исчезает. Второе — фильтр по адресу: свои кадры приёмник узнаёт по константе ADDR и пропускает мимо логики, как в приёме с белым списком; это правильный выбор, когда пульт и приёмник обязаны жить на одной плате — пульт-мигалка с подтверждением, трансивер. Третье — пауза приёма на время отправки: грубовато, но для редких команд хватает.
И заметьте, как это связано с таймером: даже без эха две роли на одном чипе дерутся за второй таймер ATmega328, и поведение такой платы плавает от версии библиотеки к версии. Мой вывод после трёх переделок — железный: передатчик получает свою плату, приёмник свою, а одна плата на две роли живёт только с фильтром по адресу и только там, где логика простая.
Отдельный случай — стенд проверки, который живёт с пультом добровольно. Пока вы отлаживаете пульт, приёмник рядом нужен каждый вечер, и у меня он так и стоит: на столе вторая плата-сниффер печатает каждый кадр первого. Разница с ловушкой в том, кто слушает: внешний сниффер не исполняет команды, ему нечего выполнять, и его честные показания не мешают никому. Приёмник на плате с логикой — другая история: он не сообщает, а действует, и именно действие делает эхо дорогим.
- 1. Сколько бит в кадре NEC и что там лежит?
- 2. Что делает третий аргумент sendNEC?
- 3. Стенд с диодом через 150 Ом доезжает на метр-полтора. Что поднять дальность до 4–5 м?
- 4. Почему приёмник на плате пульта реагирует на собственные команды?
- 5. Какая проверка дальности выглядит честной?
- Диод 940 нм и 100–150 Ом от пина: 25–38 мА в импульсе, диод горит треть времени кадра — средний ток копейки, кристалл холодный.
- sendNEC(адрес, команда, повторы): третий аргумент шлёт короткие кадры с шагом 110 мс; переключателям — ноль, громкости — два-три.
- 25 мА с пина — метр-полтора; 60–100 мА через транзистор — 4–5 м; честная метрика — счёт дошедших из пачки десяти кадров.
- Приёмник на плате передатчика слышит собственные кадры: раздельные платы, фильтр по адресу или пауза приёма на время sendNEC.
- Свой адрес — 16 бит в константе с комментарием, кому принадлежит: книга адресов в шапке окупается уже на третьем пульте.
Частые вопросы по теме урока
- Сколько бит в кадре NEC и что там лежит?
- Кадр NEC несёт 32 бита: адрес, команда и две их инверсии — встроенная проверка целостности ценой двух байт. sendNEC в 4.x принимает адрес и команду отдельными аргументами, инверсии библиотека достраивает сама. 32: адрес, инверсия адреса, команда, инверсия команды
- Что делает третий аргумент sendNEC?
- После полного кадра библиотека шлёт указанное число коротких кадров-повторов с шагом 110 миллисекунд — как родной пульт при удержании. Для команд-переключателей третьим аргументом едет ноль. задаёт число коротких кадров-повторов с шагом 110 мс
- Стенд с диодом через 150 Ом доезжает на метр-полтора. Что поднять дальность до 4–5 м?
- Пин ограничен 40 мА, и путь дальше — транзистор: база через 330 Ом, коллектор на катод, резистор диода 47–68 Ом. Резистор на 10 Ом положит на пин полампера — это уже не пульт, а приговор пину. транзистор и ток диода 60–100 мА
- Почему приёмник на плате пульта реагирует на собственные команды?
- Эхо: приёмник не знает, кто отправитель, и честно декодирует свои же кадры. Решения — раздельные платы, фильтр по собственному адресу или пауза приёма на время отправки. приёмник декодирует всё в конусе, включая кадры собственного передатчика, — эфир один на всех
- Какая проверка дальности выглядит честной?
- Одиночный успех на пределе — лотерея: рука в момент отправки подыгрывает. Пачка из десяти кадров даёт статистику: семь из десяти на четырёх метрах — рабочая дальность, парочка — уже нет. счёт дошедших кадров из пачки из десяти