Since we received our Photon several months ago it has been difficult to find a working example of Hardware PWM on the Photon. Initially, we ported our softPWM approach to the Photon, which is excellent. However, we figured it must be possible to use at least one of the spare UARTs on the Photon to achieve our goal. So first we started prototyping on the Arduino and quickly got a working example with some limitations – only 40 kHz and 33 kHz carrier frequencies were possible with the UART without delving into the registers a bit more. Then we moved the code over to the Photon, leveraging our previous softPWM examples, upgraded with the Arduino code – EUREKA! The Backdoor uPWM Hack on Photon for Infrared signals.
The Hack
Quite simple really – just set the baud rate to 10 times the desired Infrared carrier frequency and send a ‘magic’ 8 bit character to achieve the correct duty cycle. Of course we need to take the 1-start bit and 1-stop bit into account plus the 8 bits in each character. Remember that the UART sends the data inverted, so this needs to be taken into account with the characters sent and also in the IR LED driver circuit above, which required 2 transistors instead of the usual one. In summary, sending the following characters will generate the associated duty cycle, as follows:
- 0xF0 – 50%
- 0xF8 – 40%
- 0xFC – 30%
- 0xFE – 20%
- 0xFF – 10%
This is more than sufficient for most IR systems, which would typically use 50% or 33%. We defaulted the value in the sketch to 40% without problems. It should of course be possible to generate a duty cycle up to 90% by extending the code, which may be of interest in non-infrared applications.
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 series and updated the PWM initialisation, mark & space routines. Using this approach it should be relatively simple to finally port libraries like IRremote & IRlib to Photon and get some awesome IR projects going at last! If you need any advice contact us via the website above.
One of the real benefits of this approach is that there is no interference with any of the Photon’s “Cloud foo” or RTOS – which I suspect is the reason there has been no usable PWM for IR to date. Of course this approach should work with any MCU with a fast clock. Unfortunately, the 16MHz of the Arduino just isnt fast enough to get anything other that 40 or 33 kHz. We may look into playing with with the UART’s registers to achieve better performance on AVRs, using this approach, down the road.
To test the uPWM, we wired up the Photon to the circuit above and used our soon to released LearnIR 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.
The Circuit
The circuit diagram above takes the inverted IR signal from the UART’s TX pin on the Photon and inverts it back to normal with the first transistor stage. The second transistor stage drives the IR signal at 150 mA using a 22R resistor. You can get 100mA using a 33R resistor and so on. There is also a superior constant current circuit available on our blog, but you will have to design in the invert stage.
You can download a copy of the Firmware for the Photon below.
Get your own copy of AnalysIR here