Несущая частота инфракрасного пульта дистанционного управления Arduino / Esp8266

Я пытаюсь использовать Arduino Uno / ESP8266 для генерации ИК-сигнала поверх несущей частоты (38 кГц), чтобы заменить ИК-пульт дистанционного управления.

Сначала я пытался использовать библиотеку IRremote.h, но при использовании irsend.sendNEC (0x8F4567A2, 32) для отправки кода фактический полученный ИК-код не был 8F4567A2 (с использованием примера IRrecvDump). Поэтому я использовал осциллограф, чтобы проверить, какой сигнал генерируется Arduino / Esp8266. Я заметил, что длительность импульса несущей превышает 100 мкс (у 38 кГц должно быть ~ 26 мкс).

Затем я нашел учебник на YouTube, в котором рассказывается, как вручную генерировать сигнал без использования библиотеки IRremote в следующем коде. Я все еще подключил осциллограф к контакту передатчика и обнаружил, что длительность импульса несущей превышает 100 мкс вместо 26 мкс, даже я установил 26 мкс в эскизе, и я даже не могу видеть плоскую ширину импульса, даже если я установил прямоугольный импульс. . Но если я просто введу «IRcarrier (260)» в loop () для 10 импульсных циклов и удаляю весь другой код в loop (), осциллограф будет показывать правильную длительность импульса каждые 5 секунд, а импульс покажет прямоугольный импульс, как и ожидалось. .

Я как бы застрял здесь со своим ИК-проектом, пытаясь использовать arduino / esp8266 для замены ИК-пульта ТВ.

#define IRLEDpin  2              //the arduino pin connected to IR LED to ground. HIGH=LED ON
#define BITtime   562            //length of the carrier bit in microseconds
//put your own code here - 4 bytes (ADDR1 | ADDR2 | COMMAND1 | COMMAND2)
unsigned long IRcode=0b11000001110001111100000000111111;  

// SOME CODES:
// Canon WL-D89 video remote START/STOP button = 0b11000001110001111100000000111111

void setup()
{
}

void IRsetup(void)
{
  pinMode(IRLEDpin, OUTPUT);
  digitalWrite(IRLEDpin, LOW);    //turn off IR LED to start
}

// Ouput the 38KHz carrier frequency for the required time in microseconds
// This is timing critial and just do-able on an Arduino using the standard I/O functions.
// If you are using interrupts, ensure they disabled for the duration.
void IRcarrier(unsigned int IRtimemicroseconds)
{
  for(int i=0; i < (IRtimemicroseconds / 26); i++)
    {
    digitalWrite(IRLEDpin, HIGH);   //turn on the IR LED
    //NOTE: digitalWrite takes about 3.5us to execute, so we need to factor that into the timing.
    delayMicroseconds(9);          //delay for 13us (9us + digitalWrite), half the carrier frequnecy
    digitalWrite(IRLEDpin, LOW);    //turn off the IR LED
    delayMicroseconds(9);          //delay for 13us (9us + digitalWrite), half the carrier frequnecy
    }
}

//Sends the IR code in 4 byte NEC format
void IRsendCode(unsigned long code)
{
  //send the leading pulse
  IRcarrier(9000);            //9ms of carrier
  delayMicroseconds(4500);    //4.5ms of silence

  //send the user defined 4 byte/32bit code
  for (int i=0; i<32; i++)            //send all 4 bytes or 32 bits
    {
    IRcarrier(BITtime);               //turn on the carrier for one bit time
    if (code & 0x80000000)            //get the current bit by masking all but the MSB
      delayMicroseconds(3 * BITtime); //a HIGH is 3 bit time periods
    else
      delayMicroseconds(BITtime);     //a LOW is only 1 bit time period
     code<<=1;                        //shift to the next bit for this byte
    }
  IRcarrier(BITtime);                 //send a single STOP bit.
}

void loop()                           //some demo main code
{
  IRsetup();                          //Only need to call this once to setup
  IRsendCode(IRcode);                 
  delay(5000);
}

person Christ Gao    schedule 09.03.2017    source источник
comment
В любом случае, используя пример IRrecvDump библиотеки IRremote в качестве способа проверки полученного кода, сторона ИК-приемника никогда не сможет получить согласованный ИК-код, установленный в скетче, используя любой из двух методов.   -  person Christ Gao    schedule 10.03.2017
comment
Я не экспериментировал с этим, но этот пост на esp8266.com обсуждает производительность gpio с использованием переменных и поиска в таблицах по сравнению с использованием фактических значений (например, 1 вместо HIGH), и говорит, что при использовании фактических значений наблюдается значительное улучшение скорости. Однако он использует Lua. Кроме того, какова скорость вашего процессора?   -  person leetibbett    schedule 10.03.2017
comment
Здесь обсуждается скорость i2c, и они достигают гораздо более быстрой синхронизации, взгляните в их кодексе   -  person leetibbett    schedule 10.03.2017


Ответы (1)


В общем, для таких таймингов я бы предпочел писать напрямую в порт и использовать прерывания таймера для тайминга. Например, digitalWrite(), который в любом случае медленный, займет больше или меньше времени в зависимости от частоты MCU.

Также убедитесь, что значение (заданного) F_CPU совпадает с частотой, на которой работает ваш MCU.

for(int i=0; i < (IRtimemicroseconds / 26); i++)

Подразделения могут занимать много циклов ЦП, поэтому я бы изменил это на

for(int i=0; i < IRtimemicroseconds; i += 26)

Но если я просто введу «IRcarrier (260)» в loop () для 10 импульсных циклов и удаляю весь другой код в loop (), осциллограф будет показывать правильную длительность импульса каждые 5 секунд, а импульс покажет прямоугольный импульс, как и ожидалось. .

Это странно, потому что для генерации импульса вызывается точно такая же функция.

Вы уверены, что BITtime по-прежнему имеет правильное значение внутри IRsendCode()? (кроме того, BITtime не является точным кратным 26, но это не имеет большого значения)

Какой импульс генерирует IRcarrier(9000);? Или у вас работает другой код, который может конфликтовать с функциями задержки?

person Danny_ds    schedule 11.03.2017