Making a handheld prototype wake when you pick it up

A battery-powered remote should be ready when someone picks it up. Keeping its screen and processor running makes that easy, but wastes energy while it sits on a table. Putting everything to sleep creates the opposite problem: something still has to notice the next pickup.

A low-power accelerometer can watch for movement while the main processor rests. For a team turning a working controller into a handheld product, the question is whether the sensor, its breakout board and the firmware can carry that wake-up signal all the way to a usable device.

On our bench we connected a GraftSense BMA400 accelerometer module to a GraftPort-RP2040 board and configured it from MicroPython. That proved communication and sensor settings. It did not prove motion wake-up, and the reasons why are the useful part of this note.

Start with what the person expects

Imagine a handheld controller for an interactive installation. It rests quietly on a table, then lights its controls when lifted. The person cares about the time until the controls work, including any wireless reconnection, not just the time until the processor starts running.

This comes up in real project questions. An Arduino forum thread from January 2023 asks how to wake on motion, do a task and go back to sleep. Battery-powered remote designs raise the same issue from the other side: how to reconnect without an unacceptable wait.

Before choosing settings, define the intended action. Should a gentle lift work? Should a knock on the table count? What should happen while the device rides in a bag? These conditions give the engineering work something more useful than "make it sensitive."

What the BMA400 can watch for

An accelerometer measures acceleration along three axes. At rest the readings include gravity, so rotating a handheld device changes the values even without a sharp movement. The BMA400 offers ±2 g, ±4 g, ±8 g and ±16 g ranges. That flexibility helps explore ordinary handling; it does not identify a person's intention by itself.

The chip can evaluate movement internally. Instead of the main processor reading every sample, the sensor can signal a qualifying event on an interrupt pin, a wire that tells the processor something needs attention. That is the capability to look for when choosing a board for a sleeping product.

Bosch distinguishes waking the sensor into normal measurement mode from waking an external processor. The second also requires mapping the event to an interrupt output and wiring it to a suitable processor input. The BMA400 datasheet covers this in its wake-up interrupt section.

In low-power mode, movement evaluation runs at 25 Hz, a new sample every 40 ms. Threshold, reference and the number of qualifying samples decide when an event is recognized. Requiring more evidence rejects brief disturbances but also slows a wanted response. The right choice comes from handling the assembled prototype, not from copying a setting out of an unrelated example.

The communication experiment

We used I2C0 on the controller, GPIO 4 as SDA and GPIO 5 as SCL, at 400 kHz. The module takes 5 V at its connector and regulates it to 3.3 V. That is a board-level input, not permission to put 5 V on a bare sensor. An address pad selects 0x14 or 0x15, and our program scanned the bus and passed the found address to the driver, which avoids a common source of confusion when two boards are set differently.

i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
addresses = [a for a in i2c.scan() if a in (0x14, 0x15)]
if len(addresses) != 1:
    raise RuntimeError("Connect one BMA400 and check its address")

The driver package we installed is based on jposada202020's MicroPython_BMA400 (MIT, now archived). Our package's install notes named version 1.0.0 while the package actually installed was 1.0.1. Pin the exact package version when you reproduce a setup; a package name alone does not identify the code you are running.

The test program cycled through power modes, output rates, filter bandwidth, oversampling, range and data source, then printed a summary. Working through one setting at a time shows which controls belong to the sensor before you try to coordinate it with processor sleep.

Read the results as a configuration experiment

The terminal showed the sensor at 0x14 and successful initialization. It also showed a problem in the output-rate sweep: one setting raised an error, and a target value of 184 read back as 100 Hz. The driver defines its 400 Hz and 800 Hz constants incorrectly for the four-bit rate field, so those lines do not verify every supported rate.

There is a separate conversion bug in that driver. After scaling raw counts by the range sensitivity, it divides by 9.80665 to produce values labeled m/s²; converting g to m/s² needs multiplication. Do not use those acceleration numbers to set a physical movement threshold. Fix the conversion and check known stationary orientations first.

The final summary reported normal mode at 100 Hz. That is all it shows. There was no sleeping processor, no pickup event, no interrupt trace and no current measurement. The next prototype has to collect those observations directly.

The missing wake-up connection

The most consequential detail is on the module schematic: the BMA400's INT1 and INT2 pins are unconnected. The four-wire connector carries power, ground and I2C only. Reading the sensor over that connector works; sending a motion event to a sleeping processor is not possible through it.

For a wake-up experiment, choose a breakout that exposes an interrupt output, or revise the hardware to route one. Check the processor's supported wake-up pins and sleep modes before assigning the signal. The chip pinout shows where interrupt outputs exist; the carrier board decides whether you can use them.

The driver also stops at basic settings and measurements. Despite broader wording in its README, it has no wake-up interrupt configuration API. Extending it means writing the sensor's event settings, interrupt mapping and output behavior, plus firmware that enters and leaves the chosen sleep mode.

Bring those pieces up separately:

  1. With the processor awake, confirm the sensor raises an interrupt for the intended movement.
  2. Confirm the same electrical signal wakes the processor from the chosen sleep mode.
  3. Restore the display or radio and measure the delay until the product's intended action works.

Changing sensor settings, sleep behavior and wireless startup at the same time makes a failure very hard to locate.

Check the experience inside the enclosure

Mount the sensor as it will sit in the product. A loose board on jumper wires moves differently from one secured inside a remote. Record the orientation, then try slow pickups, quick pickups and normal put-downs. Include table knocks nearby and movement inside the intended carrying case. We have not run these tests; they are the plan for the next stage.

For each trial, record whether the device woke, how long it took to become usable, and whether it returned to rest. Count unwanted wake-ups as well as missed pickups. A setting that feels responsive in one demonstration may spend too much time awake during ordinary transport.

Measure current at the complete prototype's supply too. Bosch's BMA400 evaluation guide reports roughly 0.8 µA for low-power measurement at OSR=0 and roughly 3.5 µA for normal mode at OSR=0. Those are sensor figures under stated conditions. Our module adds a regulator and a power LED, and the controller, screen and radio add their own draw.

The goal is a demonstrated sequence: the assembled device rests, recognizes a wanted pickup, becomes usable, and returns to rest without repeated false wake-ups. Once that is recorded, you have a basis for choosing the interrupt connection, firmware behavior and battery strategy for the next revision.