Cornell University ECE4760
for Atmel Mega644/1284 microcontrollers
Infrared (IR) can be used for line-of-sight communications over low to moderate range. IR is nice because of the lack of interference (except for sun and compact fluroscent lights) and freedom from FCC regulation. The web site http://tthheessiiss.wordpress.com/2009/08/05/dirt-cheap-wireless/ (Jacob Sikker Remin, 2009) shows how to use a IR remote control receiver and IR LED to send ASCII serial data in a simple, but unreliable, fashion with no error control, packitizing, or other overhead. The transmitter drive uses a clever method to modulate and invert the serial output from the USART transmitter. The circuit is shown below. In my version, MCU timer 2 is used standalone to generate a 56 KHz square wave on pin D7. A lower resistor gives more range, but of course draws more current. The TSAL6400 can take 100 mA forward current, but the maximum current rating for any port pin of the MCU is 40 mA. You should probably limit the current to 30 mA. At 30 mA, the forward voltage drop of the diode is about 1.25 volts, so the the resistor needs to be
(2.5 volt)/(0.03 amp)> 83 ohms.
I improved Remin's protocol by setting up the link software so that timing constraints on the IR receiver AGC were guaranteed to be met. It turns out that there are several types of IR reciever, some of which are better at short data bursts, while others are better for sustained data. I chose a Vishay TSOP34156 for its good sustained data characteristics, minimal burst timing requirements, and reasonable data rate. The system I build works solidly at 4800 baud over IR with 5 characters of overhead/packet (start token, transmitter number, 2 char checksum , end token). It works with increasing packet loss up to 9000 baud. The receiver circuit is shown to the left. The RC circuit acts a low-pass filter on the power to surpress spike noise and improve receiver performance. The RC circuit should be close to the receiver. The range with a 100 ohm resistor is at least 3 meters with the transmitter roughly pointing at the receiver, and a packet loss of less then 0.1 percent. To manage burst length limitations there is a short pause between characters, and only 7-bit characters are sent, with two stop bits. The 7-bit limit means that you can send all of the printing characters on the US keyboard, but no extended ASCII. All data is therefore sent as printable strings, NOT as raw hexidecimal.
Programs (These programs were written for the atmega644, but also work on the atmega1284)
- The loopback test program works in full duplex mode to send a message to itself. The program assumes that the transmitter and receiver are connected as shown above, and that in D3 is connected to the line which sends data to the PC. You need to point the LEDs at the receiver, or put them side-by-side and use a reflector to bounce light back. The transmit and receive tasks are running at different rates. The transmit task just formats a string and sends it. The receive task gets a packet, then either prints it (if the return code indicates good data), or for testing, prints the nonzero return code and the corrupted packet. The hardware USART is used for the IR link, so I wrote a software UART for communication with the human at the PC. Note that on the atmega1284 this software UART is not necessary, because the 1284 has two USARTs. The software UART routines
aux_putchar allow use of
fscanf functions, but are blocking and should only be used for testing or when MCU load is light. The timer 0 interrupt service routine manages the full duplex IR link. At 4800 baud, this program puts about 430 characters/second across the IR link. Bigger packets are more efficient in a low noise environment. You could expect a maximum transmit rate of about 20 packets/sec with about 20 characters/packet.
- A two-processor link was built with one processor running a version of the loopback code, but transmitting on ID=1 and receiving on ID=2. The other processor is running an echo code, receiving on ID=1, and if the data is valid, echoing the packet back out on channel ID=2. Using this code, it is necessary to put an IR barrier (electrical tape or metal) between the LED emitter and reciever on each processor. I think this is because the light scattering from nearby LEDs sets the AGC of the receiver too high to receive the remote LED output. In the image below, you can see the IR shield around the reciever, the two LEDs at the left, and the 100 ohm resistor in series with the LEDs.
- With both transmit resistors set to 1Kohm (implying
current=(2.5 volt)/(1000 ohm)=2.5 mA), and a range of 1 meter, the packet lose is about 1/1000.
- With both transmit resistors set to 390 ohm (implying
current=(2.5 volt)/(390 ohm)=6 mA), and a range of 3 meters, the packet lose is about 1/10 and is very dependent on scattering and reflections from the full duplex base transmitter to the base receiver, both of which are active at the same time. Room illumination was bright, indirect sunlight, plus 60 Hz fluroscent lighting.
- With the base station resistor set to 390 ohms and the echo station resistor set to 100 ohms, the packet lose is about 1/1000 at 3 meters range.
- A two processor link (base code, echo code)was built with the following characteristics:
The error rate seems to be <1/1000 packets at 3 meters with same resistors as above (condition 3, example 2). With sunlight shining directly (through heat-film covered window) onto the base receiver lens, between half and 90% of the packets are lost with 3 meter range, and 100 ohms on the echo transmitter LED. Shading the receiver my hand restores low error rate.
- The base processor sends a time and packet number unless a button is pressed. If the button is pressed it sends 'zz'.
If valid, data received is sent to the puTTY window on the PC, and has an error code prepended if invalid.
- The echo processor sends back the packet it receives. If the packet is 'zz', then the echo processor zeros it's own time counter.
If no packet is received (before receive timeout expires) then the current time counter is sent back to the base formated at "RemoteTime=xxxx", where xxxx is in milliseconds.
A packet consists of :
- A start character, which defaults to '#', but can be changed with a define directive. No other character in the packet is allowed to match the start character.
- A one-character transmitter id number which the receiver will check against a number it expects. The transmitter id should be in the ASCII character range '0' to 'z'.
- An arbitrary length, printable string, which of course, must fit into the size of the defined transmit/receive buffers.
- A one character checksum, which is calculated as the bitwise XOR of all the characters in the packet (transmitter id, and payload). The checksum is actually transmitted as two 4-bit values in the low 4 bits, ORed with 0x10 to form two 7-bit characters. This seemingly roundabout encoding was necessary to avoid burst length problems.
- An end character, which defaults to '%', but can be changed with a define directive. No other character in the packet is allowed to match the end character.
Copyright Cornell University
June 29, 2012