123 lines
4.5 KiB
Markdown
123 lines
4.5 KiB
Markdown
# IMU Air Mouse
|
||
|
||
A BLE HID mouse that uses the onboard IMU of a **Seeed XIAO nRF52840 Sense** to move the cursor by tilting and rotating the device in the air. Intended as an open-source replacement for presentation remotes like the Logitech Spotlight, with additional features.
|
||
|
||
## Features
|
||
|
||
- **6-DoF gyro + accelerometer** via LSM6DS3 with complementary filter
|
||
- **Hardware tap detection** - single tap = left click, double tap = right click
|
||
- **BLE HID mouse** - works natively on Windows, macOS, Linux, Android, iOS
|
||
- **BLE Battery Service** - charge level visible in OS Bluetooth settings
|
||
- **Web config UI** (`web/index.html`) - configure over BLE from any Chrome/Edge browser, no app install
|
||
- **Flash persistence** - config survives power cycles (LittleFS)
|
||
- **Live IMU stream** - 20 Hz gyro/accel data streamed to the web UI visualiser
|
||
- **Live telemetry** - temperature, uptime, click counts, gyro bias RMS, recal count
|
||
- **Temperature compensation** - gyro drift correction by Δ temperature since last calibration
|
||
- **Auto-recalibration** - recalibrates automatically after 5 minutes of idle
|
||
- **Configurable charge rate** - OFF / 50 mA slow / 100 mA fast via BQ25100 HICHG pin
|
||
- **Boot-loop detection** - 3 rapid reboots trigger safe mode (config service disabled, flash wiped)
|
||
|
||
## Hardware
|
||
|
||
| Part | Notes |
|
||
|---|---|
|
||
| Seeed XIAO nRF52840 Sense | nRF52840 + LSM6DS3 IMU onboard |
|
||
| Li-ion battery (10440 / LiPo) | Connected to VBAT + GND pads |
|
||
|
||
## LED Status
|
||
|
||
The XIAO has three user LEDs (active LOW - HIGH = off, LOW = on):
|
||
|
||
| LED | Pattern | Meaning |
|
||
|---|---|---|
|
||
| Blue | Single pulse every 10 s | BLE connected (heartbeat) |
|
||
| Green | Single pulse every 10 s | Advertising / not connected (heartbeat) |
|
||
| Green | Rapid flutter (~10 Hz) | Gyro calibration in progress |
|
||
| Red | Fast blink (continuous) | IMU init failed - hardware fault |
|
||
| Red | 3 slow blinks on boot | Boot-loop detected - entered safe mode |
|
||
| Red | 6 rapid blinks | Battery critically low (< 3.10 V) |
|
||
|
||
> **Blue** = BLE-related state. **Green** = device activity. **Red** = fault only.
|
||
|
||
## Web Config UI
|
||
|
||
Open `web/index.html` in Chrome or Edge (desktop). Requires Web Bluetooth - enable it at `chrome://flags/#enable-web-bluetooth` on Linux.
|
||
|
||
**Configurable parameters:**
|
||
|
||
| Parameter | Range | Description |
|
||
|---|---|---|
|
||
| Sensitivity | 100 – 1500 | Cursor speed multiplier |
|
||
| Dead zone | 0.005 – 0.2 rad/s | Noise floor; raise to reduce drift |
|
||
| Accel strength | 0 – 0.5 | Pointer acceleration multiplier |
|
||
| Curve | Linear / Square / √Sqrt | Response shape for input magnitude |
|
||
| Flip X / Y | on/off | Invert horizontal or vertical axis |
|
||
| Charge mode | Off / 50 mA / 100 mA | BQ25100 charge current |
|
||
|
||
**Commands:**
|
||
|
||
- **Calibrate Gyro** - recalculates bias offset; hold the device still on a flat surface for ~1 s
|
||
- **Factory Reset** - wipes flash config, restores defaults
|
||
|
||
## Building
|
||
|
||
### Requirements
|
||
|
||
- [PlatformIO](https://platformio.org/) (VS Code extension or CLI)
|
||
- `adafruit-nrfutil` for flashing: `pip install adafruit-nrfutil`
|
||
|
||
### Flash
|
||
|
||
```sh
|
||
pio run -t upload
|
||
```
|
||
|
||
Double-tap the reset button to enter the UF2 bootloader (red LED pulses) if the board doesn't auto-reset.
|
||
|
||
### Feature flags
|
||
|
||
All optional features are enabled by `#define` in `source/config.h`. Comment out any line to disable that feature and reduce firmware size / RAM:
|
||
|
||
```c
|
||
#define FEATURE_CONFIG_SERVICE // BLE config GATT service
|
||
#define FEATURE_TELEMETRY // 1 Hz telemetry notifications
|
||
#define FEATURE_IMU_STREAM // 20 Hz raw IMU stream
|
||
#define FEATURE_TAP_DETECTION // Hardware tap → click engine
|
||
#define FEATURE_TEMP_COMPENSATION // Gyro drift correction by temperature
|
||
#define FEATURE_AUTO_RECAL // Auto-recalibrate after 5 min idle
|
||
#define FEATURE_BATTERY_MONITOR // ADC battery level + BLE Battery Service
|
||
#define FEATURE_BOOT_LOOP_DETECT // Crash counter → safe mode
|
||
```
|
||
|
||
## BSP memory layout fix
|
||
|
||
The XIAO nRF52840 Sense requires a modified linker script to work with SoftDevice S140 7.3.0. Edit `cores/linker/nrf52840_s140_v7.ld` in the Adafruit nRF52 Arduino core:
|
||
|
||
```c
|
||
MEMORY
|
||
{
|
||
FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xED000 - 0x27000
|
||
RAM (rwx) : ORIGIN = 0x2000E000, LENGTH = 0x20040000 - 0x2000E000
|
||
}
|
||
|
||
SECTIONS
|
||
{
|
||
. = ALIGN(4);
|
||
.svc_data :
|
||
{
|
||
PROVIDE(__start_svc_data = .);
|
||
KEEP(*(.svc_data))
|
||
PROVIDE(__stop_svc_data = .);
|
||
} > RAM
|
||
|
||
.fs_data :
|
||
{
|
||
PROVIDE(__start_fs_data = .);
|
||
KEEP(*(.fs_data))
|
||
PROVIDE(__stop_fs_data = .);
|
||
} > RAM
|
||
} INSERT AFTER .data;
|
||
|
||
INCLUDE "nrf52_common.ld";
|
||
```
|