Electronic – How to measure pulse width of an IR signal using an 8-bit PIC

frequency-measurementmicrocontrollerpic

My friend and I want to design a universal learning remote controller, like this one, for learning purposes. What we want to do basically is store and replay infrared pulses.

We want to detect 36kHz, 38kHz and 40kHz signals. A 40kHz signal will have a period of 25\$\mu\$s.

We want to use an 8-bit PIC microcontroller, for now we have selected PIC16F616, that will run at 20MHz high speed crystal oscillator. We have two options available:

  1. Use the Interrupt On Change module.
  2. Use the capture mode of the CCP module.

First option will be as follows:

Assume a register is set as: unsigned char _10_us = 0;. This register will hold the time. TMR2 module with period register is set to create an interrupt every 10\$\mu\$sec. When an interrupt occurs, it will increment the _10_us register and exit. This will give a maximum time of 2.55msec. If more time measurement is needed, additional registers such as _1_ms can be defined and incremented as needed.

Now, every time an interrupt is generated by any kind of change ( high-to-low or low-to-high), the program will note the current time, that is the value of _10_us register. After a while, when the next interrupt is generated, the program will subtract the saved value from the _10_us register, and thus will now the time that is taken in the meantime, with a unit of 10 \$\mu\$seconds.

This option make me scratch my head; TMR2 interrupt will occur about every 50 instructions. Interrupt handling will take about 20 instructions. I am left with 30 instructions to calculate and save the period to an array. Will this method work?

Second option will be as follows:

Set up the capture mode of the CCP module so that it will generate an interrupt when an event(high-to-low) occurs on CCP1 pin. In the interrupt routine, it will set a flag so that a task in the program can calculate(if needed) and save the value of CCPR1H (probably will not be needed) and CCPR1L. Then we will change the configuration of the capture mode so that it will trigger the interrupt when a low-to-high edge occurs. And then it will wait for the next event. I cannot estimate the performance of this method since I've never used it.

Another option?

We can use an infrared demodulator IC such as TSOP17xx series. That would solve our problem completely. However some questions come to mind.

Our reading distance requirement is not much; 1 metre (~3 feet). If we select a TSOP1738 that is meant to be working in 38kHz, how well will this work with 36kHz and 40kHz signals?

Page 4 of the datasheet of TSOP17xx series shows "Frequency Dependence of Responsivity" graph. As far as we understood;

  • 40kHz, which is ~1.053 of 38kHz, will give a relative responsitivity of ~0.6.
  • 36kHz, which is ~0.95 of 38kHz, will give a relative responsitivity of ~0.65.

What do these values mean? Can we use a TSOP1738 and be fine?

Best Answer

Yes, the TSOP1738 will do at this short distance. The 0.65 relative responsitivity means that at 36 kHz your IR LED needs to be \$\sqrt{0.65}\$ = 0.8 times closer to see the same signal strength, due to the inverse-square law. So if your TSOP1738 sees a certain level for 38 kHz at 1 m, you'll have to hold the transmitter at 80 cm to get the same signal strength at 36 kHz. BTW, with a remote control with fresh batteries I measured perfect reception at more than 15 m distance, so no problem at all.

Don't worry about the PIC's performance. The TSOP1738 won't output the 38 kHz signal. That's the carrier frequency, which is removed by the TSOP1738 to get back the baseband signal, which has a much lower frequency, with pulse durations in the order of 1 ms, so there's plenty of time to measure time between edges accurately.

The following scope images illustrate this:

enter image description here

This is one RC5 code. The top signal is the 36 kHz modulated signal, the bottom the baseband signal with the actual code.

enter image description here

This is zoomed in on one pulse of the baseband signal. You can see individual pulses of the 36 kHz carrier.

One more word about the carrier frequency. You may be using a remote control which you don't know this frequency of. The TSOP1738 doesn't give it on its output, so if you want to read it you'll have to connect an IR photodiode or transistor to one of the PIC's inputs and read the time between two same edges. That's feasible. Period times for different carrier frequencies:

40 kHz: 25 µs
38 kHz: 26.3 µs
36 kHz: 27.8 µs

A 20 MHz PIC16F616 has an instruction cycle of 200 ns (it divides the clock by 4!). So readings for the three frequencies should be about 125, 131 and 139. That should be enough to tell them apart. But if you want you can let a number of edges pass and only read the timer after the 10th interrupt, for instance: 1250, 1316, 1389. Not too much longer because you have to keep the time shorter than one pulse of the baseband signal.

Success!