I am trying to stream video from an ESP32-wrover cam dev board to a round tft 240x240 board. I can get the web stream example to work ok and tft_espi graphics examples to work, but am have trouble getting the camera to stream to the tft. The camera and tft initialize ok and the loading... text on the screen works, but then there are only vertical strips. It seems the camera is only buffering part of the image - (see serial print below). Any ideas to fix my problem?
I am using ESP board manager 2.0.17
#include "esp_camera.h"
#include <Arduino.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
// Camera pin definitions
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
TFT_eSprite spr = TFT_eSprite(&tft);
camera_config_t config;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
// Initialize the TFT screen
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_NAVY);
delay(200);
tft.fillScreen(TFT_BLACK);
delay(100);
// Initialize the camera
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_240X240;
config.pixel_format = PIXFORMAT_RGB565;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 16;
config.fb_count = 1;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return;
}
Serial.println("Camera initialized successfully");
delay(100);
// Create a sprite
if (spr.createSprite(240, 240) == nullptr) {
Serial.println("Failed to create sprite buffer. Not enough memory.");
return;
}
Serial.println("Sprite initialized successfully");
delay(1000);
tft.setTextColor(TFT_WHITE);
tft.drawString("Loading...", 105, 105, 2);
delay(2000);
}
void loop() {
Serial.println("Loop start");
// Take a picture
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
Serial.println("Camera capture successful");
// Process the image data here
uint16_t *spritePtr = (uint16_t *)spr.getPointer();
// Render the image to the sprite
for (size_t i = 0; i < 240 * 240; i++) {
spritePtr[i] = fb->buf[i * 2 + 1] << 8 | fb->buf[i * 2];
}
// Debug: Print first few pixels to verify data
for (size_t i = 0; i < 30; i++) {
Serial.printf("Pixel %d: 0x%04x\n", i, spritePtr[i]);
}
spr.pushSprite(0, 0);
// Return the frame buffer back to the driver for reuse
esp_camera_fb_return(fb);
Serial.println("Loop end");
//delay(1000);
}
Serial print
Camera initialized successfully
Sprite initialized successfully
Loop start
Camera capture successful
Pixel 0: 0x0000
Pixel 1: 0x0000
Pixel 2: 0x0000
Pixel 3: 0x0000
Pixel 4: 0x0800
Pixel 5: 0x8c88
Pixel 6: 0xffee
Pixel 7: 0xffff
Pixel 8: 0x0000
Pixel 9: 0x0000
Pixel 10: 0x0000
Pixel 11: 0x0000
Pixel 12: 0x0000
Pixel 13: 0x0000
Pixel 14: 0x0000
Pixel 15: 0x0000
Pixel 16: 0x0000
Pixel 17: 0x0000
Pixel 18: 0x0000
Pixel 19: 0x0800
Pixel 20: 0xcc88
Pixel 21: 0xffee
Pixel 22: 0xffff
Pixel 23: 0xffff
Pixel 24: 0x0000
Pixel 25: 0x0000
Pixel 26: 0x0000
Pixel 27: 0x0000
Pixel 28: 0x0000
Pixel 29: 0x0000