Wednesday, November 26, 2014

New Firmware for the IR Trigger

Some days ago I posted an article about a RC-1 clone infrared remote trigger for Canon SLR cameras. You can find it in this link.

The design included a quick and dirty firmware developed using Energia, an Arduino like environment for the MPS430 MCUs. This firmware was enough for testing most of the hardware but it could be improved. Mainly:

  • It didn't used the 32768 Hz watch crystal
  • It didn't used the resistors included to measure the battery voltage
  • It consumed 3.2mA in idle state so it was not efficient at all
Before talking about the code I should comment that there were a pair of errors in the schematic of the previous article. There are two changes that are indicated in blue in the following figure: The 22k resistors to measure the battery voltage were at incorrect pins. When soldering the components I changed the pins on the fly to ease the connections and I forget to update the schematic. In the same way the resistor and IR LED diode are swapped to ease, also, the connections.

IR Trigger Schematic v1.4

GCC Firmware

The new firmware was developed on the Portable MSP320 Environment I set up some days ago. The Texas Instruments sponsored Red Hat MSP430 GCC I used is a mixed bag. On one hand it provides an easy setup and an up to date selection of MCUs but on the other hand is not fully compatible with previous MSP430 code I developed for the MSP430 GCC at Sourceforge

The firmware code is distributed in three files:

This file includes some macros to ease the acces to bit fields on the MCU hardware registers.
I developed this file long time ago but I needed to do some modifications for this project due to the change of toolchain. Due to that, it is not guaranteed that all this file works in a particular toolchain.

This is the main file for the firmware. It practically contains all the code. It also includes some test code not used in the final firmware but that was left  behind.

This is the makefile that coordinates the build of all the firmware.

The code starts stopping the Watchdog and configuring the I/O ports. In particular it is very important to leave guarantee than there is no I/O floating as they will ruin the low power figures. In order to tie the unused lines to GND, the pull-downs are enabled on these lines.

Next, the 32768 Hz ACLK clock is configured and set as SMCLK. Then the main DCO clock is configured to operate at 16MHz using the Flash stored factory calibrated values.

After that, the push buttons SW1 and SW2 are configured to generate an interrupt when pressed. The configuration ends with the Timer0A that is connected to the 32768 Hz ACLK as input and associated with a capture interrupt RSI.

At the end of the initialization the red LED gives two blinks to indicate that the system is ready to operate.

After the initialization there is an infinite event loop. There are two possible events, each one associated to a function. If there is no event to process, the system enters in deep sleep LPM4 mode.

The Port 1 RSI associated to the pushbuttons generates the two possible events and gets out of LPM4 mode if needed so that the main event loop can process them.

As it was indicated there are two kinds of events. The SW1 button generates Normal Trigger Events that sends through the IR LED the signal that makes the camera shoot immediately. The SW2 button generates the Delayed Trigger Event that sends a similar signal that makes the camera shoot with a 2 seconds delay.

The signals associated to each event are composed on two 32768 Hz 16 cycles square wave bursts separated with some delay. That delay is used by the camera to identify both signals. The Normal Trigger signal has both bursts starts separated 7.82ms whereas the Delayed Trigger signal uses a 5.86ms separation.

The signals associated to those events are generated with an state machine associated to the Timer. An ISR execution associated to the Capture channel 0 of the Timer 0 provides the change from one state to the following one. The entry point to the state machine for the Normal Trigger Event is the Normal First Burst (NFB) state that connects the ACLK to the P1.4 pin during 16 cycles. After the state times out, the following Normal Delay (ND) state waits during 240 clock cycles. Then the Second Burst (SB) state outputs the second burst of 16 clock cycles to the IR LED. That ends the state machine for the Normal Trigger.
There is a sencod path in the state machine for the Delayed Trigger signal that starts with the Delayed First Burst (DFB) state. The only difference is this path is the second Delayed Delay (DD) state that is 176 cycles long instead of the 240 cycles associated to the ND state.
To provide some security against random errors, any undefined state goes to the NONE estate that stops the machine and also the associated timer.   

Timer State Machine

The use of an state machine is an efficient way to sequence the operations associated to the generation of the IR signal. At the start of the first state NFB, the SMCLK clock is sent to the P1.4 pin, the Compare register TACCR0 is set to 16 cycles in the future and the timer counter TAR is started in countinuous up mode.

Timer 0 TAR evolution and States
When the TAR counter reaches the TACCR0 value, an interrupt is generated. That changes the state from NFB to ND. The P1.4 pin is disconnected from the SMCLK clock and the TACCR0 Compare register is set 176 cycles in the future. When TAR reaches the 256 cycle mark a new interrupt is generated giving start to the SB state. A new burst is generated and TACCR0 is set 16 cycles in the future. Finally, at the 272 cycle mark, we enter in the NONE state where the burst ends and the TAR timer counter is stopped. 


I have made some measurements to test the operation of the system. The following image shows the voltage at the IR LED diode during the first burst. We can see that there are 16 pulses.

Burst signal at the IR LED

To measure the clock frequency we can zoom in the burst pulses at the LED. We can see from it that the period is 30.6us so that the frequency is about 32680 Hz. As the start of the signal is not synchronized with the clock, the first pulse is not equal to the rest. In practice this is not a problem but, if it were, we could add another state in the machine to synchronize the burst start.

Burst pulse detail
The following figure shows the IR LED voltage for the full signal in normal non delayed camera trigger mode. We can measure a 7.81ms delay time between the start of both bursts. This is just the desired value.

Normal Trigger Full signal
In the same way we can see that the delayed mode trigger features a 5.86 ms time between the start of the two bursts. So everything is ok.

Delayed Trigger Full signal
The above signals indicate that the IR LED has a non zero offset voltage. This is true but it doesn't affect its current. As the IR LED is a diode, it features an exponential relationship between its voltage and its current so by the time its voltage falls below 1V  the current is practically zero.

To test the real current on the diode we can measure the voltage on the current limiting 6.8Ohm resistor that is in series with the LED. We can see that the peak pulse voltage goes from 560mV at the start of the burst to about 470mV at its end. That means that the peak current goes from 82mA to 69mA. We planned for 100mA current and we could lower the current limiting resistor to increase the current, but in the end the CR2032 battery that powers the system could produce system resets due to the fall in the supply during the bursts.

Voltage at 6.8 Ohm resistor

Idle current

One of the most important drawbacks in the Energia firmware was the 3.2mA idle current. Using the GCC firmware we can use the low power LPM4 mode to significantly reduce this current.
From the information provided on the MSP430G2553 we know that the LPM4 current can be as low as 0.1uA.

Low Power figures in the MSP430G2553
Going to currents as low as that is not easy. 0.1uA at 3V means an equivalent resitance of 30 MOhm. Just touching the battery terminals will give a much greater current. That means that we must take care that no current in wasted during the sleep time. As we have commented, all unused pins are tied down to GND using the integrated pull-down resistors. That includes the port 3 lines that are not used in the DIP20 package.
Using this method I obtained in practice the datasheet indicated value of 0.1uA for the typical scenario at 25ºC as you can see in the image below. 0.1uA  is so low that we don't need to power down the circuit at all as the battery will live ages with that current.

0.1uA current at LPM4 mode

Power supply measurement

The firmware also includes a measurement of the power supply after each signal sent. The ADC uses the 1.5V internal reference because the 2.5V one cannot be used below 2.8V. That means that our resistor divider used to measure the supply will get just the maximum 1023 10 bit count at 3V. The system detects the low voltage condition when the voltage falls below 2.6V, that means that the voltage at the divider is 1.3V so that the ADC gives about 890 counts.

The firmware lights the red LED during 400ms after each transmited signal. When it detects a low battery voltage condition the LED is not turned on so that the user can see that the battery is nearly depleted.

Last words

That's all for now. The code currently ocupies about 2500 bytes with no optimization and with debug enabled. Disabling the debug and turning on the compiler optimizations its size falles to about 2000 bytes. That leaves a lot of room for future firmwares improvements as the MSP430G2553 features 16KB of flash memory.
In fact, the project could be developed in a smaller MCU but given the price differences in the MSP3250G budget line at low volumes there is little to gain in costs selecting another MCU.

Gist Update (30/11/2014)

Thanks to Gist, now the code, with syntax highlighting, is now included inside the blog entry.

Code on Github (11/02/2018)

This new firmware and the old energia one are now on Github:

No comments:

Post a Comment