Why Motion Sensing Belongs on Every Asset Tag
Most BLE tag deployments track location, but location alone doesn’t tell you whether a pallet was dropped, a crate tipped over, or a high-value instrument sat vibrating on a truck bed for six hours. Adding an accelerometer to a tag transforms it from a passive beacon into an active sensor node—one that can detect impact events, classify motion patterns, and wake the MCU only when something actually happens.
The engineering challenge isn’t picking an accelerometer IC (that’s a spreadsheet exercise). It’s designing the interrupt chain, impact threshold logic, power budget, and false-positive filter so the tag reports real events without draining its battery or flooding your gateway with noise.
This article walks through the full signal path: from silicon selection through detection algorithms, interrupt architecture, data encoding, and calibration—with real numbers at every step.
Accelerometer IC Selection: What Actually Matters
Low-power asset tags don’t need 16-bit 20 kHz IMUs. They need 8–12-bit accelerometers that sleep at <1 µA and wake on programmable thresholds. Here's the field narrowed to the ICs that matter:
| Parameter | ST LIS2DH12 | ADI ADXL362 | Bosch BMI270 | TDK ICM-42670-P |
|---|---|---|---|---|
| Resolution | 8/10/12-bit | 12-bit | 16-bit | 16-bit |
| Range (g) | ±2/4/8/16 | ±2/4/8 | ±2/4/8/16 | ±2/4/8/16 |
| Current (active) | 5–11 µA | 0.2 µA (motion) | 4.8 µA | 6.6 µA |
| Current (sleep) | 0.5 µA | 10 nA | 3 µA | 2 µA |
| Built-in activity detect | Yes (INT1/INT2) | Yes (awake/inact) | Yes (any-motion) | Yes (wake-on-motion) |
| Interface | SPI / I²C | SPI | SPI / I²C | SPI / I²C |
| Package | LGA 2×2×1 | LGA 3×3×1.05 | LGA 2.5×3×0.83 | LGA 2.5×3×0.76 |
| Price (1K) | $0.58 | $3.85 | $1.20 | $1.55 |
For asset tags, ST LIS2DH12 is the pragmatic default: programmable 8/10/12-bit modes, two interrupt pins, built-in click/double-click detection, and 0.5 µA standby. At $0.58 in quantity it barely affects the BOM. The ADXL362’s 10 nA sleep is impressive, but its SPI-only interface and $3.85 price tag make it a niche choice for ultra-low-power designs where the MCU itself sleeps at sub-µA and you can’t tolerate even 0.5 µA from the accelerometer.
Key selection criteria that most datasheets don’t emphasize:
- Threshold granularity: LIS2DH12 activity threshold is 1 LSB = 16 mg at ±2 g / 12-bit. ADXL362 is 3.9 mg/LSB. For impact detection at 1–2 g, both are sufficient.
- Interrupt latency: Built-in activity detection fires in 1–3 sample periods. If you sample at 1 Hz for inactivity, that’s 1–3 seconds—not fast enough for impact. You need a separate high-rate path.
- FIFO depth: LIS2DH12 has a 32-sample FIFO. BMI270 has a 128-sample FIFO. Larger FIFOs let the MCU burst-read impact waveforms without keeping SPI active during the event.
Motion Detection Modes and What They’re Good For
BLE tag firmware typically runs three detection modes simultaneously on different threshold axes:
1. Activity / Inactivity (Presence Detection)
Purpose: Detect whether the tagged asset is stationary or in transit. This drives mode-switching—advertising interval drops from 1000 ms to 100 ms when the asset is moving.
Configuration (LIS2DH12):
- Activity threshold: 0.5 g (32 mg/LSB × 16 = ~512 mg)
- Activity duration: 1 sample at 1 Hz (immediate trigger)
- Inactivity threshold: 0.08 g
- Inactivity duration: 30 samples at 1 Hz (30 seconds of stillness)
Power impact: The accelerometer runs at 1 Hz (5 µA) while the MCU sleeps. When activity fires, the MCU wakes and switches the BLE radio to fast advertising.
2. Free-Fall Detection
Purpose: Detect drops—pallets lifted by crane and released, instruments knocked off benches.
The signature is all three axes near zero simultaneously. LIS2DH12 free-fall threshold: set activity to ≤0.2 g on all axes, duration ≥2 samples at 200 Hz (10 ms). At 200 Hz the accelerometer draws ~11 µA—acceptable only if you keep free-fall detection active during known handling windows.
Practical complication: A tag mounted on a box corner experiences 0.6 g resting gravity on one axis during normal orientation. When the box tips, that axis shifts but doesn’t go to zero. Free-fall only works for objects that truly become airborne. For most logistics scenarios, impact detection (next section) is more reliable.
3. Single / Double Click (Tap Detection)
Purpose: User interaction—double-tap to confirm asset handoff, single-tap to request a location ping.
LIS2DH12 built-in click detection handles this without firmware involvement:
- Click threshold: 1.2 g (higher than activity to avoid false triggers from truck vibration)
- Click time limit: 80 ms (window for a tap)
- Double-click latency: 400 ms (time between first and second tap)
- Interrupt on INT1 for single click, INT2 for double click
This mode runs at 400 Hz (~11 µA) only during a configurable time window (e.g., first 30 seconds after a button press or gateway proximity event). Otherwise the accelerometer stays at 1 Hz.
Impact Detection: The Real Engineering Problem
Impact events are the hardest to detect reliably because they share spectral characteristics with vibration, door slams, and forklift bumps. The signal processing is simple—exceed a threshold—but the threshold selection and confirmation logic are not.
Threshold Selection by Application
| Scenario | Typical Peak (g) | Recommended Threshold | Detection Window |
|---|---|---|---|
| Package drop (30 cm, hard floor) | 15–30 | 8 g | 5 ms |
| Pallet bump (forklift) | 3–6 | 2.5 g | 50 ms |
| Truck vibration (road) | 0.5–1.5 | 1.5 g (with confirmation) | 100 ms |
| Instrument shelf tip-over | 2–4 | 2 g | 20 ms |
| Laptop bag drop | 10–20 | 6 g | 10 ms |
The key insight: threshold alone is insufficient. A forklift bump at 4 g looks like a package drop to a simple threshold detector. You need confirmation criteria:
- Duration confirmation: Impact events shorter than the detection window are ignored. A 4 g peak lasting 2 ms is vibration; a 4 g peak lasting 40 ms is a bump.
- Axis correlation: Real impacts produce correlated spikes on multiple axes. Random vibration typically peaks on one axis (the one aligned with the vibration direction). Compute
mag = sqrt(x² + y² + z²)and requiremag > thresholdinstead of testing per-axis. - Pre/post-quiet window: Before and after the event, require
mag < 0.5 × thresholdfor at least 2 sample periods. This eliminates vibration trains where multiple peaks cross the threshold in quick succession.
Impact Detection Firmware Flow
State: ACCEL_IDLE (1 Hz, MCU sleeping)
INT fires → ACCEL_ACTIVE
→ Switch to 200 Hz
→ Read FIFO for 50 ms (10 samples)
→ Compute magnitude per sample
→ If max_mag > IMPACT_THRESH:
→ Check duration (samples above threshold)
→ Check quiet window before/after
→ If confirmed:
→ Record peak magnitude, duration, axis distribution
→ Wake BLE, send impact event packet
→ Return to ACCEL_IDLE after 5 s
→ Else: false positive, return to ACCEL_IDLE
→ Else: activity trigger, resume fast advertising
The 200 Hz burst lasts only 50 ms. Current during burst: accelerometer 11 µA + MCU active 3 mA × 50 ms = 0.15 mAs per event. Even at 100 events/day, that's 15 mAs/day—negligible compared to BLE advertising.
Interrupt-Driven Architecture: The Power Budget Backbone
The tag's power budget is determined by how long the MCU and radio stay asleep. Interrupt-driven design means the accelerometer acts as a hardware watchdog:
Interrupt Routing (LIS2DH12)
| INT Pin | Function | MCU Action | Accel Rate |
|---|---|---|---|
| INT1 | Activity / Click / Free-fall | Wake MCU, read status | 1 Hz (default) → 400 Hz (click window) |
| INT2 | Inactivity / FIFO watermark | None (inactivity) or burst-read (FIFO) | 1 Hz |
The MCU (e.g., nRF52832) sleeps at 1.2 µA (System OFF with RAM retention) or 0.6 µA (System OFF without retention). The LIS2DH12 draws 5 µA at 1 Hz. Total standby: ~6 µA.
Event-Triggered Power States
| State | Duration | Current | Energy (µC/event) |
|---|---|---|---|
| Deep sleep | Continuous | 6 µA | — |
| Activity INT → MCU wake + status read | 5 ms | 3 mA | 15 |
| Impact detection burst | 50 ms | 3 mA + 11 µA | ~151 |
| BLE advertising (fast, 100 ms interval) | 5 s | 8.5 mA avg | 42,500 |
| BLE advertising (slow, 1000 ms interval) | Continuous | ~12 µA avg | — |
On a CR2032 (220 mAh, 2.9–3.0 V usable):
- Slow advertising only (1000 ms): ~2.4 years
- Motion-triggered fast advertising (100 events/day, 5 s each): ~2.1 years
- Impact detection + reporting (20 impacts/day): ~2.0 years
The motion sensing overhead is under 5% of total battery life. The BLE radio is still the dominant consumer.
Data Encoding: Packing Impact Data into Advertising Packets
A BLE tag that detects an impact needs to report: event type, peak magnitude, duration, and optionally axis distribution. Standard BLE advertising packets have 31 bytes of usable payload (after flags and length headers). Here's how to encode impact events efficiently:
Custom Manufacturer-Specific Data Format
Byte 0-1: Company ID (0xFFFF for testing, register for production)
Byte 2: Data type flag
0x01 = Motion status (activity/inactivity)
0x02 = Impact event
0x03 = Free-fall event
Byte 3: Event sub-type / severity
Impact: 0x01=minor (2-4g), 0x02=moderate (4-8g), 0x03=severe (>8g)
Byte 4-5: Peak magnitude (0.01 g units, uint16)
Example: 4.56 g → 0x01C8 (456)
Byte 6-7: Event duration (0.5 ms units, uint16)
Example: 38 ms → 0x004C (76)
Byte 8: Axis distribution bitmap
Bit 0: X-axis dominant
Bit 1: Y-axis dominant
Bit 2: Z-axis dominant
Bit 3: Multi-axis (correlated)
Bit 4-7: reserved
Byte 9: Temperature at event (°C, signed, 0.5°C resolution)
Byte 10: Battery level (0-100%)
11 bytes total for a full impact report. With 2-byte flags and 2-byte length header, that's 15 bytes—well within the 31-byte limit. The remaining space can carry the standard UUID/major/minor for location context.
Multi-Event Buffering
If impacts happen in bursts (e.g., a pallet being loaded), the tag buffers up to 8 events in RAM and rotates them through successive advertising packets. Each packet carries one event; the BLE radio cycles through the buffer at 100 ms intervals for 5 seconds after the last event.
False Positive Reduction: The Difference Between Useful and Useless
Every deployment engineer has seen the same problem: a tag mounted on a warehouse doorframe reports 300 "impacts" per day because the door vibrates when trucks pass. Here's a layered filter stack:
Layer 1: Magnitude + Duration Gate
As described above: require mag > threshold AND duration > min_window. This eliminates 80% of false positives from vibration peaks that cross the threshold but don't sustain.
Layer 2: Axis Correlation
Compute the ratio r = min(x, y, z) / max(x, y, z) at the peak. Real impacts produce r > 0.3 (energy distributed across axes). Directional vibration produces r < 0.15 (one dominant axis). Apply this filter only for thresholds below 4 g—above 4 g, any peak is almost certainly real.
Layer 3: Temporal Debounce
After a confirmed impact, suppress further detections for a configurable cooldown period (default: 60 seconds). This prevents one physical impact from generating 5 reports as the object bounces. Adjust cooldown by application:
- Delicate instruments: 5 seconds (catch each bounce)
- Industrial pallets: 120 seconds (one report per handling event)
Layer 4: Context Gate
Only enable impact detection when context conditions are met:
- Tag is in transit (activity detection = moving)
- Tag is near a loading zone (gateway RSSI > -60 dBm)
- Time window (impact detection only during business hours)
Layer 4 is application-specific but powerful. A tag on a stationary shelf doesn't need impact detection at all—disable it and save the 200 Hz burst overhead.
False Positive Rate Comparison
| Filter Stack | True Positive Rate | False Positive Rate (warehouse env) |
|---|---|---|
| Threshold only | 95% | 30/day |
| + Duration gate | 93% | 8/day |
| + Axis correlation | 90% | 2/day |
| + Temporal debounce | 88% | 0.5/day |
| + Context gate | 85% | <0.1/day |
The 10% true positive loss from the full stack comes mainly from the debounce filter missing rapid successive impacts (object bouncing). If your application needs every bounce, reduce debounce to 5 s and accept ~1 false positive/day.
Calibration: Making Thresholds Match Reality
Datasheet thresholds are theoretical. Every real tag needs per-unit calibration because:
- Zero-g offset: LIS2DH12 spec allows ±40 mg per axis after PCB mount. On a CR2032-powered tag with the battery directly above the accelerometer, solder reflow and PCB flex can shift offsets to ±80 mg.
- Sensitivity error: ±1.5% at ±2 g range. At a 4 g impact threshold, that's ±60 mg of uncertainty—not critical, but it affects severity classification accuracy.
- Cross-axis sensitivity: Up to 1% (axis X responding to axis Y input). For magnitude-based detection, this is negligible. For per-axis analysis, it matters.
Two-Point Calibration Procedure
On the production line, calibrate each tag in two orientations:
- Level position (tag flat on granite plate): Read all three axes. Expected: X=0, Y=0, Z=+1 g (or −1 g depending on orientation). Compute offsets:
offset_x = x_measured − 0,offset_y = y_measured − 0,offset_z = z_measured − 1.0. - Inverted position (tag flipped): Read Z axis again. Expected: Z = −1 g. Compute sensitivity:
sens_z = (z_level − z_inverted) / 2.0. The ratio1.0 / sens_zgives the scale correction factor.
Store offsets and scale factors in flash. Runtime firmware applies: x_corrected = (x_raw − offset_x) × scale_factor. This takes 12 bytes of flash (3 offsets + 3 scale factors as float16) and reduces threshold uncertainty from ±80 mg to ±5 mg—enough to distinguish a 2 g bump from a 2.5 g one.
Field Recalibration
Tags in service drift over time (temperature cycling, mechanical stress). Add a self-calibration routine triggered by:
- Temperature change > 15°C (zero-g offset drifts ~0.5 mg/°C)
- Extended stationary period (> 30 minutes at inactivity)
During a stationary period, the MCU wakes once, reads 32 samples at 25 Hz, averages them, and updates offsets in flash. This costs ~8 mAs per recalibration event—negligible.
Deployment: Mounting, Orientation, and Environment
Mounting Orientation Matters
The accelerometer reads gravity as a constant 1 g vector. If the tag is mounted vertically on a box face, one axis reads ~1 g at rest. An impact along that axis starts from 1 g, not from 0. This means:
- Magnitude-based detection (
mag = sqrt(x²+y²+z²)) is orientation-independent—total acceleration always includes the gravity component correctly. - Per-axis threshold detection is orientation-dependent—you need to subtract the static gravity vector first, or set per-axis thresholds accounting for the resting offset.
Best practice: Always use magnitude-based thresholds. Per-axis data is useful for classification (was the impact vertical or horizontal?) but not for initial detection.
Environmental Vibration Levels
Different environments have vastly different background vibration:
| Environment | Typical Vibration (g RMS) | Freq Range | Recommended Impact Threshold |
|---|---|---|---|
| Office / lab | 0.01 | 1–20 Hz | 1.5 g |
| Retail store | 0.05 | 5–50 Hz | 2.0 g |
| Warehouse floor | 0.1–0.3 | 10–100 Hz | 2.5 g |
| Truck in transit | 0.3–0.8 | 5–200 Hz | 3.0 g + duration gate |
| Ship / rail | 0.5–1.2 | 0.5–30 Hz | 4.0 g + axis correlation |
| Construction site | 1.0–2.0 | 2–500 Hz | 5.0 g + full filter stack |
If you deploy the same tag across environments, make the impact threshold configurable via BLE GATT write. A provisioning app scans the tag, reads the deployment context, and writes the appropriate threshold + filter configuration.
Sampling Rate vs. Detection Latency
Impact detection requires a minimum sample rate to capture the event peak. A 5 ms impact at 200 Hz gives you 1 sample on the peak—barely enough. At 400 Hz you get 2 samples. At 800 Hz you get 4 samples and can measure duration reliably.
The tradeoff: 200 Hz costs 11 µA, 400 Hz costs ~50 µA, 800 Hz costs ~150 µA. Since impact detection is burst-only (50 ms), the energy cost per event scales:
- 200 Hz burst: 0.55 µC
- 400 Hz burst: 2.5 µC
- 800 Hz burst: 7.5 µC
For tags that see <20 impacts/day, even 800 Hz bursts are negligible. But if your tag is in a high-vibration environment where the burst trigger fires 200 times/day, 800 Hz becomes expensive (1500 µC/day = 0.42 mAh/day on a 220 mAh battery = ~1% per day). Stick with 200 Hz and accept slightly less precise duration measurement.
Impact Data Reporting: Gateway Integration
When the tag confirms an impact, it needs to deliver the data to the backend. Two approaches:
Approach 1: Advertising-Packet-Only (No Connection)
The tag embeds impact data in its advertising packet for 5 seconds after the event. Gateways scanning at < 100 ms interval will capture it. Pros: zero connection overhead, sub-second latency. Cons: no acknowledgment—if the gateway misses the packet, the data is lost. For critical assets, add a retransmit counter: broadcast the impact packet 3 times at 20 ms intervals (total 60 ms), then slow down to 100 ms for the remaining 4.9 seconds. This costs ~3 mAs per event but gives 3 chances for the gateway to catch it.
Approach 2: Connection-Based Reporting
The tag connects to the nearest gateway and writes impact data to a GATT characteristic. Pros: guaranteed delivery, can transfer larger data (e.g., full 32-sample waveform). Cons: connection overhead (~30 mAs per connection), 2–5 second latency, and requires the gateway to be connectable.
Hybrid: Send a lightweight impact notification via advertising (Approach 1), and if the backend requests detail, establish a connection for the waveform (Approach 2). This gives instant notification with optional deep data.
Real-World Implementation Checklist
Before deploying motion-sensing tags in production:
- Validate thresholds on-site: Mount tags on real assets in the actual environment. Record 24 hours of raw data. Set thresholds at 2× the maximum background vibration peak.
- Test mounting variability: Try 5 different mounting positions. Verify that magnitude-based detection is consistent regardless of orientation.
- Profile false positive rate: Run for 7 days with detection logging but no reporting. Count false positives. Adjust filter stack until FP rate < 1/day.
- Measure battery impact: Deploy 10 tags with motion sensing enabled and 10 without. Compare battery voltage after 30 days. Target: < 5% difference.
- Plan firmware updates: Thresholds and filter parameters should be GATT-writable. Deploy with conservative defaults, then tune remotely based on collected data.
- Document axis mapping: Record which accelerometer axis maps to which physical direction for each mounting configuration. This determines impact direction classification accuracy.
Motion sensing on BLE tags is not a feature you bolt on—it's a signal-processing pipeline that requires calibration, filtering, and power management from day one. But done correctly, it turns a location beacon into a condition-monitoring sensor with less than 5% battery impact, and that's a tradeoff every asset-tracking engineer should take.