Design q's: LSM303 sleep-to-wakeup, and inertial interrupts

I’m using a LSM303 and Baby Orangutan in a battery powered digital compass project, and would like to use the “intertial interrupt” feature to avoid needing a power switch.

It seems I should be able to do this by:

  1. configuring the LSM303 sleep-to-wakeup (to wake the sensor) and inertial interrupts (to wake the uC)
  2. sending the the LSM303 and then the uC to sleep after some idle period

I’m having trouble discerning exactly how to set this up from the LSM303 datasheet, is there any tutorial or library that handles this part of the LSM303?

My notes thus far, with q’s aplenty:

Waking the sensor
The LSM303 inertial and magnetic sensors are separate, and section 4.3 only mentions sensing acceleration when sleeping, so I presume it’ll not wake on magnetic field change (which is fine for my application)

The accel. sensor power modes include: power-down, “normal”, and a number of low-power modes (slower update rates); I’m unclear as to what mode the device should be put to enable the wake-from-sleep aka sleep-to-wake feature. The process below is what I extracted from the datasheet’s 9.1.1 CTRL_REG1_A and 9.1.5 CTRL_REG5_A, and 9.1.12 INT1_CFG_A:

So seems like when setting up and entering sleep, I need to:
a) turn off the mag sensor: set MR_REG_M:MD0 and/or MD1 (mode select) to 1
b) configure the acceleration sensor: with say a “normal” update (Output Data Rate) of 50 Hz (CTRL_REG1_A: PM=001; DR=00), I’d just have to set TurnOn bits of CTRL_REG5_A to 11 to go into sleep mode?
(an alternate reading suggests I’d set CTRL_REG1_A:PM=010 to go into a low-power mode, and then do CTRL_REG5_A:TurnOn ?)

I’d also need to configure INT1_* registers to select the interrupt events and thresholds: the INT1_CFG_A register has AOI and D6 bits that together are described as “6-direction movement recognition” and “6-direction position recognition”; what’s the difference? (what does “Position detection” mean on this component, anyhow? does it doubly-integrate acceleration over time to give some displacement measure? The datasheet says zip on this.)

Waking the uC
If the INT1 pin were level shifted, it would be straightforward to connect to any pin on the uC and set a wake interrupt on that; however…
The INT1 pin is not level shifted by the Pololu carrier board, at 1.8V will be too low to register on the uC (which is running from 5V; atmega328p datasheet says V_IH = 0.6Vcc; or 3V); I’ve considered:

a) connecting INT1 to the uC analog comparator and setting an interrupt on that (ACSR / ANALOG_COMP_vect)
b) level shifting the INT1 output via a MOSFET
c) configure INT1 on the sensor to be active low, configure a uC PCINTx input with a pull-up to the uC Vcc (5V) - I believe I’ll need a ~20k resistor from the uC input to GND to limit the voltage on INT1 to under (VDD+0.1)=3.1 V

a) requires the comparator be left on and thus will use more power (how much?) than a simple pin level interrupt
b) I don’t otherwise need any external components (currently: baby orangutan, lsm303 and a 5v regulator) so introducing a single mosfet is a little awkward
c) still has an additional component, but a resistor can probably be piggy-backed on the orangutan; can I get away without this?

I also considered observing if the sensor toggles i2c state in any way when waking and trigger the uC on that - but from what I’ve read of i2c so far, the i2c master must kick off every exchange. i.e. the sensor will be mute via i2c until instructed by the uC (right?).


Hello, Ben.

We haven’t really tested the sleep-to-wakeup and advanced interrupt features of the LSM303, but what you are trying to do seems interesting and sounds like it might work. My responses to your questions are below:

I think your “alternate reading” is the correct one. My understanding is that you start with the LSM303 in a low-power mode and enable sleep-to-wakeup, and then when something triggers an interrupt, it kicks the chip back into normal mode.

I agree that the datasheet has a frustrating lack of information about certain details. The datasheet for the LSM303DLHC has a little explanation for the 6D bit on page 30, but it is still a little cryptic. However, I found an app note for a different ST accelerometer that seems to have a much better explanation on page 27-29, and it probably applies to the LSM303 as well. To summarize, it sounds like “6D movement recognition” triggers momentarily when the sensor arrives at a particular orientation, while “6D position recognition” triggers and stays active for as long as the sensor remains at a particular orientation.

There might actually be a fourth solution if you are using an LSM303DLM (not an older LSM303DLH). The carrier board for both chips is the same, with both a 3 V regulator and a 1.8 V regulator, since the LSM303DLH required both of those voltages. However, the LSM303DLM should be able to run off a single 3V supply, and there might be a way to bypass the 1.8 V regulator and supply 3 V to VIO instead, which would make the interrupt pins 3 V as well. I can look into this tomorrow if you are interested.

Right, the master always has to be the one to initiate an I2C transfer.

- Kevin

G’Day Kevin,

Re. DRDY, INT1,2 interrupts: I do have the LSM303DLM. The datasheet (Table 4) notes that Vdd_IO max is Vdd+0.1, where Vdd max is 3.6V (fixed 3V on the pololu carrier). Is 3.1V sufficient to reliably register as a high on the atmega328p? (my expectation: it would probably work most of the time, noise immunity would be compromised). Is it possible to disable the onboard regulator and connect VIO to VDD? (my expectation: not easily, without cutting fine traces / desoldering the reg).

Also, with Vdd_IO max of 3.1V, when the INT pins are configured as open drain and an external pullup to 5V (e.g. the uC’s internal pullups), that would seem to violate this limit. Configuring as push-pull would still see current into the port on high, which might also be an issue?

At present I have a simple BJT common emitter buffering each output, which seems to work fine. I might just stick with that, but I’d appreciate any thoughts on the above from an educational perspective.


To follow up on the inertial interrupt stuff: after reviewing the LIS3DH data sheet info, I tried various values for the INT2_THS_A threshold and INT2_DURATION_A duration, and found that I could only get a useful response with a very narrow range of values: I could never get any remotely useful trigger for:

  • any threshold when duration was above about 2 or 3 (no interrupts at all)
  • any thresholds above 100 (no interrupts at all)
  • any thresholds below 80 (continuous interrupts at the ODR)

With a threshold of 80 and duration 2, I got a “few” (2-10) interrupts when bumped hard.

(this is with an ODR of 50Hz, and the “6D” stuff in INT2_CFG_A:AOI set to 00, “position or movement”; pretty much per the LIS3DH’s example in section 6.3.2.)

The resolution on duration particularly is useless for determining when the device is “idle” (has been put down and no longer being handled).

The above seems consistent with the LIS3DH data sheet, in that at an ODR of 50Hz, each unit of duration is 20ms. i.e. in order to trigger an LSM303, an event would need to last at least 20ms

I’m going to try the approach of simply having the uC waking periodically and sampling the orientation to see whether to go back to sleep or begin operating.

In response to your second post, it looks like the minimum input high voltage for the ATmega328P is 0.6Vcc, or 3 V, when it’s running at 5 V. That means a 3 V or 3.1 V signal would be right on the threshold, so it might work, but maybe not reliably.

A nice solution for you would be to supply 3.3 V to both Vdd and Vdd_IO, but as you expect, the safest way to do this involves desoldering both of the existing regulators, which would be difficult unless you have some surface mount rework equipment. Unfortunately, I don’t think there’s a good place to cut traces to disconnect the regulators from the circuit without removing them.

Thanks for sharing your findings about the inertial interrupts. Will your device always be put down in the same orientation (e.g. always with the Z axis pointing up and down), or could it come to rest on its side, at an angle, etc.? If it will always be the same, you might be able to simplify things by just setting up an interrupt to trigger if the Z acceleration differs a lot from 1 g.

- Kevin