SuperDuplex: An InfraRed Bootloader for Arduino…



NoMi Designs implemented an optical infrared Arduino bootloader based on the common 38kHz infrared remote modualtion.  Using the Asuro as inspiration, our bootloader goes a step further in that it works seamlessly from within the Arduino IDE, utilizing the STK500V2 protocol without modification.  
As described in detail below, due to hardware specifics and a low carrier frequency, the maximum data rate is 4200 baud and in practice about 4k baud reliably without error.  While not amazingly fast, this results in about 1 min 30 seconds to transfer a moderately large Arduino sketch of 20kb.  With the sketch loaded, the IR hardware also functions as a bidirectional half duplex serial link.  As itemized in the following list, the project as a whole is the sum of it’s parts:
  • Echo Cancellation Simplex
  • Continuous Demodulation
  • Demodulator Phase Delay
  • USB Transceiver (Software)
  • USB Transceiver (Hardware)
  • Arduino IR Transceiver
  • Arduino Bootloader
  • Board Specifications
Echo Cancellation Simplex
If you’ve ever talked to someone on speakerphone and heard your own echo, you can understand the confusion this creates.  This is the issue when adapting the normally full-duplex USB converter to infrared communication, while transmitting the reflected infrared bitstream is also being heard and it stuffs up the receive buffer like a bad head cold.  To make the bootloader work seamlessly with the Arduino IDE over modulated infrared, full duplex serial operation is blocked, this is achieved on both sides with software and/or hardware.
Continuous Demodulation
Almost all infrared receivers found in home appliances have an automatic gain control (AGC) circuit to account for variations in signal strength as well as ambient interference from fluorescent lights.  If your lucky, the datasheet for the part will state the maximum duty cycle for data transmission before the AGC normalizes the signal and kills the output.  From testing it appeared to be less than 5%, which is much too low to send appreciable amounts of data within a reasonable time frame.Ideally we want the AGC to allow a bit over 50% or no AGC at all.  Infrared demodulators without AGC are not common but thankfully, they do exist.  Besides being specifically purposed for high volume data transmission, they also find use in sensing and light barrier systems.  A couple of these devices are the TSOP58038 and the TSOP4038 from Vishay.
Demodulator Phase Delay
To reject ambient noise, the infrared data is modulated with a 38kHz carrier frequency, a digital one is represented as a tone and a digital zero as no tone.  When the demodulator sees the correct carrier frequency,  it outputs a digital one.  Inside the demodulator, the detection process is implemented in analog as a band pass filter and requires about 7 carrier waves to pass before it reports on the output.  It is this requirement that introduces as phase response delay of about 200 microseconds and which can be seen in the following signal capture of the transmission “Hello World”: The red signal is the 38kHz modulated send and yellow is the demodulated receive signal.  The received signal is phase shifted right a full bit width (200us), resolution is at 1ms per division.
USB Transceiver (Software)
For simplicity the computer side transceiver was first implemented in software with a spare Arduino and an IR shield.  A 120 ohm resistor is used to hold the Arduino’s reset pin high, preventing the transceiver from resetting.  It’s implemented using pinChange interrupt as a bit bang pass though, with the condition that when transmitting, the receiver is ignored.  As TTL serial signals are active low and the IR LED is active high, the transmission component is inverted.The Arduino, the IR shield and the logical truth table to make sense of it all.
USB Transceiver (Hardware)
Once the transceiver was proven in software, the design was moved into the hardware space.  This presented a couple of challenges in that the aforementioned phase delay made a logical OR difficult.  The solution was to implement a similar or longer delay on the TX line OR input.  As can be seen in the following schematic, this is implemented with a 100nF capacitor and 4k7 resistor, click for pops:  
The phase delay arrangement turns on quickly and turns off slowly,  adding about 2 milliseconds to block the receiver while transmitting using a bit of transistor logic.  As the signals are active low and the TX line is inverted, the gate function required for RXD is the logical OR between inverted TX and the demodulator output (refer to truth table for clarification).
Arduino IR Transceiver
On the Arduino side, all that is required for additional hardware is a demodulator and an IR LED, this makes for a very cheap Arduino sans FT232R converter.  The demodulator is connected directly to the Arduino UART receiver (Pin 0).  The IR LED connection takes inspiration from the Asuro bootloader, the LEDs anode is fed with a 38kHz PWM from Pin3 while the cathode is connected to Arduino Pin1, the UART Transmitter.  As TTL serial is active low, the LED lights with the 38kHz carrier when commanded by the UART.This schematic has been setup on a bread board Arduino, the basics which have been detailed in the previous post here: http://n0m1.com/2012/04/30/how-to-bread-board-arduino/
Arduino Bootloader 
The existing bootloader was modified for half duplex by turning off the receiver while transmitting, 38kHz PWM was setup and some delay was added to handle the phase offset of the demodulator.  Prior to making changes, some effort was required to successfully compile the bootloader as documented here: http://n0m1.com/2012/04/01/how-to-compiling-the-arduino-bootloader/
When uploading the IDE checks for the existence of the bootloader, so the hex, source and makefile need to be in the folder here: arduino-1.0\hardware\arduino\bootloaders\IRbbArduino\.  The source, hex and makefile can be downloaded here: IRbbArduino.
Board Specifications
The final bit of the puzzle is to let the Arduino IDE know who we are talking to.  We add a few lines of text to the end of the boards.txt file in \arduino-1.0\hardware\arduino\.  As seen below, it defines who, what and how we are talking.  The IDE must be restarted for these changes to apply:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
##############################################################
bbArduino.name=BreadBoard Arduino328 16MHz w/IR Bootloader@2400
bbArduino.upload.protocol=arduino
bbArduino.upload.maximum_size=30720
bbArduino.upload.speed=2400
bbArduino.bootloader.low_fuses=0xc6
bbArduino.bootloader.high_fuses=0xdd
bbArduino.bootloader.extended_fuses=0x00
bbArduino.bootloader.path=IRbbArduino
bbArduino.bootloader.file=ATmegaBOOT_168_atmega328ir.hex
bbArduino.bootloader.unlock_bits=0x3F
bbArduino.bootloader.lock_bits=0x0F
bbArduino.build.mcu=atmega328p
bbArduino.build.f_cpu=16000000L
bbArduino.build.core=arduino
bbArduino.build.variant=standard