In this blog post we follow up on our recent article about generation of infrared PWM from the Photon’s UART where we suggested that it may be possible to achieve something similar with the Arduino. In our previous attempt the Arduino was only able to generate PWM at 40 kHz and 33 kHz using the same approach. After some investigations we discovered a new approach which provides an even better set of results using the Arduino’s USART. Yes, we were able to generate 30, 33, 36, 38, 40 , 56 and surprisingly the illusive 455 kHz which was not possible on the Photon (using this approach). Read on for the details. Readers should also study our original series of articles on ‘softPWM‘ for a better understanding of the source code which can be downloaded below.
The reason for this ‘hack’ is to provide an IR carrier for sending IR signals when all of the other AVR’s timers are used for other purposes. Of course the normal serial Tx & Rx pins will not longer be available after startup is completed. The code should run as is on the Arduino UNO, Duemilenove, Nano, Pro Mini or any clone running an AVR Atmega328p. It should be relatively simple to customise for other AVRs, provided they have USART support.
The Hack
The same approach used in the original Photon hack will not work for Arduino as the required baud rates are not achievable, with acceptable accuracy, via the USART clock subsystem. However, after a quick examination of the ATmega328P’s data sheet and pin-out in more detail we confirmed that it is capable of exposing the USARTs baud rate clock on the XCK pin or digital pin 4 in Arduino-speak. XCK can be used as an input or output clock pin for synchronous serial communication (vs the more common asynchronous method which effectively has the clock preset or embedded with the data edges). Setting Pin 4 as output places the BAUD rate clock on this output pin. After some initial adjustments to the registers on the the AVR chip were were generating PWM across all of our desired carrier frequencies including 455 kHz. The 455 kHz signal is actually 444 kHz which is more than good enough for 455 kHz Infrared receivers. We also decided to disable the Rx pin for the USART and this can now be re-used as a general IO pin. So for now we are using the Tx pin (D1) & Pin 4. The Tx pin is effectively redundant.
To generate the IR marks & spaces we just enable or disable the synchronous clock via the AVR’s registers in the mark function.
As the Baud rate clock is internally generated the only duty cycle available is 50%, which is acceptable and does the job well.
The Code
I will leave it up to the reader to review the code and figure the rest out. Suffice to say we took the softPWM code in part 3 of the softPWM series and updated the PWM initialisation, mark & space functions. Using this approach it should be relatively simple to update libraries like IRremote & IRlib to get some awesome IR projects going! If you need any advice contact us via the website above.
One of the real benefits of this approach is that all of the AVR’s timer peripherals remain free for other uses, but at the expense of serial communications and some IO – 2 pins in total.
To test the uPWM, we wired up the Arduino to the circuit above and used our soon to released LearnIR and A.IR Shield connected to AnalysIR to record the signals. As you can see from the screenshot of AnalysIR all test signals were received, decoded and at the correct carrier frequencies of 30, 33, 36,38,40 & 56 kHz. Unfortunately we didn’t have time to set up a 455 kHz IR receiver but we can confirm that these signals were perfect when viewed on our oscilloscope.
Backdoor uPWM Hack on Arduino for Infrared signals using UART.
The Circuit
The circuit diagram above takes the IR carrier from the UART’s XCK pin (D4) on the Arduino and feeds it through a resistor to the base of a simple transistor driver circuit. You could opt for an improved driver circuit as explained in our earlier constant current blog post.
We also tested another approach using a PCINT interrupt on pin 4 to toggle other pin(s) for the complete IR carrier signal output. While this approach works fine, it uses a lot of extra resources in the ISR processing, so we settled with the circuit shown above for our example. The PCINT approach would not work with a 455 kHz signal due to the processing overhead.
The transistor stage drives the IR signal at 150 mA using a 22R resistor. You can get 100 mA using a 33R resistor and so on. We just used a 1k resistor for the base of transistor, but a 2K2 or 4k7 resistor should also do the job.
You can download a copy of the Firmware source code for the Arduino uPWM hack here.
Get your own copy of AnalysIR here