Arduino / Esp8266红外遥控载波频率

3

我正在尝试使用Arduino Uno/ESP8266在38KHz载波频率上生成红外信号来替代红外遥控器。

首先,我尝试使用IRremote.h库,但是当我使用“irsend.sendNEC(0x8F4567A2, 32)”发送代码时,实际接收到的IR代码不是8F4567A2(使用IRrecvDump示例)。因此,我使用示波器将发射器引脚连接起来以检查Arduino/Esp8266生成的信号是什么。我注意到载波脉冲持续时间超过100us(38KHz应该约为26us)。

然后,我找到了YouTube教程,教人们如何手动生成信号而不使用IRremote库,代码如下。我仍然将示波器与发射器引脚连接起来,并发现载波脉冲持续时间超过100us,即使我在sketch中设置为26us,我也无法看到平坦的脉冲宽度,即使我设置了方波脉冲。但如果我只是简单地在loop()中放置“IRcarrier(260)”,并删除循环中的所有其他代码,示波器每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);
}

无论如何,通过使用IRremote库中的“IRrecvDump”示例来检查接收到的代码,红外接收器侧都无法接收到在草图中使用任一方法设置的匹配的红外代码。 - Christ Gao
我没有尝试过,但是esp8266.com上的这篇文章讨论了使用变量和表查找与使用实际值(例如1而不是HIGH)来使用gpio的性能,并且它说使用实际值可以大大提高速度。他正在使用Lua。另外,你的CPU速度设置是多少? - leetibbett
这里有一个关于i2c速度的讨论,他们实现了更快的时序,请看一下他们的代码。 - leetibbett
1个回答

0
一般来说,对于这样的定时,我更喜欢直接写入端口并使用计时器中断进行定时。例如digitalWrite(),无论如何都很慢,将根据MCU频率花费更多或更少的时间。
此外,请确保(定义的)F_CPU的值与您的MCU运行频率相同。
for(int i=0; i < (IRtimemicroseconds / 26); i++)

除法可能需要大量的CPU周期,因此我建议将其更改为

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

但是,如果我只是在 loop() 中简单地放置“IRcarrier(260)”进行 10 个脉冲周期,并删除循环中的所有其他代码,则示波器每 5 秒钟显示正确的脉冲持续时间,并且脉冲显示出预期的方形脉冲。 现在这很奇怪,因为完全相同的函数被调用以生成脉冲。 你确定 IRsendCode() 中 BITtime 仍然具有正确的值吗?(此外,BITtime 不是 26 的精确倍数,但不会产生太大差异) IRcarrier(9000); 生成什么脉冲?或者你是否还运行了其他可能与延迟函数冲突的代码?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接