ИК-приёмник (VS1838B): подключение к ESP32 и Arduino

Приёмник инфракрасного пульта

Принимает команды обычного пульта от телевизора. Каждая кнопка — свой код, и им можно управлять чем угодно.

Как работает

Пульт мигает инфракрасным светодиодом с частотой 38 кГц, а приёмник выделяет эту несущую и выдаёт на OUT уже огибающую — последовательность импульсов (выход инверсный: есть сигнал — LOW). Длительности пауз кодируют биты команды; самый распространённый протокол — NEC.

Библиотека IRremote: IrReceiver.begin(вывод), а в loop — if (IrReceiver.decode()) { код = IrReceiver.decodedIRData.command; IrReceiver.resume(); }.

Выводы

ВыводНазначение
OUTвыход сигнала
VCCпитание
GNDобщий провод

Подключение к ESP32

ИК-приёмник (VS1838B)ESP32
OUTGPIO15
VCC3V3
GNDGND

Схема из примера «ИК-пульт: приём кода».

ИК-пульт: приём кода

Открыть пример целиком
Код скетча
// Приём ИК-пульта на блоке RMT.
//
// Обычным digitalRead этот сигнал не поймать: кадр NEC укладывает
// тридцать два разряда в шестьдесят миллисекунд импульсами по 560 мкс.
// RMT ловит их сам и складывает в память парами «уровень и длительность».

#include <driver/rmt.h>

const rmt_channel_t CH = RMT_CHANNEL_0;
const gpio_num_t IR_PIN = GPIO_NUM_15;

// Допуск на длительность: у настоящих пультов разброс заметный, и
// сравнивать с точностью до микросекунды бессмысленно.
bool near(int value, int want) {
  return value > want - 250 && value < want + 250;
}

void setup() {
  Serial.begin(115200);

  rmt_config_t cfg = RMT_DEFAULT_CONFIG_RX(IR_PIN, CH);
  cfg.clk_div = 80;              // такт в микросекунду
  cfg.mem_block_num = 2;         // кадру NEC нужно 68 записей, в блоке 64
  cfg.rx_config.idle_threshold = 12000;   // тишина 12 мс — конец кадра
  cfg.rx_config.filter_en = true;
  cfg.rx_config.filter_ticks_thresh = 100;
  rmt_config(&cfg);
  rmt_driver_install(CH, 1024, 0);
  rmt_rx_start(CH, true);

  Serial.println("жду пульт");
}

void loop() {
  RingbufHandle_t rb = NULL;
  rmt_get_ringbuf_handle(CH, &rb);
  if (!rb) return;

  size_t size = 0;
  rmt_item32_t *items = (rmt_item32_t *)xRingbufferReceive(rb, &size, pdMS_TO_TICKS(200));
  if (!items) return;

  int count = size / sizeof(rmt_item32_t);
  // Заголовок: 9 мс несущей и 4.5 мс паузы. По нему кадр и опознаётся.
  if (count >= 34 && near(items[0].duration0, 9000) && near(items[0].duration1, 4500)) {
    uint32_t code = 0;
    for (int i = 1; i <= 32; i++) {
      // Разряд задаёт не импульс, а пауза после него: 560 мкс — ноль,
      // 1690 — единица.
      code = (code << 1) | (items[i].duration1 > 1000 ? 1 : 0);
    }
    Serial.printf("код 0x%08X\n", code);
  } else {
    Serial.printf("кадр не похож на NEC: %d записей\n", count);
  }

  vRingbufferReturnItem(rb, (void *)items);
}

В железе

Порядок выводов у разных приёмников разный (у VS1838B и TSOP1838 — не совпадает). Сверяйтесь с маркировкой модуля или паспортом.

Частые ошибки

Другие детали