IoT time-series data logger for SparkFun hardware. Records IMU sensor data at 100Hz with QR code metadata tagging for ML datasets.
| Component | Part Number | I2C Addr | Purpose |
|---|---|---|---|
| SparkFun DataLogger IoT | DEV-22462 | - | Main controller (ESP32, microSD, Qwiic) |
| ISM330DHCX IMU Breakout | SEN-19764 | 0x6B | 6DoF inertial measurement (100Hz) |
| SAM-M8Q GPS Module | GPS-15210 | 0x42 | Time sync and location |
| Qwiic Button - Red LED | BOB-15932 | 0x6F | Recording trigger |
| Tiny Code Reader | SEN-23352 | 0x0C | QR code metadata scanner |
| MAX17048 Fuel Gauge | (onboard) | 0x36 | LiPo battery monitoring |
All sensors connect via Qwiic (I2C) - no soldering required!
-
Install PlatformIO
- VSCode: Install the PlatformIO IDE extension
- CLI:
pip install platformioorbrew install platformio
-
Hardware Setup
- Connect all Qwiic sensors to the DataLogger IoT board using Qwiic cables
- Insert a microSD card (formatted as FAT32 with MBR partition table - see CLAUDE.md)
- Connect USB-C cable to computer
# Build the project
pio run
# Upload to device
pio run --target upload
# Monitor serial output
pio device monitor --baud 115200Expected serial output shows:
- 6 I2C devices detected: 0x0C, 0x36, 0x42, 0x6B, 0x6F, 0x7E
- SD card mounted with size
- Free heap ~302KB
- IMU initialization with test readings
- GPS status (acquiring/locked)
- Battery voltage and state of charge
Troubleshooting: If "Invalid head of packet" error, hold BOOT button during upload or reduce upload_speed to 115200 in platformio.ini.
Important: Device enters deep sleep when IDLE to save battery. To wake the device, press the hardware RESET button (not the Qwiic button). The Qwiic button is only for starting/stopping recordings once the device is awake.
m3_data_logger/
├── platformio.ini # PlatformIO configuration
├── src/
│ └── main.cpp # Main application
├── include/ # Header files
├── lib/ # Custom libraries
├── test/ # Unit tests
├── tools/ # Development tools
│ └── qr_generator/ # QR code generation scripts
├── data/ # Sample datasets
│ └── test_qr_codes/ # Pre-generated test QR codes
└── README.md # This file
Data Recording:
- Press Button → RGB LED blinks (awaiting QR scan, 30s timeout)
- Scan QR Code → Captures metadata (test_id, description, labels)
- Recording Starts → LED solid, IMU data logged to microSD at 100Hz with GPS timestamps
- Press Button → Recording stops, LED returns to breathing pattern
Device Configuration (M3L-72):
- Long Press Button (3s) → Enters CONFIG mode, purple LED double-blink
- Scan Config QR Code → Device validates WiFi connection
- Config Saved → Returns to IDLE if validation succeeds, rollback if fails
RGB LED Status (dual-channel indication):
- Color: Green=GPS locked, Yellow=GPS acquiring, Blue=millis fallback, Red=error, Purple=CONFIG mode
- Pattern: Breathing=IDLE, Blinking=AWAITING_QR, Solid=RECORDING, Double-blink=CONFIG
Power Management (M3L-83 - Completed):
- Deep Sleep: Device enters deep sleep when IDLE to save battery (<1mA consumption)
- Wake: Press hardware RESET button to wake (timer wakeup with I2C polling, no GPIO interrupt)
- Battery Life: ~117 days on 2000mAh LiPo (2024-03-12 projected depletion from 2024-11-15)
- Battery Monitoring: MAX17048 fuel gauge tracks voltage, SOC%, low battery alerts
- Session Tracking: Start/end battery levels logged in metadata.json
Data Formats:
- CSV:
/data/session_YYYYMMDD_HHMMSS.csvwith GPS timestamps (Unix epoch ms), lat/lon, accel_xyz, gyro_xyz - Metadata:
/data/metadata.jsonwith session info, test_id mapping, time source (GPS or millis), battery data
Setup (first time only):
cd tools/qr_generator
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txtMetadata QR (for data sessions):
python generate_qr.py --mode metadata --description "walking_outdoor" --labels "walking,outdoor"Configuration QR (for device provisioning, M3L-74):
python generate_qr.py --mode config \
--wifi-ssid "MyNetwork" \
--wifi-password "SecurePassword123" \
--mqtt-host "mqtt.example.com" \
--device-id "m3logger_001"REST API (Docker, alternative):
cd tools/qr_generator
docker-compose up
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"description": "walking_outdoor", "labels": ["walking", "outdoor"]}' \
--output qr_code.pngSee tools/qr_generator/README.md for full API documentation and Postman guide.
- CLAUDE.md: Complete developer documentation (hardware, architecture, gotchas, patterns)
- PRD.md: Product requirements and roadmap
- tools/qr_generator/README.md: QR Generator API documentation
- docs/: Testing guides and procedures
Current Phase: NOW - MQTT Connectivity Implementation
Completed:
- Core data logging: State machine, button handler, QR scanner, IMU (100Hz), SD storage
- Session management with metadata.json (M3L-64)
- QR Generator CLI + REST API + Docker (M3L-66/67)
- ESP32 I2C fix for Tiny Code Reader (M3L-66)
- GPS time synchronization (M3L-77 Epic)
- time_manager module with GPS/millis fallback (M3L-78)
- GPS integration (SAM-M8Q at I2C 0x42) (M3L-79)
- Dual-channel RGB LED status indication (M3L-80)
- CSV timestamps with Unix epoch ms (M3L-81)
- GPS location logging (lat/lon in CSV with 1Hz caching) (M3L-82)
- Battery optimization and deep sleep (M3L-83)
- MAX17048 fuel gauge integration for battery monitoring
- Deep sleep implementation with timer wakeup (hardware RESET wake)
- Battery start/end tracking in session metadata
- Power manager with low battery detection
- Network configuration storage (M3L-71)
- Hybrid NVS + SD card storage
- Serial command interface for config management
- WiFi connection manager
- Configuration QR code generator (M3L-74)
- Config mode in CLI tool and REST API
- WiFi credentials + MQTT broker settings
- 220-byte size optimization for Tiny Code Reader
- QR-based device configuration (M3L-72)
- CONFIG state with 3s button hold entry
- Purple double-blink LED pattern
- WiFi validation before config save
- Automatic rollback on validation failure
Next Up (NOW Phase - MQTT Connectivity):
- M3L-84: WiFi & MQTT Core Connection (HIGH PRIORITY)
- M3L-85: High-Frequency Sensor Data Streaming (100Hz batched)
- M3L-86: Metrics, Monitoring & Shutdown Handling
Build Stats: 8.0% RAM (26KB), 38.0% Flash (498KB), 302KB free heap
See Linear project: M3-Data-Logger
This project is for personal/research use.
For issues or questions, see:
- Hardware datasheets: SparkFun product pages
- PlatformIO docs: https://docs.platformio.org
- Linear issues: https://linear.app/m3labs