ARDUINO IRremote, NEC и эмуляция ИК-сигналов

xa0c

✩✩✩✩✩✩✩
26 Апр 2021
7
0
Пытаюсь сделать, казалось бы, простую как три копейки штуковину: заменить ик-пульт на физические кнопки.
На ArduinoUNO залил сэмпл от IRremote (3.4.0) библиотеки: ReceiverDump, понажимал кнопки на пульте, вроде все коды считал, беру Digispark (attiny85) / Digispark Pro (attiny167), соединяю входной пин на UNO с выходным на Digispark, посылаю тот же сигнал, а он отправляется каким-то не таким, каким я его кодирую.
Пробовал и стандартные методы библиотеки IRremote: sendNEC, sendNECRaw и методы с явным указанием всего массива пауз/состояний — всегда отправляется так, будто первое состояние (9000нс) пропускается.
Пример декодированного сигнала с пульта:
Нормальный сигнал:
Protocol=NEC Address=0x0 Command=0x10 Raw-Data=0xEF10FF00 32 bits LSB first

Raw result in internal ticks (50 us) - with leading gap
rawData[68]:
     -65535
     + 182,-  89     +  12,-  11     +  12,-  12     +  11,-  12
     +  12,-  11     +  11,-  12     +  12,-  11     +  12,-  11
     +  12,-  12     +  11,-  33     +  12,-  33     +  11,-  33
     +  12,-  33     +  12,-  33     +  11,-  33     +  12,-  33
     +  11,-  34     +  11,-  12     +  12,-  11     +  11,-  12
     +  11,-  12     +  12,-  33     +  12,-  11     +  11,-  12
     +  11,-  12     +  12,-  33     +  11,-  34     +  11,-  33
     +  11,-  34     +  11,-  12     +  11,-  34     +  11,-  33
     +  12,-  33     +  11
Raw result in microseconds - with leading gap
rawData[68]:
     -3276750
     +9100,-4450     + 600,- 550     + 600,- 600     + 550,- 600
     + 600,- 550     + 550,- 600     + 600,- 550     + 600,- 550
     + 600,- 600     + 550,-1650     + 600,-1650     + 550,-1650
     + 600,-1650     + 600,-1650     + 550,-1650     + 600,-1650
     + 550,-1700     + 550,- 600     + 600,- 550     + 550,- 600
     + 550,- 600     + 600,-1650     + 600,- 550     + 550,- 600
     + 550,- 600     + 600,-1650     + 550,-1700     + 550,-1650
     + 550,-1700     + 550,- 600     + 550,-1700     + 550,-1650
     + 600,-1650     + 550

Result as internal ticks (50 us) array - compensated with MARK_EXCESS_MICROS=20
uint8_t rawTicks[67] = {182,89, 12,11, 12,12, 11,12, 12,11, 11,12, 12,11, 12,11, 12,12, 11,33, 12,33, 11,33, 12,33, 12,33, 11,33, 12,33, 11,34, 11,12, 12,11, 11,12, 11,12, 12,33, 12,11, 11,12, 11,12, 12,33, 11,34, 11,33, 11,34, 11,12, 11,34, 11,33, 12,33, 11};  // Protocol=NEC Address=0x0 Command=0x10 Raw-Data=0xEF10FF00 32 bits LSB first

Result as microseconds array - compensated with MARK_EXCESS_MICROS=20
uint16_t rawData[67] = {9080,4470, 580,570, 580,620, 530,620, 580,570, 530,620, 580,570, 580,570, 580,620, 530,1670, 580,1670, 530,1670, 580,1670, 580,1670, 530,1670, 580,1670, 530,1720, 530,620, 580,570, 530,620, 530,620, 580,1670, 580,570, 530,620, 530,620, 580,1670, 530,1720, 530,1670, 530,1720, 530,620, 530,1720, 530,1670, 580,1670, 530};  // Protocol=NEC Address=0x0 Command=0x10 Raw-Data=0xEF10FF00 32 bits LSB first

uint16_t address = 0x0;
uint16_t command = 0x10;
uint32_t data = 0xEF10FF00;

Pronto Hex as string
char ProntoData[] = "0000 006D 0022 0000 015F 00AA 0018 0014 0018 0016 0016 0016 0018 0014 0016 0016 0018 0014 0018 0014 0018 0016 0016 003F 0018 003F 0016 003F 0018 003F 0018 003F 0016 003F 0018 003F 0016 0041 0016 0016 0018 0014 0016 0016 0016 0016 0018 003F 0018 0014 0016 0016 0016 0016 0018 003F 0016 0041 0016 003F 0016 0041 0016 0016 0016 0041 0016 003F 0018 003F 0016 06C3 "
То, что декодируется тем же сэмплом при попытке послать этот сигнал любым способом (включая ручной, без библиотек, он ниже):
Неверный сигнал:
Protocol=PULSE_WIDTH Address=0x0 Command=0x0 Raw-Data=0xEF10FF00 32 bits LSB first

Space between two detected transmission is greater than 5000 but smaller than the minimal gap of 20000 known for a protocol.
If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h.


Raw result in internal ticks (50 us) - with leading gap
rawData[68]:
     -181
     +  90,-  11     +  11,-  11     +  12,-  11     +  11,-  11
     +  11,-  11     +  11,-  12     +  11,-  11     +  11,-  11
     +  12,-  11     +  33,-  11     +  34,-  11     +  34,-  11
     +  33,-  12     +  33,-  11     +  34,-  11     +  34,-  11
     +  33,-  12     +  11,-  11     +  11,-  11     +  12,-  11
     +  11,-  11     +  34,-  11     +  11,-  11     +  11,-  12
     +  11,-  11     +  34,-  11     +  33,-  11     +  34,-  11
     +  33,-  12     +  11,-  11     +  33,-  12     +  33,-  11
     +  34,-  11     +41669
Raw result in microseconds - with leading gap
rawData[68]:
     -9050
     +4500,- 550     + 550,- 550     + 600,- 550     + 550,- 550
     + 550,- 550     + 550,- 600     + 550,- 550     + 550,- 550
     + 600,- 550     +1650,- 550     +1700,- 550     +1700,- 550
     +1650,- 600     +1650,- 550     +1700,- 550     +1700,- 550
     +1650,- 600     + 550,- 550     + 550,- 550     + 600,- 550
     + 550,- 550     +1700,- 550     + 550,- 550     + 550,- 600
     + 550,- 550     +1700,- 550     +1650,- 550     +1700,- 550
     +1650,- 600     + 550,- 550     +1650,- 600     +1650,- 550
     +1700,- 550     +51834

Result as internal ticks (50 us) array - compensated with MARK_EXCESS_MICROS=20
uint8_t rawTicks[67] = {90,11, 11,11, 12,11, 11,11, 11,11, 11,12, 11,11, 11,11, 12,11, 33,11, 34,11, 34,11, 33,12, 33,11, 34,11, 34,11, 33,12, 11,11, 11,11, 12,11, 11,11, 34,11, 11,11, 11,12, 11,11, 34,11, 33,11, 34,11, 33,12, 11,11, 33,12, 33,11, 34,11, 255};  // Protocol=PULSE_WIDTH Address=0x0 Command=0x0 Raw-Data=0xEF10FF00 32 bits LSB first

Space between two detected transmission is greater than 5000 but smaller than the minimal gap of 20000 known for a protocol.
If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h.


Result as microseconds array - compensated with MARK_EXCESS_MICROS=20
uint16_t rawData[67] = {4480,570, 530,570, 580,570, 530,570, 530,570, 530,620, 530,570, 530,570, 580,570, 1630,570, 1680,570, 1680,570, 1630,620, 1630,570, 1680,570, 1680,570, 1630,620, 530,570, 530,570, 580,570, 530,570, 1680,570, 530,570, 530,620, 530,570, 1680,570, 1630,570, 1680,570, 1630,620, 530,570, 1630,620, 1630,570, 1680,570, 51814};  // Protocol=PULSE_WIDTH Address=0x0 Command=0x0 Raw-Data=0xEF10FF00 32 bits LSB first

Space between two detected transmission is greater than 5000 but smaller than the minimal gap of 20000 known for a protocol.
If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h.


uint16_t address = 0x0;
uint16_t command = 0x0;
uint32_t data = 0xEF10FF00;

Pronto Hex as string
char ProntoData[] = "0000 006D 0022 0000 00AE 0014 0016 0014 0018 0014 0016 0014 0016 0014 0016 0016 0016 0014 0016 0014 0018 0014 0040 0014 0042 0014 0042 0014 0040 0016 0040 0014 0042 0014 0042 0014 0040 0016 0016 0014 0016 0014 0018 0014 0016 0014 0042 0014 0016 0014 0016 0016 0016 0014 0042 0014 0040 0014 0042 0014 0040 0016 0016 0014 0040 0016 0040 0014 0042 0014 07CA 06C3 "
То есть, маркер протокола NEC (9000нс) почему-то считывается неправильно (к тому же, отрицательный сигнал). Команда не читается, но "data" одинаковая что там, что там.
Ядро ATTiny использую от Spence Konde.
Пробовал даже руками посылать, тот же результат — 9000 обрезаются, а в конце добавляется какое-то большое число.
Пример "ручной посылки":
#define IR_SEND_PIN     4

void setup() {
  pinMode(IR_SEND_PIN, OUTPUT);
  digitalWrite(IR_SEND_PIN, LOW);
}

void loop() {
  SendCommand(0x10);
  delay(2000);
}

// Отправка байта (протокол NEC-Clarion)
void SendByte(byte data)
{
  for (int i = 0; i < 8; i++)
  {
    digitalWrite(IR_SEND_PIN, HIGH);
    delayMicroseconds(560); // Пауза между битами
    digitalWrite(IR_SEND_PIN, LOW);

    if (data & 1) // Последний бит умножаем на 1
    {
      delayMicroseconds(1680); // Логическая единица
    }
    else
    {
      delayMicroseconds(560); // Логический ноль
    }

    data >>= 1; // Новый, сдвинутый вправо байт (на 1 бит)
  }
}

// Отправка команды
void SendCommand(byte command)
{
  // Что-то вроде приветствия,
  // особенность модифицированного протокола NEC
  digitalWrite(IR_SEND_PIN, HIGH);
  delayMicroseconds(9000);
  digitalWrite(IR_SEND_PIN, LOW);
  delayMicroseconds(4500);

  // Адрес протокола
  SendByte(0x00);
  SendByte(0xFF);

  // Отправка команды
  SendByte(command);
  SendByte(~command);

  // Для определения последнего бита (конец посылки)
  digitalWrite(IR_SEND_PIN, HIGH);
  delayMicroseconds(560);
  digitalWrite(IR_SEND_PIN, LOW);

  delay(120); // Техническая пауза
}
Не выходит каменный цветок. Что я делаю не так? Как правильно послать ИК-сигнал?
 

Sergo_ST

★★★★★★✩
15 Мар 2020
821
745
Обычно, у ик приёмников высокий уровень в состоянии покоя. И исходя из лога, скорее всего вам необходимо инвертировать везде в передающем коде логические уровни(и ещё бы неплохо добавить физическую подтяжку к +питания для сигнального пина кОм на 10-30), для примера:
C++:
digitalWrite(IR_SEND_PIN, LOW);
  delayMicroseconds(9000);
  digitalWrite(IR_SEND_PIN, HIGH);
  delayMicroseconds(4500);

digitalWrite(IR_SEND_PIN, LOW);
  delayMicroseconds(560);
  digitalWrite(IR_SEND_PIN, HIGH);
Но это справедливо только для связки мк-мк, при работе с ик передатчиком инвертировать сигнал не нужно, но нужно добавить несущую частоту 38кГц.
 
Изменено:
  • Лойс +1
Реакции: xa0c

xa0c

✩✩✩✩✩✩✩
26 Апр 2021
7
0
Благодарю. Да, инвертирование во всех трёх местах теперь выдаёт правильный код (по крайней мере, в сэмпле IRremote, проверить на реальном железе смогу только в конце недели).

ИК приёмников и передатчиков у меня не будет, весь смысл проекта — избавиться от ПДУ, управлять физическими кнопками.
На что может повлиять отсутствие подтяжки OUTPUT пина?
 

Sergo_ST

★★★★★★✩
15 Мар 2020
821
745
На что может повлиять отсутствие подтяжки OUTPUT пина?
Могут появляться ошибки при передаче вызванные помехами. Нужно изучать цепи принимающего устройства, возможно внешняя подтяжка там уже реализована.