A Serial-Driven Infrared Remote Controller

Copyright © 1991 John H. DuBois III

Overview

This paper describes a serial infrared transmitter (SIT) capable of generating the infrared codes used by most current equipment that incorporates an infrared remote control. It is operated by a computer through an asynchronous communications port. Driver software for a computer with such a port can use the SIT to issue commands to remote-controlled equipment, and can thus act as a universal infrared remote control. Putting the equipment under computer control presents many possibilities besides direct use through a menu or command line.

The major limitation in application of the SIT is that it can only produce one carrier frequency. Since most current equipment uses a 40 kHz carrier, this is not a serious problem. Also, the device does not record the output of remote controls. The remote codes must be analyzed by other means and saved in data files.

The SIT is intended to use an asynchronous serial bitstream to modulate an infrared carrier in the simplest manner possible. It is operated exclusively from a computer. It has no keypad; commands are entered at the computer keyboard, or selected with a mouse or other input device. The SIT is not programmable. The codes used to control the remote equipment are stored on the computer and sent to the SIT as necessary.

Asynchronous communication is used for several reasons. Asynchronous ports are available for virtually all computers. Since the asynchronous port produces a precisely timed serial bitstream, there is no need for circuitry on the SIT to do that. Also, a single byte written to the computer's serial port can be used to send several bits to the SIT, while a parallel port used for direct output would require that a byte be written for each bit to be sent. If the serial port uses a UART (serial transceiver chip) with an on-board FIFO buffer, several bytes can be written to it at once (up to 16 for the 16550 series of UARTs), further reducing the load on the computer, which may have other functions.

The major problem with using an asynchronous port for communication is that the infrared codes used by common equipment are not asynchronous. They are usually self-clocking bitstreams with no start or stop bits, often with variable bit timing. Therefore, an asynchronous port cannot directly produce the required codes. However, carrier transitions do occur at intervals set by a fixed clock, so that the codes can be synthesized if the carrier can be switched on and off at the rate set by the clock. Although each unit has its own clock rate, the remote receivers are highly tolerant of timing discrepancies, so the clock rates do not need to be matched exactly.

Because a UART produces a bitstream that includes start and stop bits after every word, it cannot directly send the codes even if its clock rate is set to the same clock rate used by an infrared remote. The SIT circumvents this problem by using the UART to send one-bit words. Every data bit sent by the UART is preceded by a start bit and followed by a stop bit, so each data bit takes the same amount of time to send. By using the data bit to set the state of the carrier for three serial bit periods (until the next data bit is received), the SIT lets a stream of data bits control equal periods of carrier time.

The UARTs used by most computers can only be set to between five and eight data bits per word. To simulate a one-bit UART, the UART is set to seven data bits per word with one start bit and one stop bit, for a total of nine bit times per byte written to the UART. The byte written to the UART is arranged so that it actually includes three data bits, with the other bits always set to one or zero to simulate the other start and stop bits (depicted later). From here on, the term data bit will refer to the bits that control the state of the carrier, three of which are written to the UART in each byte. The rate at which these data bits are sent, which determines the controllable unit of carrier time, is referred to as the SIT rate.

The data rate used by remotes is low enough, and the tolerance for timing errors (afforded by the self-clocking protocols) is high enough, that the asynchronous port can be set to a relatively low, standard Baud rate and still have fine enough timing granularity to operate various remote devices. A standard Baud rate also allows the SIT to be used from an operating system like UNIX that does not allow setting the Baud rate to nonstandard values without modifications to the serial driver. The Baud rate is selected so that the SIT rate (one-third the Baud rate) is an even enough multiple of the clock rates of all of the receivers of the equipment to be operated that the waveforms produced are within their tolerance. If the clock rates vary widely, the Baud rate should be selected so that the SIT rate is sufficient for the equipment with the highest clock rates. This will probably result in sufficiently fine granularity to synthesize the waveforms of the remotes with lower clock rates.

Circuit Description

It is relatively easy to extract the data from the one-bit asynchronous protocol so that it can be used for carrier modulation. The code for a data bit can have only two forms. It will always have one rising edge and one falling edge. The rising edge will occur at the start of the start bit. The falling edge will occur after the end of the start bit if the data bit is a one (because a one is transmitted as a low voltage by an RS232 port), or at the end of the data bit if the data bit is a zero. The stop bit guarantees that even if the data bit is a zero, there will be a period of low voltage between the end of the data bit and the next start bit.

To convert each start bit/data bit/stop bit into a continuous high or low voltage, the SIT starts a one-shot timer each time the data line goes high. The one-shot is set to 1.5 serial bit times. When the one-shot finishes, whatever value is on the data line is latched. The latched value is used to enable or disable the carrier transmission. Another timer ensures that if the last bit sent to the SIT inadvertently leaves the carrier on, it is eventually turned off.

    ___________
 0 |        :  |_____
    _____   :
 1 |     |__:_________
            ^ Latch Time

The SIT is implemented in CMOS so that it can be battery operated. The carrier disable turns off both the carrier oscillator and the infrared emitters so that the SIT will be completely quiescent when not being used. The analog parts of the design avoid DC current paths, resulting in a quiescent current consumption of approximately 0.5 uA. This makes operation from a 9V battery practical without the need for trickle charging from the data line or other schemes.

The input signal is conditioned by resistors and diodes to limit it to the range (0,+9V). It is inverted and cleaned up by a NAND gate. This signal is fed to a one-shot made from two NAND gates arranged with feedback so that even if the trigger ends before the timing period ends (as it will if the data bit is a one), the one-shot will continue timing. The cleaned up signal is also put on the D input of a flip-flop, in addition to driving an RC network which will reset the flip-flop whenever no data is transmitted for a certain period of time (so that the transmitter will not be left on).

The output of the one shot is the clock for the flip-flop. The received data bits appear at the outputs of the flip-flop, which enable or disable an oscillator made from a Schmitt NAND gate, and reset or allow clocking of the flip-flop that the oscillator drives. The flip-flop output drives a VMOS transistor which in turn drives two high-power infrared emitting diodes. The emitters can be mounted parallel to each other to obtain greater range than a single emitter would have, or can be mounted with an angle between them for better coverage of multiple pieces of equipment. They are in series, so no more current is used for two than would be needed for one. The flip-flop ensures that a good square wave is produced for the carrier, and avoids the need for another inverter (package or transistor) which would be necessary because disabling the oscillator forces it high which would turn on the N-channel VMOS transistor. The transistor also drives a visible-red emitter to provide an operating indicator.

Transmitter Construction
+9 O__|/|__ __|/|______          +9 O___|/|__,---\/\/\/--+    +       O +9
      |\|  |  |\|     _|_               |\|  |      ^ R1 |--)|--+_____|
 O Tx      |   _____  \c/      _____         |______|   _|_470uF|     |
 |--\/\/\--+--|     \    ,----|     \ 0.001uF|   _____  \c/    _|_   _|_IR
 |   47K  +9  | U1A  |O--|    | U1B  |O--|(--+--|     \     red\ /   \ /
 |         O--|_____/    |  ,-|_____/       +9  | U1C  |O-+    ---~~ ---~~
 /10  ___________________|  |                O--|_____/   |     |     |
 \K  |   |      |   ________|_____________________________|     |    _|_IR
 /   |  _|_     |  |   _________________________                \    \ /
 \   /  /_\    _|__|__|_      _____         ____|____           /    ---~~
 /   \   |    | D  > ~Q |  ,-|     \  80kHz|    R    |     470R \     |
 |   /1M |    |        Q|--' | U1D  |O--+--|>      ~Q|--+       /     |
_|_  \   |----|R  U2A   |  ,-|_____/    |  |   U2B   |  |       \     \
\c/  /   |    |         |  |            /  |        D|--'       |     /
     |___|    |_S_______|  |        20K \  |__S___Q__|    ______| 27R \
     | 0.1uF    |   0.001uF|            /     |   |     ||      |  1W /
     `--|(--+  _|_  ,--)|--|_____       \    _|_  `-----||<-+   |     \
            |  \c/  |      |     |      /    \c/        ||__|   |     |
           _|_     _|_     | R2  V 20K  |          VN10KM  _|_  |_____|
    Common \c/     \c/     `---\/\/\----'                  \c/

U1 is a CD4093B quad Schmitt NAND package. U2 is a CD4013B dual D flip-flop package. All diodes are 1N914 or equivalent. The IR emitters are XC880A or equivalent. The LED marked red can be any visible LED. The transistor marked VN10KM can be any N-channel power MOSFET with an ON resistance at 9V gate voltage of five ohms or less. None of the component values is critical.

The adjusted value of R1 should be approximately (2e+9)/(bits/s) ohms, where (bit/s) is the Baud rate of the port the SIT is connected to. Select a pot with a somewhat higher value and adjust it until the output of U1C goes low for about 1.5x the bit time of the serial port each time a data bit is sent. Adjust R2 until the output of U1D is 80 kHz when the oscillator is on. Connect the serial line signal ground to the circuit common. Connect the serial transmit-data line to the point marked Tx. Remember to apply power to the two integrated circuits.

The serial signal, clipped to the power supply rails, should appear at the input of U1A. Note that the 9V supply and CMOS circuitry require that the serial signal reach at least +4.5V when a zero is sent in order for it to be recognized. Any good serial port will easily satisfy this (most reach +12V to +15V). The serial signal should appear inverted at the output of U1A. The output of U1B should go high for 1.5 bit times when a one is sent, and go high for two bit times when a zero is sent. The output of U1C should go low for 1.5 bit times regardless of what is sent. The data bit transmitted should appear on the Q output of U2A. When a one is sent, the oscillator formed from U1D should produce an 80 kHz signal at the output of U1D, and a 40 kHz square wave should appear at the Q output of U2B and should be transmitted by the IR emitters. If a sequence of ones is sent, the visible LED should flicker on.

Adjustment and Operation

To select the SIT rate, determine the clock period of the remote codes of the equipment to be controlled. This is the unit of time on which all carrier transitions take place. For example, one Mitsubishi remote sends a zero as 10 cycles of carrier followed by 30 cycles of no carrier, and a one as 10 cycles of carrier followed by 70 cycles of no carrier. The clock period is therefore 10 cycles of 40 kHz, or 1/4000 second. Accurately creating codes for this device requires a SIT rate of 4000 bps.

When all of the clock periods have been determined, select a SIT rate that all of the clock periods can be approximately constructed from. Generally, just selecting the shortest clock period will work. If it doesn't, halve the period.

Multiply the SIT rate by three to get the approximate serial rate and then select the closest standard serial rate. For the Mitsubishi remote, the approximate serial rate is 12 Kbps. The closest standard serial rates are 9600 bps and 19.2 Kbps, giving SIT rates of 3200 bps and 6400 bps. Most receivers expecting a code with a clock period of 1/4000 second will accept codes produced with a SIT rate of 3200 bps, so a serial rate of 9600 bps would be tried first.

In some cases, it may not be necessary to accurately reproduce a short pulse sent by a remote. Some remotes send a brief, intense pulse for each bit, followed by variable period of off-time. This is used to extend the range of the remote without overdriving the emitter. A longer pulse, requiring less time resolution, will also work, since the data is coded in the length of the period from the start of the pulse to the start of the next pulse. For example, the receiver for the Mitsubishi remote described above actually works fine with the serial port set to 4800 bps and the SIT set accordingly, as long as the software driving the serial port rounds up codes that are less than one data-bit-time long. The receiver is allowing considerable leeway:

           0          1
Expected ~___      ~_______

Sent     ~~~___    ~~~______

It is generally advisable to use the lowest serial port rate that will work. Although serial ports can often be set to very high rates, perhaps up to 110 Kbps, the system may not actually be able to write data at that rate, especially if it has other functions. Each word will be sent at a high rate, but there will be gaps between them, so that the timing of the code is ruined. Under UNIX, output at high rates may break up on clist (serial driver character buffer) boundaries, so it is advantageous to ensure that an entire code fits in a clist, which is typically 64 bytes long. At higher Baud rates, it is necessary to send more data to transmit the same code, so that a code may require more than a clist can hold. Even if a single remote code fits in a clist, a multi-code sequence may not. It may even be longer than the maximum amount of data that will be stored by the serial driver for tty output. Breakup will occur if the process generating output is not run again before the tty output buffer is exhausted. Using the lowest Baud rate possible reduces all of these problems.

To use the SIT, set the serial port to the Baud rate that R1 has been adjusted for, and seven data bits, one start bit, and one stop bit. In the byte written to the serial port, bits one and four should always be one (to create extra stop bits), and bits two and five should always be zero (to create extra start bits). The data bits to be transmitted are sent in bits zero, three, and six. An RS232 port transmits a one as a negative voltage and a zero as a positive voltage. Data is transmitted from low bit to high bit. After clipping to the supply rails, a one bit appears as 0V and a zero bit appears as +9V.

       ____________         ____________         ____________
0     /start\ 0/lo \   1   /  2  \   3  \   4   /  5  \ 6/hi \ stop
1 ___/       \______\_____/       \______\_____/       \______\_____
     | start  bit 0  stop | start  bit 1  stop | start  bit 2  stop |

Place the SIT somewhere where the emitters can cover all of the equipment to be controlled, preferably in a position where the transmissions are not likely to be blocked. If the equipment is stacked on shelves and the SIT is put at the front of the bottom shelf with the emitters pointed up, transmission is unlikely to be blocked. However, the transmissions will be perpendicular to the receivers, so it will probably be necessary to add reflectors to make the SIT work reliably. Try taping small pieces of aluminum foil above the receivers, either on the equipment itself or on the shelf above each piece of equipment. Angle the foil so as to reflect the transmissions into the receivers, with the foil high enough that the equipment can still be operated by the handheld remotes.

Decoding Signals

The best way to decode the signals from an infrared remote is to digitize and record them. The data could then be directly used, or could be converted to a more easily interpreted form. The codes can be observed with a phototransistor or photodiode, or by opening up the remote control and connecting directly to the emitter leads.

If no means of digitizing signals is available, the next best option is to use a storage oscilloscope and transcribe the codes manually. If only a non-storage 'scope is available, a code can usually be viewed by holding down a button on the remote. However, some remotes only send a code once, so it may be necessary to repeatedly press each button to view the code for the button. The codes tend to be somewhat long, so set the 'scope to x10 time magnification, if available.

First determine the fundamental form of the codes. The base time period that all state changes occur on will probably be relatively obvious. Don't look at the beginning or ending of the pulse train for this, because the code may start or end with a sequence where the carrier is on and/or off for longer periods than it is at any point in the data. Generally, the base time period will be the length of the shortest on- or off-time observed anywhere in the code. Record the number of carrier cycles in the base time period.

Once the base time period has been found, write down some code segments with on-times written as 1 and off-times written as 0. But, don't consider these to be the real code being transmitted, because the self-clocking protocol includes a lot of redundancy. Codes could be recorded and transmitted this way, but the transcription would be needlessly verbose, and would obscure the underlying code. Instead, determine the bit encoding that is being used. Try dividing the code segments into bits on zero to one transitions (points where the carrier turns on), so that each bit code consists of an on-time followed by an off-time. Some remotes may use other codes (for example, Manchester coding).

There should be only two bit codes. They will probably have different lengths. Decide which will be recorded as a zero and which will be recorded as a one. In the example data given below, the shorter code, or the one that has the shorter on-time, is taken to be a zero and the other is taken to be a one. Once the codes for zero and one have been determined, the codes for each button can be recorded in this more compact form. However, it may be necessary to separately record a start or stop sequence that cannot be described using the codes for zero and 1 (though none of the remotes described below have a stop sequence like this).

To further reduce the amount of data transcribed and saved, check the codes sent by each button for a common prefix and/or suffix, after the start and before the stop sequences, if any. If there are prefixes and/or suffixes that are common to all of the codes, they can be recorded just once. Be very careful to start and finish transcribing the variable part of the code for each button at the correct points. If the remote sends codes that appear to be of constant length after conversion, a code that comes out longer or shorter is likely to have been copied incorrectly. This is another reason to record the actual function codes instead of their transmitted forms.

Here are some examples. Data bit coding is shown with on periods as ~ and off periods as _. Start and stop are start and stop sequences that cannot be represented with ones and zeros. They are given in the same form as the data bit codes. Prefix and suffix are the common prefix and suffix codes found. Pause, sleep, and repeat are described later.







        Mitsubishi VCR/audio/TV remote, with the VCR/audio|TV switch set
        to VCR/audio, and the VCR-A/VCR-B/Audio select set to VCR-A.
        Carrier: 40 kHz
        Cycles in base time period: 10
        0 data bit: ~___
        1 data bit: ~_______
        prefix: 1110
        start, stop, suffix: none
        Length of unique part of codes: 13 bits
        Pause: 25 mS
        Sleep: 25 mS
        Repeat: 3

        Kenwood Remote Control Unit RC-6010
        Carrier: 40 kHz
        Cycles in base time period: 22
        0 data bit: ~_
        1 data bit: ~___
        Start: ~~~~~~~~~~~~~~~~________
        Prefix: 0001110111100010
        Suffix, stop: none
        Length of unique part of codes: 17 bits
        Pause: 4 mS
        Sleep: 50 mS
        Repeat: 1

        Sony CD Player Remote RM-D505
        Carrier: 40 kHz
        Cycles in base time period: 24
        0 data bit: ~_
        1 data bit: ~~_
        Start: ~~~~_
        Suffix: 10001
        Prefix, stop: none
        Length of unique part of codes: 7 bits
        Pause: 25 mS
        Sleep: 60 mS
        Repeat: 2
        

An IR receiver may help in transcribing the codes. Radio Shack sells the GP1U52X IR receiver/demodulator module for about $5.00. It detects 40 kHz modulated IR signals and produces a TTL and CMOS compatible signal, and comes with a data sheet. It works fairly well, but it should not be used for the initial analysis of the signals. The turn-on and turn-off times of the GP1U52X are considerably different, and vary with IR signal strength, resulting in a distorted output waveform. However, once the bit codes have been determined, they can be easily recognized in the GP1U52X output, and it makes transcription easier by removing the clutter of the 40 kHz carrier.

Driving the Transmitter

Once the function (button) codes, prefixes, suffixes, start and stop sequences, one and zero codes, and base period have been recorded, the information can be used to transmit remote control codes. Convert the one, zero, start, and stop codes into interface bit codes by determining how many interface bits will be needed to transmit each of the off-times and on-times in the codes. For each off-time and on-time, add the appropriate number of zeros or ones to the interface bit code being generated. Remember that each interface bit will take three serial port bit times to transmit, and therefore will turn the carrier on or off for three serial port bit times. Convert the prefix and suffix into an interface bit code by replacing each zero and one with the interface bit code for zero or one.

To transmit a function code, convert the function code into an interface bit code the same way the prefix and suffix were. Construct a complete code sequence by stringing together the interface bit codes for the start sequence, prefix, function code, suffix, and stop sequence. Convert this into data to be sent to the serial port by taking three bits at a time and substituting them into the correct places in a byte as described in the section on using the SIT. It may help to build a lookup table to translate the eight possible three-bit values into bytes to be sent to the serial port.

To get the SIT to work, a few other parameters may have to be recorded. Some equipment requires that a code be received more than once before it is acted on. If the SIT is functioning correctly (preferably verified by detecting its output with an IR receiver module and viewing it on a 'scope), but the transmitted codes aren't being recognized, hold down a button on the remote for the equipment and record how long it pauses between repeating codes (if it repeats at all). Then try using the SIT to send codes to the equipment multiple times, with pauses between them of the same duration the remote used. It shouldn't need more than a few repeats to make it work. The time between repeats is the pause time given in the remote data. The number of repeats required is the value given for repeat in the remote data (a repeat value of one means the code only needs to be sent once).

A pause time is given for the Kenwood remote even though it only requires one repeat because for some functions (volume up, volume down, etc.) it may be useful to simulate a continuous button press. The Kenwood remote only sends a code once, and then sends a button pressed code until the button is released. However, repeatedly sending the code for the button has the same effect.

Another parameter that may be important is the length of time that must pass with no code being sent before a new code can be sent and be recognized as a new button press. This information will be needed to automatically send multi-function sequences. Determine it by experimentation. This is the sleep time given in the remote data.

Finally, check all of the codes by sending them to the equipment. If they were recorded manually, some of them may not work due to errors in transcription and will need to be re-recorded.