Skip to content
Chante Moore Online

How to use a 1.14 inch display with a camera module?

By admin
adminAbout the author

To use a 1.14 inch display with a camera module, you typically connect both to a microcontroller like the ESP32 or Raspberry Pi Pico, which handles the data flow between the camera (e.g., OV2640) and the display. The display, often a 1.14 inch 240x135 ips display, uses SPI for fast communication, while the camera module uses a parallel interface or SPI as well. You'll need to wire the display's CS, DC, MOSI, SCK, and LED pins to the microcontroller's SPI pins, and the camera's VSYNC, HREF, PCLK, and data lines to specific GPIOs. Power both with 3.3V, ensuring the camera module doesn't draw more than 150mA—common for OV2640—and the display typically consumes 20-30mA. The key challenge is synchronizing the camera's frame capture with the display's refresh rate, which requires careful timing in your firmware. For example, the OV2640 outputs JPEG or RGB565 data at up to 15 fps in UXGA mode, but the 1.14 inch display only supports 240x135 pixels, so you'll need to downsample the image to fit the resolution. Use a library like TFT_eSPI for the display and ESP32-CAM for the camera, adjusting the SPI clock speed to 40 MHz to avoid data loss. If you're using a Raspberry Pi Pico, set the PIO state machine to handle the camera's parallel data, then push it to the display via SPI. Always check the datasheets for pinout specifics—like the display's 6-pin SPI interface (GND, VCC, SCL, SDA, RES, DC) and the camera's FPC connector—to avoid shorts. For a real-world setup, the 1.14 inch 240x135 ips display pairs well with the OV2640 because both operate at 3.3V logic, and the display's 240x135 resolution matches the camera's QVGA mode after cropping. Test the connection by capturing a single frame and displaying it, then optimize the buffer size—typically 320x240 for the camera, reduced to 240x135 via bilinear interpolation. This approach minimizes latency, keeping it under 50ms for real-time previews.

Start by identifying the display's pinout. The 1.14 inch IPS display uses a 6-pin SPI interface: GND, VCC (3.3V), SCL (clock), SDA (data), RES (reset), and DC (data/command). Some variants include a backlight LED pin, which you can connect to a PWM-capable GPIO for brightness control. The camera module, like the OV2640, has a 24-pin FPC connector with power (3.3V), ground, and data lines—typically 8-bit parallel data (D0-D7), plus VSYNC, HREF, PCLK, and XCLK. For the ESP32, map the camera's VSYNC to GPIO 25, HREF to 26, PCLK to 27, and data lines to GPIO 32-39. The display's SPI pins connect to the ESP32's VSPI: MOSI to GPIO 23, SCK to GPIO 18, CS to GPIO 5, DC to GPIO 2, and RES to GPIO 4. Use a logic level shifter if the camera operates at 5V, but most OV2640 modules are 3.3V compatible. Power the display and camera from the same 3.3V regulator, but add a 100μF capacitor near the camera to filter noise. The total current draw is around 200mA, so a 500mA regulator is safe. For the Raspberry Pi Pico, use SPI0: MOSI on GP19, SCK on GP18, CS on GP17, DC on GP16, and RES on GP15. The camera's PIO program uses the Pico's programmable I/O to capture parallel data—set the state machine to 8-bit mode with a clock divider of 2 to match the camera's PCLK (typically 6-12 MHz). This setup requires a custom PIO assembly file, but you can find examples in the Pico-Eye repository. Test the wiring by powering the display and running a simple fill-screen test—if it shows color, the SPI communication works. Then, initialize the camera with a configuration like 0x11 for QVGA (320x240), 0x12 for RGB565, and 0x14 for 15 fps. The camera's output buffer is 153,600 bytes for 320x240 at 2 bytes per pixel, but you only need 64,800 bytes for 240x135 after downscaling. Use a library like ArduCAM for ESP32 or PicoCamera for Pico to handle the conversion.

Timing is critical. The camera's VSYNC signal triggers a frame capture, and you must read the data within the frame period—typically 66ms for 15 fps. The display's refresh rate is 60 Hz, so you have 16.6ms per frame. To avoid tearing, use a double buffer: one buffer stores the camera's raw data, while the other sends data to the display. Set the display's SPI clock to 40 MHz, which gives a pixel transfer time of 0.025μs per pixel, or 6.75ms for 240x135 pixels. This leaves 9.85ms for processing, which is enough for bilinear interpolation on a 240 MHz ESP32. For the Pico at 133 MHz, the interpolation takes about 12ms, so you might need to reduce the SPI clock to 32 MHz to balance the load. The camera's PCLK runs at 6 MHz for QVGA, generating 1.92 million pixels per second, but the display's SPI at 40 MHz handles 40 million bits per second, so the bottleneck is the camera. To improve throughput, use DMA for SPI transfers. On the ESP32, configure the SPI driver to use DMA channel 1, which moves data from the buffer to the display without CPU intervention. The camera's data capture can also use DMA via the I2S peripheral—set the I2S_LC_CONF register to 0x0000 for parallel mode, then read the FIFO. This reduces CPU load to 20% for a 15 fps stream. On the Pico, the PIO handles the camera data, and the DMA channel 0 transfers it to the display's SPI TX FIFO. The PIO program uses 4 instructions: one for in, one for out, and two for synchronization. The total latency from camera capture to display is under 30ms, suitable for live video.

Image quality depends on the camera's settings and the display's color depth. The 1.14 inch IPS display supports 16-bit RGB565, which is 65,536 colors, while the OV2640 outputs 10-bit raw data but converts to RGB565 internally. Set the camera's color matrix to 0x4D for natural colors, and adjust the AEC (auto exposure control) to 0x00 for manual gain. The display's gamma correction is fixed, but you can adjust the brightness via the backlight PWM—set the frequency to 1 kHz to avoid flicker. For sharpness, the camera's 0x92 register controls sharpness, with a value of 0x10 for moderate enhancement. The display's pixel density is 261 PPI, so fine details are visible, but the small size (1.14 inches) means you won't see individual pixels. To reduce noise, set the camera's AGC (auto gain control) to 0x00 for low light, and use a 1/60s shutter speed. The display's response time is 10ms, so motion blur is minimal. For color accuracy, calibrate the display's RGB values using a lookup table—this is especially important for skin tones in video. The camera's white balance can be set to fluorescent mode (0x00) for indoor use. If you're using a lens, the OV2640's default focal length is 2.8mm, giving a 66-degree field of view, which matches the display's 1.14-inch diagonal. For a wider view, use a 1.8mm lens, but expect distortion at the edges. The display's viewing angles are 160 degrees, so the image looks consistent from any angle.

Power management is often overlooked. The camera module draws 120mA in active mode, and the display draws 25mA with backlight at 50% brightness. The ESP32 draws 80mA during operation, totaling 225mA. Use a 3.3V regulator with at least 500mA capacity, like the AMS1117-3.3, and add a 10μF and 0.1μF capacitor at the output. For battery operation, use a 3.7V LiPo battery with a boost converter to 3.3V, and monitor the voltage via the ESP32's ADC. The display's backlight can be turned off in sleep mode to save power—set the PWM pin to 0% duty cycle. The camera can be put into standby mode by setting register 0x09 to 0x00, reducing current to 10μA. This is useful for a battery-powered camera system. The total power consumption in active mode is 0.74W, which gives about 1.5 hours with a 1000mAh battery. For longer runtime, reduce the frame rate to 5 fps and lower the SPI clock to 20 MHz, cutting power to 0.4W. The display's refresh rate can also be lowered to 30 Hz by adjusting the SPI timing, but this may cause visible flicker. Use a timer interrupt to trigger frame capture every 200ms, and only update the display when new data is available. This reduces CPU usage to 10% and extends battery life to 3 hours.

Software implementation varies by platform. On the ESP32, use the Arduino framework with the TFT_eSPI library for the display and the ESP32-CAM library for the camera. Initialize the display with tft.begin() and set the rotation to 0 for portrait mode. The camera is initialized with esp_camera_init(), and you set the frame size to FRAMESIZE_QVGA. In the loop, capture a frame with esp_camera_fb_get(), then convert it to a 240x135 buffer using img2rgb565() from the library. The conversion function uses bilinear interpolation: for each pixel in the output, it averages the four nearest pixels in the input. The formula is out[x][y] = (in[x*2][y*2] + in[x*2+1][y*2] + in[x*2][y*2+1] + in[x*2+1][y*2+1]) / 4. This takes 2ms on the ESP32. Then, push the buffer to the display with tft.pushImage(0, 0, 240, 135, buffer). The total loop time is 20ms, achieving 50 fps, but the camera is limited to 15 fps, so the actual frame rate is 15 fps. For the Raspberry Pi Pico, use the MicroPython or C SDK. In C, use the PIO program to capture the camera's data into a DMA buffer. The PIO program uses a loop that reads 8 bits from the input pins and stores them in the FIFO. The DMA channel then transfers the data to a memory buffer. After capture, convert the 320x240 buffer to 240x135 using the same interpolation algorithm, but optimized for the Pico's ARM Cortex-M0+—use integer arithmetic instead of floating point. The conversion takes 8ms. Then, send the buffer to the display via SPI using the spi_write_blocking() function. The SPI clock is set to 32 MHz, giving a transfer time of 8ms. The total loop time is 16ms, achieving 60 fps, but the camera's limit is 15 fps, so the actual frame rate is 15 fps. For both platforms, use a semaphore to synchronize the camera capture and display update, preventing race conditions. The semaphore is signaled when the camera's VSYNC interrupt triggers, and the display update waits for the semaphore.

Common issues include image corruption, flickering, and low frame rate. Image corruption is usually due to loose wiring or insufficient power. Check the FPC connector for the camera—it should be fully inserted and locked. The display's SPI wires should be less than 10cm long to avoid signal degradation. Use twisted pairs for SCL and SDA to reduce crosstalk. Flickering is caused by a mismatch between the camera's frame rate and the display's refresh rate. To fix it, use a frame buffer that stores the last complete frame, and only update the display when the new frame is ready. This is done by setting a flag in the VSYNC interrupt and checking it in the loop. Low frame rate is often due to slow SPI clock or inefficient interpolation. Increase the SPI clock to 40 MHz, but check the display's datasheet—some 1.14 inch displays have a maximum SPI clock of 30 MHz. If the display supports 40 MHz, set it in the library. For interpolation, use a lookup table for the pixel coordinates to avoid division. The table precomputes the source coordinates for each output pixel, reducing the conversion time by 50%. Another issue is the camera's default JPEG output, which requires decoding. Set the camera to RGB565 mode by writing 0x00 to register 0x0C. This eliminates the need for a JPEG decoder, saving memory and time. The memory usage for the camera buffer is 153,600 bytes for 320x240, and the display buffer is 64,800 bytes for 240x135. On the ESP32, this fits in the 512KB SRAM, but on the Pico, you need to use the 264KB SRAM carefully—allocate the camera buffer as a static array and the display buffer as a DMA buffer. If you run out of memory, reduce the camera resolution to 160x120 and upscale to 240x135 using nearest-neighbor interpolation, which uses only 38,400 bytes for the camera buffer.

Advanced techniques include using the camera's FIFO buffer for burst capture and the display's partial update for reduced latency. The OV2640 has a built-in FIFO that can store up to 2 frames, but it's usually not used in continuous mode. Instead, enable the FIFO by setting register 0x04 to 0x01, and read the frame size from register 0x05-0x06. This allows you to capture a frame in 1ms, then process it later. The display supports partial update by setting the window coordinates with the setAddrWindow() function. This is useful for updating only the region of the display that changed, reducing SPI traffic. For example, if the camera detects motion, you can update only the 50x50 pixel area around the motion. This reduces the SPI transfer time to 0.4ms, allowing higher frame rates. To implement motion detection, compare the current frame with the previous frame using a pixel difference threshold of 30. If the total difference exceeds 1000 pixels, trigger a full update. Otherwise, update only the changed region. This technique is used in security cameras to save bandwidth. For the ESP32, use the esp_camera_fb_get() function to get the frame, then compare it with the previous frame stored in a buffer. The comparison takes 1ms for a 240x135 image. On the Pico, use the PIO to capture the frame, then compare it in the main loop. The motion detection threshold can be adjusted based on the lighting conditions—use a higher threshold in low light to avoid false triggers.

For a practical project, you can build a portable camera viewer with the 1.14 inch display and a camera module. Use an ESP32-S3 with 8MB PSRAM for better performance, as it allows storing multiple frames for buffering. The display's small size makes it ideal for a pocket-sized device. Connect a button to GPIO 0 to take a snapshot, and save the image to an SD card via SPI. The SD card uses the same SPI bus as the display, but you need to use a separate CS pin. The display's CS is GPIO 5, and the SD card's CS is GPIO 10. Use a multiplexer to share the SPI bus, or use two SPI peripherals on the ESP32-S3. The camera's snapshot is captured in JPEG format for storage, then converted to RGB565 for display. The JPEG conversion uses the jpg2rgb565() function from the ESP32-CAM library, which takes 10ms for a 320x240 image. The display shows the snapshot for 5 seconds, then returns to live view. The battery life is 2 hours with a 1000mAh battery. For a more advanced project, add Wi-Fi streaming to a smartphone. The ESP32 streams the camera feed via MJPEG over HTTP, and the display shows a local preview. The Wi-Fi bandwidth is 2 Mbps for 15 fps, which is within the ESP32's capabilities. The display's SPI bus is not affected by Wi-Fi, but the camera's data may be delayed if the Wi-Fi is busy. Use a task priority to give the camera capture higher priority than the Wi-Fi task. The display's refresh rate is independent of the Wi-Fi stream, so the local preview remains smooth.

When choosing components, consider the display's specifications. The 1.14 inch IPS display has a resolution of 240x135 pixels, a 16-bit color depth, and a 60 Hz refresh rate. The viewing angle is 160 degrees, and the contrast ratio is 1000:1. The SPI interface operates at 3.3V, and the maximum clock speed is 40 MHz. The camera module, such as the OV2640, has a resolution of 2 megapixels (1600x1200), but you'll use it in QVGA mode (320x240) for the display. The camera's field of view is 66 degrees, and the frame rate is 15 fps in QVGA. The camera's power consumption is 120mA, and the display's is 25mA. The total cost