Skip to content
Kris Winer edited this page Oct 4, 2021 · 27 revisions

Wake-on-motion for ultra-low-power portable/wearable devices

By Kris Winer, Tlera Corporation

October 1, 2021

Motion detection via low-cost MEMs sensors has many applications including navigation and absolute orientation estimation, presence detection, and vibrational analysis to name a few. We are all familiar with functions embedded in our smart phones like compass, landscape/portrait orientation detect (changes the display orientation) and free-fall detect (turns off the smartphone when dropped to minimize damage to the electronics). These are all made possible by inexpensive MEMs sensors embedded in every smart device. There is one other smart device feature everyone uses but not everyone knows in detail how it works: wake-on-motion.

The rationale behind wake-on-motion functionality should be obvious. Smart devices run on batteries. In order to maximize time between battery charging it is desirable for the device to remain in a low-power state whenever it is not actively being used. As long as the device is in motion, the rationale goes, the user is probably actively using it. If the device sits "motionless" for long enough, the assumption is made that the user is doing something else and the smart device can safely power down until needed. The sensitivity to motion is usually accomplished by using an accelerometer that detects motion above an acceleration threshold for wake/sleep transitions and a timer to determine when motion has stopped and/or started. For smart phones, there are additional use cues including device orientation, light level, etc. to determine if the phone is simply in someone's pocket (not in active use) even though the device might be moving through programmed motion thresholds. So practically, how does wake-on-motion work?

For the simplest use case, we will assume that we are interested in a battery-powered (wearable or portable) device. Let's further assume that the device has a low power host MCU like the STM32L432, which manages several slave sensors and a slave radio modem. We have designed dozens of different devices with this same basic architecture. The STM32L432 is an excellent choice for small wearable devices since it is only 5 mm x 5 mm, has enough GPIOs and serial peripherals to manage several slave sensors and a radio, has an excellent memory- and power-efficient Arduino core, and uses just 1.65 uA in STOP mode with RTC and full memory retention. The well-written Arduino core closes gaps and cures race conditions typical of the ST HAL, and works around all errata allowing sophisticated device firmware to be built quickly with just a few hundred lines of C++ for easier maintenance, extensibility and portability.

Spectrometer AS7265X spectrometer using STM32L432 host and BMA400 as wake-on-motion watchdog accelerometer.

Standard practice for ultra-low-power applications is to manage all sensors and slave devices through one or more interrupts. The interrupt handlers are designed to do just one thing: set a Boolean flag, which avoids timing collisions no matter how many devices are present. Then the main loop simply checks for any flags that are true, resets them to false and then manages that device: reads and processes data, stores data to memory device (SD card or flash), or sends a message via radio, etc. The main loop ends with a call to put the STM32L432 into STOP mode. This way, unless the host MCU is actively responding to a sensor data ready or timer interrupt, etc it waits in its lowest power state. Furthermore, it is usually possible to run portable/wearable applications at 4 MHz MCU clock speed so that even when the STM32L432 is actively managing the device, it is using much less power than at the full 80 MHz clock speed.

It is often the case that we want to minimize power usage in portable/wearable devices even further. And we would use the same method described as wake-on-motion for smart phones. When the device is "motionless" the MCU will suspend or disable radios and sensors, detach interrupts, enter STOP or STANDBY power modes and wait for a "wakeup" signal to resume operations. In practice, we use a "watchdog" accelerometer for this purpose. It alone remains "awake" with an interrupt that alerts the host to motion in STOP mode or wakes the host from STANDBY mode. In fact, we usually use an accelerometer with two separate interrupts; one for wake-on-motion and one for sleep-on-no-motion functionality.

We have been using the BMA400 for the last few years for this purpose. Unique among available accelerometers until recently, the BMA400 has a low-power mode that runs at 25 Hz sample rate and uses just 800 nA. When the BMA400 detects motion above a user-programmable threshold, it sends a "wake" interrupt to the host. Similarly, when the motion persists below the threshold for a user-programmable duration, the BMA400 sends a "sleep" interrupt to the host. The BMA400 is currently out of production and all but unavailable. Fortunately, there are at least two promising replacement candidates currently available: the MC3635 and the LIS2DW12.

LIS2DW12 LIS2DW12 breakout with (a dusty) Ladybug (STM32L432 Development Board)

We have evaluated both these replacement candidates (see MC3635 and LIS2DW12). The MC3635 offers a "sniff" mode which allows "wake-on-motion" functionality at a cost of just 0.3 uA at 7 Hz sample rate. The MC3635 works as advertised. However, we prefer the LIS2DW12 for three reasons: 1) the LIS2DW12 has two interrupts and the MC3635 only one, 2) the LIS2DW12 documentation is better and, therefore, the LIS2DW12 is easier to use, and 3) the LIS2DW12 has "stationary" mode. So we will limit further discussion to how to use the LIS2DW12 and why "stationary" mode is so useful.

Like most MEMs accelerometers, the LIS2DW12 offers embedded activity/inactivity detect functionality. This is activated in the LIS2DW12 by enabling sleep detect (setting bit 6 in register LIS2DW12_WAKE_UP_THS), setting a wake threshold (31.25 mg resolution at 2 g full scale), and setting activity/inactivity times in register LIS2DW12_WAKE_UP_DUR as follows:

`

// enable sleep detect (bit 6), set wake threshold 1 LSB = 1/64 of full scale
_i2c_bus->writeByte(LIS2DW12_ADDRESS, LIS2DW12_WAKE_UP_THS, 0x40 | 0x02); //  62.5 mg threshold for wake on any axis, n x 31.25 mgs at 2 g FS

// wake-up from sleep duration (bits 5-6) * n/odr, at 25 Hz max is 4/25 = 0.16 s
// inactivity delay before sleep (bits 0 - 3) 512*n/odr, at 25 Hz, 0 is 0.64 s, 1 is 20.5 s, max is 327 sec
_i2c_bus->writeByte(LIS2DW12_ADDRESS, LIS2DW12_WAKE_UP_DUR, 0x40 | 0x01);  // set inactivity delay before sleep to 20.5 s at 25 Hz odr

`

You can see the full sketch and further details here.

The way this works is that the accelerometer runs at whatever sample rate and in whatever power mode the user sets for the active or "awake" state of the accelerometer. This could be 400 Hz, HIGH_PERFORMANCE mode in order to allow single- and double-tap detect, somewhat lower performance, say, 25 Hz and LowPowerMode 4 to enable orientation (landscape/portrait) change detect, etc. When the motion drops below the user-set threshold for longer than the user-set time (62.5 mg for 20.5 seconds as above), the accelerometer automatically enters whichever low-power mode the user had previously selected at a fixed 12.5 Hz sample rate. Depending on the low power mode selected, the accelerometer power usage when in this "sleep" state will be between 1 and 4 uA. Thus the accelerometer can function at whatever level the user requires in the wake state, detect a "no-motion" transition, alert the host MCU via interrupt and then drop automatically into a low power state. Furthermore, the accelerometer can detect a "motion" transition, alert the MCU host via interrupt and automatically return to the previous power state and sample rate. Once configured via the two registers above, these transitions occur automatically which simplifies power management for the host firmware.

But there is another trick that the embedded activity/inactivity recognition engine can do that can be very useful for ergonometric and other motion analyses. The embedded 32 sample FIFO (First In First Out) buffer can be used to continuously store data samples while the accelerometer is in its low-power "sleep" mode. When a "wake" event causing an interrupt occurs, the FIFO will automatically switch from continuous mode to FIFO mode and stop collecting data when the FIFO is full. In this way, a 32-sample record of the acceleration history (~2 seconds with settings above) of the wake event can be captured for later analysis.

The wake-on-motion and sleep-on-motion functionality provided by the embedded activity/inactivity engine as described costs about 1.5 uA @ 3.3 V in LPMode1 as we measure it. This is about twice what the BMA400 uses and 5x higher than the MC3635. If this were the end of the story we might be tempted to spend more time getting to know the MC3635. However, the LIS2DW12 has one more feature that can cut this power cost by about 3x. This is stationary mode, which is part of the Android motion sensor specification. By setting LPMode 1, the sample rate to 1.6 Hz (lowest), and setting one bit in register LIS2DW12_WAKE_UP_DUR as follows:

`

// enable sleep detect (bit 6), set wake threshold 1 LSB = 1/64 of full scale
_i2c_bus->writeByte(LIS2DW12_ADDRESS, LIS2DW12_WAKE_UP_THS, 0x40 | 0x02); //  62.5 mg threshold for wake on any axis, n x 31.25 mgs at 2 g FS
// wake-up from sleep duration (bits 5-6) * n/odr, at 1.6 Hz max is 4/1.6 = 2.5 s, set to 0.625 s
// inactivity delay before sleep (bits 0 - 3) 512*n/odr, at 25 Hz, 0 is 16/odr, 1 is 320 s, set to 10 s
// set stationary bit 4
_i2c_bus->writeByte(LIS2DW12_ADDRESS, LIS2DW12_WAKE_UP_DUR, 0x20 | 0x10);  // set inactivity delay before sleep to 10 s at 1.6 Hz odr

`

an average accelerometer power usage of 0.55 uA @ 3V3 can be achieved whether in sleep or wake mode. This is because stationary mode is identical to activity/inactivity detect except that the power mode and sample rate are not changed from wake to sleep mode. This means the user can set the accelerometer to the absolute lowest power setting and the MCU host can get wake-on-motion and sleep-on-no-motion interrupts as before when the user-programmed thresholds for motion and timing are crossed. Since the sample rate is now 1.6 Hz though, there is a lot less flexibility in the timing i.e., time-to-sleep is either 10 seconds, or 320 seconds, or larger.

Now you might be asking yourself, "What is all the fuss over one uA here...?" Well, it is true that for many applications where the total device sleep current might be ~10 uA, whether it is 9 uA or 11 uA probably doesn't matter too much. However, if a device is intended to be deployed remotely and last for months or years between battery charges/changes, then 1 uA is ~9 mAH per year and for some applications this might matter.

At least the user has a choice. For pure wake-on-motion/sleep-on-no motion functionality at the lowest power cost, LIS2DW12 stationary mode is the way to go. For full embedded functionality when awake with automatic fall back to a low power sleep state, the standard activity/inactivity detection works well. Either way, the LIS2DW12 makes a pretty good watchdog accelerometer!

Clone this wiki locally