Building a camera for Flipper Zero with an ESP32-CAM
You can use the
Flipper Zero Camera Suite
to make a cheap ESP32-CAM module work like it belongs on a Flipper Zero.
The repository is split into two parts: firmware for the ESP32-CAM in
firmware/, and the Flipper app in fap/. Together
they let me stream a live preview to the Flipper screen, tweak a few image
controls, and save captures from the device itself.
Why I made it
I liked the idea of giving the Flipper a camera without pretending it was going to become a polished photography device. The whole point of this project is that it stays small, cheap, and a little weird. At its core, this is about capturing live previews and saving those blocky little memories with an ESP32-CAM wired into the Flipper over GPIO.
That shaped the UX too. I wanted just enough control to make the feed usable on a Flipper screen, contrast up and down, invert, dithering on and off, rotation, flash, and a quick way to save a shot to the SD card. It is intentionally simple, and that simplicity is part of what makes it fun.
How the system works
On the firmware side, the ESP32-CAM starts a serial connection at
230400, initializes the camera, loads a default camera model,
and then sits in a loop reading one-byte commands from serial. Those
commands are small and direct. I use single characters to toggle
streaming, flash, invert, dithering, brightness, contrast, and the
selected dithering mode.
For the live feed, I keep the camera configured for
PIXFORMAT_GRAYSCALE at FRAMESIZE_128X128. When
streaming is enabled, the firmware can run error-diffusion dithering, then
packs 8 pixels into a byte and sends each row with a tiny header:
Y: plus the row number. On the Flipper side, a worker thread
reads that serial stream into a buffer, checks the row header,
reconstructs the image row by row, and redraws the screen.
When the camera view opens on the Flipper, the app sends S to
start streaming, pushes the selected dithering mode, resets invert, and
applies the current flash state. While the stream is running, the Flipper
just keeps sending tiny one-character control messages back to the
ESP32-CAM whenever I press a direction or toggle an option.
What is happening inside the Flipper app
The Flipper side is structured like a normal multi-scene app. There is a start screen, a main menu, a camera view, a guide view, camera settings, and application settings. The main menu branches through the scene manager and view dispatcher, and the app saves things like orientation, dithering, flash, haptics, speaker, and LED feedback to a config file so they persist between runs.
Hardware, flashing, and getting it running
The wiring is straightforward: VCC goes to 3V3,
GND to GND, U0R to TX,
and U0T to RX. For flashing, the ESP32-CAM also
needs IO0 tied to GND so it boots into flash
mode.
There are two installation paths by design. The easy firmware path is the
Windows flashing script at the repo root, firmware-flash.bat.
The manual path uses the Arduino IDE, the AI Thinker ESP32-CAM board
profile, and the Flipper's GPIO > USB-UART Bridge mode. On
the app side, the Flipper application can be installed from the Flipper
app catalog, or you can manually copy the built
camera_suite.fap into apps/gpio on the MicroSD
card.
You can also check out my Flipper Zero Development Toolkit for a Visual Studio Code workflow.
Big thanks
This project also owes a lot to earlier work. It is based on Z4urce's Flipper Zero Camera Application, and I leaned on leedave's Flipper Zero FAP boilerplate to learn a cleaner app structure on the Flipper side. Big thanks to the community. I really enjoyed building this one.
