Skip to content

Iot

AtomBrick: ESP32 BLE Motor Controller to KMP Mobile App

AtomBrick is a Bluetooth motor controller. An ESP32 acts as a BLE peripheral driving up to five DC motors. A Kotlin Multiplatform app on Android and iOS connects, authenticates via passkey, and sends motor commands. This post walks the full stack, covering firmware, command protocol, and the mobile layer, with specific attention to where the two sides meet.

BLE GATT Profile Design for Hardware Control: AtomBrick

When you define a BLE GATT profile for the first time, it feels like boilerplate: pick some UUIDs, create a service, add characteristics. Those decisions define the protocol between your firmware and every app that ever connects to the device. AtomBrick went through one revision of this, and the mistakes are specific enough to be worth documenting.

ESP32 BLE Passkey Pairing, Bonding, and Encryption

The default ESP32 BLE example from Espressif ships with zero authentication. Any device in range can connect, read, and write your characteristics. For a product controlling physical actuators, that is not acceptable. This post shows how to add passkey pairing, MITM protection, and bonding to an ESP32 BLE server using the Arduino BLE stack, drawn from a real motor controller firmware.

Kotlin Multiplatform BLE with Kable, Koin, and Compose

Android BLE is BluetoothGatt callbacks firing on arbitrary threads. iOS BLE is CBCentralManager delegates with its own threading model. Kable, a KMP BLE library by JUUL Labs, wraps both behind a coroutines and Flow API. This post shows how the AtomBrick motor controller app uses Kable alongside Koin and Compose Multiplatform to scan, connect, and send commands to an ESP32 peripheral from a single shared codebase.