← All work

In progress

Moji

Moji is a pocket-sized companion on an ESP32-C3 with an expressive face, games, tools, custom messages, and a local management portal.

Moji render showing the pocket-sized companion with a pixel face.
In progress. Firmware v1.0.0 is running with the current menu, apps, management portal, and low-power behavior.

The idea

Moji is meant to feel like a small companion with a mood, not a breadboard demo. It runs real ESP-IDF firmware, spends most of its life asleep, and still reacts when you pick it up. The firmware is organized around one on-device menu and a local web portal for everything that is easier from a phone or laptop.

Current firmware

Two-button UI

On the face, left and right clicks make Moji glance toward the button. Pressing both opens the menu. Inside menus, left and right move through items and a held right button enters the selected item. The same hold feedback shows up in the setup flow and menu navigation.

Display bring-up

SSD1315 over 3-wire SPI (D/C bit in-band). CS toggles per byte on this board. Segment/column remap is ignored by the panel, so orientation is fixed at flush while draw code keeps normal coordinates. Flush promotes to a full frame when any page is dirty to avoid tearing.

Power

Active → idle → light sleep → deep sleep. Charging inferred from ADC trend (no charge-detect pin). Buttons wake from deep sleep; IMU wakes from light sleep only. Radio-heavy modes block at ~15%. At ~5%, state flushes to NVS and the device drops to deep sleep on purpose.

Capabilities

Companion

Expressive idle face, motion-aware gaze, mood state, friendly phrases, charging animation, and low-power sleep.

Play

Connect, Pong, Reaction, Tilt Maze, Dice, and Coin Flip.

Tools

Level, Flashlight, Timer, and Stopwatch.

Device

Stats, display controls, sleep, about, and factory reset.

Management

Local SoftAP portal for setup, settings, custom messages, status, and OTA firmware upload.

Architecture

Focused ESP-IDF components. ISRs only queue events; a UI/behavior task does the work.

moji_input

Button ISRs and battery ADC into a FreeRTOS queue.

moji_display

SSD1315 9-bit bit-banged SPI, staged framebuffer flush.

moji_face

Parametric eyes/mouth from a single mood state.

moji_nav

Shared scroll + long-press-release select and text entry.

moji_behavior

Mood metrics with decay, persisted in NVS.

moji_shell

App switching and power state machine.

moji_ble_hid

BLE HID mouse support.

moji_link

ESP-NOW link for paired play.

moji_portal

SoftAP web UI and OTA.

Manual

Owner controls, modes, and power behavior.

Open manual →