Ok, I’m not really OCD but I have to admit that sometimes I get stuck on a theme. Besides electronics and software I like to do things like woodwork and, lately, copper pipe yard art. The problem with the craft stuff is that I build like crazy until I either lose interest or run out of closet space. Anyway, you might say that I’m at least slightly stuck on the PIC IR theme because this is my third post about it. One earlier post was about decoding and displaying NEC format IR codes (the most common) and the previous post was about actually building a useful IR receiver to control something. The one missing piece is an IR transmitter so that’s what this post is about. While making this a standalone IR remote may not be highly practical, one thing it would be useful for is to make up your own codes to copy into a cheap learning remote like the one I mentioned in an earlier post.
NEC IR Transmit Format
In an earlier post we looked at the IR receive format that comes out of the 3-pin IR receiver. As you can see above, the transmit format is basically the inverse of that waveform. The other key difference (also shown above) is that the positive portions of the waveform are filled with pulses (aka: a carrier frequency). In the case of the NEC format, the carrier frequency is centered around 38-kHz. That is what the 3-pin receiver module looks for when decoding the transmission. The low parts of the waveform are basically an off time for the IR LED. In other words, no pulses are being transmitted. The term for this type of function is known as “signal gating”. Very simply, when we open the gate, a stream of 38-kHz pulses comes out and when we close the gate no pulses come out. We will see in the software section that this is easy to implement with the PIC. One other thing to note in the transmit sequence is that there is one last 560us pulse burst to signify the end of transmission (EOT).
The waveform above shows the old NEC format where there were originally only 256 addresses allocated. That meant that the second data byte was simply the inverse of the first byte. The cheap (non-learning) remote I detailed in a previous post adheres to this old format but most modern remotes do not. The newer format allows for up to 65k addresses by using both of the address bytes.
As seen in the schematic, the hardware is pretty simple. I only added two normally open, momentary contact buttons on my prototype but there are three unused inputs on the PIC that could also be used. The IR LED is one that I scrounged from a broken remote but they are cheap if you need to buy one. The driver for the IR LED is just a transistor to boost the current dumped across the LED. When I looked online at similar projects I found a wide variety of circuits and comments about the proper duty cycle and amount of current to apply to the LED. It really has to do with how much range you want for the remote. Keep in mind that we are applying short pulse bursts of current to the LED so it’s not the same situation as if we were turning it on for long periods. What I finally settled on was a 50% duty cycle for the 38-kHz pulses. I also wanted to keep the peak power below ½ watt so in my prototype I wired a pair of 82 ohm, ¼ watt resistors in parallel for R1. Originally I used a single 75 ohm, ¼ watt resistor and that gave me a maximum range of about 14 feet. With the parallel pair of 82 ohm resistors (effectively 41 ohms) it worked at double that range.
The software link is listed below. While it is targeted for the 12F683, it is easily ported to other versions of the PIC. You will need to change the line that identifies the PIC version (LIST=) and the INCLUDE file but those are intuitive changes. The __CONFIG line may also need tweaking just because one or two of the labels used are spelled differently in some of the INCLUDE files. Just make sure that the PIC you use has the pulse width modulation (PWM) capability.
There are a couple of different ways to generate the waveform that we need. One method that is common on the internet uses a series of NOPs to produce the 38-kHz signal and set the duty cycle. That method works because a 38-kHz pulse takes a little more than 26us so it is fairly easy to do that using the PIC internal 4-MHz clock (1us per instruction cycle). The other common method is to use something that produces a 38-kHz pulse stream and then use the PIC to gate the pulses for the proper amount of time. That could be done using something like a 555 timer to generate the pulses but many PICs have the pulse generation capability built in. What I’m referring to is the PWM function that we used in Episode 9 to control the speed of a DC motor. For our IR application, however, we will allow the PWM generator to run at a fixed duty cycle instead of changing the duty cycle like we did for the motor speed controller.
As we saw in an earlier post, the PIC provides a dedicated pin for the PWM output. In order to gate the pulses on this pin all we have to do is to change the definition of the pin from an input to an output. To close the gate we simply change the pin definition back to an input. That can be done on the fly in the software. While starting a transmission we want to ensure that we are synchronized with the pulses so we keep tabs on the Timer2 overflow flag. Timer2 is dedicated to the PWM function so it will set the overflow flag at a 38-kHz rate. All we need to do then is to count the number of overflows based on the time we need to leave the gate open. For instance, the 560us part of the NEC waveform is equal to approximately 21 pulses. We also count overflows for the gate closed time. All of that could be done using another timer and interrupts but the easy way is to just kill time watching the overflow flag in the software. That’s ok because there really isn’t anything else we need to do when outputting the IR waveform.
In this example, I hardcoded the IR address to be 00 FF and gave arbitrary values to the two switch commands. You can change those to suit your own needs. The switch handling logic is very simple and just looks for a low value on the appropriate GPIO pin. When one is detected a switch handler routine is called. Each switch handler delays 50ms and then checks the GPIO pin again. That’s to account for contact bounce on the switch. After the IR command is transmitted we check the GPIO pin for a release of the switch. When a release is detected we again delay for 50ms to account for possible contact bounce. That’s it for this post. Check out my other electronics projects.