All projects

ESP32 · IoT Device

CrossWave

A motion-sensing IoT device that reads acceleration with a 3-axis IMU, exchanges packets with a paired unit over 433 MHz RF, displays multi-screen information on an OLED, and streams live sensor data via WebSocket to a companion web app. BLE provisioning, pocket detection, and deep-sleep power management make it ready for real-world carry.

C++ ESP32 433 MHz RF BLE WebSocket MPU6050 SSD1306 Arduino PlatformIO
specifications
chipESP32 DevKit
frameworkArduino
buildPlatformIO
rf_band433 MHz OOK
rf_rate2000 bps
imuMPU6050 I2C
displaySSD1306 128×64
ws_rate~10 Hz JSON
sleepdeep after 30 s

What CrossWave does

433 MHz RF Mesh

Exchanges RadioHead-framed packets with a second identical device. Detects when a paired unit comes into range and displays the RF message count on the OLED overview screen.

3-Axis IMU Streaming

MPU6050 delivers accelerometer readings at ~10 Hz over a WebSocket connection. Each frame is a JSON payload with ax, ay, az, rfCount, rfMessages, and a timestamp.

BLE Provisioning

The companion web app connects over Bluetooth and writes the WiFi SSID and password to GATT characteristics. The device notifies CONNECTED:<ip>:81 when online.

Multi-Screen OLED UI

Navigates between screens with two hardware buttons. Screens include an overview (RF count, WiFi status), detailed RF stats, custom message display, and animated boot logo.

Pocket Detection

A digital light sensor on GPIO 16 forces the screen off when the device is in a pocket. The OLED turns back on automatically the moment light is detected again.

Deep Sleep

Enters deep sleep after 30 seconds of no accelerometer motion. GPIO 14 (BTN_NEXT, an RTC GPIO) is the wake source via ext0. Power consumption drops to microamp range during sleep.

Bill of materials

#ComponentGPIO / BusNotes
1ESP32 DevKit (38-pin)Any standard ESP32 devkit; 3.3 V logic
2MPU6050 accelerometerSDA 25 · SCL 26I2C address 0x68 (AD0 → GND)
3SSD1306 OLED 128×64SDA 25 · SCL 26Shared I2C bus with MPU6050
4433 MHz RF TX moduleGPIO 32RadioHead 2000 bps; ~17 cm wire antenna
5433 MHz RF RX moduleGPIO 33XY-MK-5V, RXB6, or similar
6Button NEXTGPIO 14 → GNDInternal pull-up; also RTC wake source
7Button PREVGPIO 18 → GNDHold 3 s triggers factory reset
8Digital light sensorGPIO 16HIGH = dark (pocket); toggles screen

Get it running

# clone and enter the CrossWave sub-project
git clone https://github.com/mabushi-lab/CrossWave
cd CrossWave
 
# build and flash (change upload_port in platformio.ini first)
pio run -t upload
 
# monitor serial output at 115200 baud
pio device monitor

Upload port defaults to /dev/cu.usbserial-0001 in platformio.ini — change it to match your machine.

Live data stream

Once provisioned, CrossWave broadcasts JSON on ws://<ip>:81 at ~10 Hz. Send MSG:<text> to update the custom message shown on the OLED.

// broadcast frame — emitted ~10 Hz
{
  "type": "data",
  "ax": 0.12,
  "ay": -0.04,
  "az": 9.79,
  "rfCount": 2,
  "rfMessages": [],
  "customMsg": "",
  "ts": 1748476800
}