3

I am trying to use Arduino Uno/ESP8266 to generate IR signal on top of carrier frequency(38KHz) to replace IR remote control.

First, I was trying to use IRremote.h library, but when using "irsend.sendNEC(0x8F4567A2, 32)" to send the code, the actual received IR code is not 8F4567A2 (using IRrecvDump example). So I used oscilloscope to hoop up with the transmitter pin to check what is the signal generated from Arduino/Esp8266. I noticed that carrier pulse duration is over 100us(38KHz should have ~26us).

Then, I found youtube tutorial teaching how to manually generate the signal without using IRremote library as following code. I still hooked up oscilloscope with the transmitter pin, and found the carrier pulse duration is over 100us instead of 26us, even I did set it to be 26us in sketch, and I cann't even see flat pulse width even I did set square pulse. But if I just simply put "IRcarrier(260)" in the loop() for 10 pulse cycles and removing all other code in the loop(), the oscilloscope showed correct pulse duration every 5s, and the pulse show kinda square pulse as expected.

I kinda stuck here with my IR project, trying to use arduino/esp8266 to replace TV IR remote.

#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);
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
Christ Gao
  • 41
  • 2
  • Anyway, by using "IRrecvDump" example of IRremote library as a way to check received code, the IR receiver side can never receive the matched IR code set in the sketch using either of the two methods. – Christ Gao Mar 09 '17 at 21:12
  • I have not experimented with it, but [this post on esp8266.com](http://www.esp8266.com/viewtopic.php?f=24&t=832) discusses performance of gpio using the variables and table lookups vs. using the actual values (1 instead of HIGH for example), and it says there is a large speed improvement using actual values. He is using Lua though. Also, what is your cpu speed set to? – leetibbett Mar 10 '17 at 13:58
  • [Here is a discussion](https://github.com/esp8266/Arduino/issues/1536) about i2c speed and they are achieving much faster timing, take a look at their code – leetibbett Mar 10 '17 at 14:03

1 Answers1

0

In general for such timings I would prefer to write directly to the port and use the timer interrupts for the timing. For example digitalWrite(), which is slow anyway, will take more or less time depending on the MCU frequency.

Also make sure the value of (the defined) F_CPU is the same as the frequency your MCU is running at.

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

Divisions can take a lot of CPU cycles, so I would change that to

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

But if I just simply put "IRcarrier(260)" in the loop() for 10 pulse cycles and removing all other code in the loop(), the oscilloscope showed correct pulse duration every 5s, and the pulse show kinda square pulse as expected.

Now this is strange, because the exact same function is called to generate the pulse.

Are you sure BITtime still has the correct value inside IRsendCode()? (also, BITtime is not an exact multiple of 26, but that won't make a big difference)

What pulse does IRcarrier(9000); generate? Or do you have some other code running as well that could conflict with the delay functions?

Danny_ds
  • 11,201
  • 1
  • 24
  • 46