Files
air-mouse/README.md

123 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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";
```