A 3D printed camera with an OLED display, saving to SD card and capacitive touch button controls.
ButtonCam 3D Printed Model
I designed the camera in Tinkercad. The front and back look like this:
The 3D files need to flipped upside down in the slicer before printing:
The final 3D prints look like this:
In addition to the ESP32-CAM. The project requires a microSD card, an SSD1306 OLED, three TTP223 capacitive touch switches, 15 dupont cables, a voltage booster, a 18650 battery and holder.
The 18650 battery, holder and booster could be replaced with anything that can supply 5v to the ESP32-CAM.
It should be easy to install all the components as shown in the video. If you use a different part or something doesn’t fit, you can snap off the clips and just glue or Blu Tack the part in place.
C++ Code on the ESP32
In the Arduino loop, frames are constantly requested from the camera. Each JPG frame is decoded and the pixels converted to grey scale while saving into an array. This array is then processed a second time to create to a dithered monochrome array that is output to the OLED screen.
While this camera data is being streamed to the OLED the ESP32 also listens for button presses from the three capacitive touch buttons. If the trigger button is pressed, the camera switches to a higher resolution, captures a frame and this is saved to the microSD card and also briefly shown on the OLED screen.
If the left or right buttons are pressed the ESP32 reads the files before or after the current image on the microSD card and again, shows this on the OLED.
Fully assembled the project looks and functions like this:
Dithering Video for Monochrome Displays
Video passed directly from a camera to a monochrome screen can be difficult to make out. It needs to be dithered using error diffusion to break up the solid black and white areas. The Arduino code processes the image using the Floyd-Steinburg dithering algorithm.
When the frame size is set to QQVGA2 it is easy to decode the top part of the 128×160 frame to give 128×64 pixels to display on the OLED screen. The problem is that only the top part of the camera frame is shown on the screen.
I wanted to use frames from the full sensor so I set the resolution to QQVGA (160 × 120) and resampled the camera frames to create an array with the same resolution as the screen. However I discovered later than the minimum resolution that the ov2640 sensor outputs at full frame is CIF (352 x 288 pixels). I need to investigate this further.
It’s easier to see how effective using dithering can be with monochrome screens in the video below which shows the same two resolutions as above but with a moving image.
Mark II of this project will have a power switch, the camera will be relocated and the code improved. The slide-show will probably be replaced with an image browser.
Code, 3D models, STL and Wiring Diagram
Front 3D model in Tinkercad: https://www.tinkercad.com/things/dK7u5P9LzYN
Rear 3D model in Tinkercad: https://www.tinkercad.com/things/7xgXlRxUpKV
Back 3D model with extra depth: https://www.tinkercad.com/things/4IcffHCq0cD
For the STL files, just click the Export button in the pages above.
The Arduino code is here:
You need to copy both files into new directory named ButtonCam with your other Arduino sketches. Use the following settings when uploading:
Best guide to dithering I found – https://tannerhelland.com/2012/12/28/dithering-eleven-algorithms-source-code.html
Basic Floyd-Steinburg pseudocode – https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering