最近笔者在学习使用安信可的ESP32-CAM开发板,该开发板自带一个OV2640摄像头。
官方提供的例程可以将摄像头视频通过WIFI传输到网页显示,而笔者手里正好有一块240x240像素的屏幕,便想将摄像头的图像显示到该屏幕上。
从esp32-camera\sensor.h 头文件中可以找到
#define OV9650_PID (0x96)
#define OV2640_PID (0x26)
#define OV7725_PID (0x77)
#define OV3660_PID (0x36)
typedef enum {
FRAMESIZE_QQVGA, // 160x120
FRAMESIZE_QQVGA2, // 128x160
FRAMESIZE_QCIF, // 176x144
FRAMESIZE_HQVGA, // 240x176
FRAMESIZE_QVGA, // 320x240
FRAMESIZE_CIF, // 400x296
FRAMESIZE_VGA, // 640x480
FRAMESIZE_SVGA, // 800x600
FRAMESIZE_XGA, // 1024x768
FRAMESIZE_SXGA, // 1280x1024
FRAMESIZE_UXGA, // 1600x1200
FRAMESIZE_QXGA, // 2048*1536
FRAMESIZE_INVALID
} framesize_t;
typedef enum {
PIXFORMAT_RGB565, // 2BPP/RGB565
PIXFORMAT_YUV422, // 2BPP/YUV422
PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
PIXFORMAT_JPEG, // JPEG/COMPRESSED
PIXFORMAT_RGB888, // 3BPP/RGB888
PIXFORMAT_RAW, // RAW
PIXFORMAT_RGB444, // 3BP2P/RGB444
PIXFORMAT_RGB555, // 3BP2P/RGB555
} pixformat_t;
可以看到Arduino core for the ESP32库支持4种摄像头,ESP32-CAM开发板搭载的是OV2640,而IPS屏幕像素为240x240,所以选FRAMESIZE_HQVGA(240x176)格式。
查看
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
void Arduino_ST7789::drawPixel(int16_t x, int16_t y, uint16_t color) {
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
setAddrWindow(x,y,x+1,y+1);
SPI_BEGIN_TRANSACTION();
DC_HIGH();
CS_LOW();
spiwrite(color >> 8);
spiwrite(color);
CS_HIGH();
SPI_END_TRANSACTION();
}
可以看到该驱动库采用RGB颜色空间,比如
RED=0xF800=11111_000000_00000,
GREEN=0x07E0=00000_111111_00000,BLUE=0x001F=00000_000000_11111,所以每个像素点为16位数据,即RGB565格式。
使用以下函数将OV2640图像格式设置为RGB565,分辨率设置为240x176。
.pixel_format = PIXFORMAT_RGB565,
.frame_size = FRAMESIZE_HQVGA,
使用以下函数将单帧图像数据通过串口输出到串口调试助手
Serial.write(fb->buf, fb->len);
接收数据为下图所示,单帧RGB565格式图像数据为84480字节,刚好等于 240 x 176 x 2,该帧图像数据并不像JPEG图像输出数据那样有头部格式字节,所以当笔者将该图像数据存到内存卡里时,在电脑端会显示无法打开该图像。
下图为单帧JPEG格式图像数据:
这个单帧数据数据量有点问题,且每次接收到的都不太一样,可能传输过程中出了点错误。
但是数据前面的FF DB FF E0 是正确的JPEG格式。
而且每帧的数据量比RGB565格式少很多,后面有时间再研究图像格式。
好了。根据上面的内容我们就可以写程序了。
直接根据ESP32官方camera例程修改。
主要的函数为:
每一个像素点数据为RGB565单帧数据的每两个字节组合而成。
void camera_show(void)
{
unsigned long i=0;
camera_fb_t *fb = esp_camera_fb_get();
//单帧图像数据输出
// delay(2000);
// delay(2000);
// delay(2000);
// Serial.write(fb->buf, fb->len);
// delay(2000);
// delay(2000);
// delay(2000);
for(uint8_t y = 0; y <SCREEN_HEIGHT; y ++)
{
for(uint8_t x = 0; x <SCREEN_WIDTH; x ++)
{
//RGB565格式 240X176
tft.drawPixel(x,60+y,((fb->buf[2*i])<<8)|(fb->buf[2*i+1]));
i++;
}
}
esp_camera_fb_return(fb);
}
这个屏幕正常的显示效果是有目共睹的好,但是测试显示效果不太清晰,可能还需要设置一下OV2640的一些参数才能达到更清晰的效果,然后笔者在屏幕的左上角显示了帧率,可以看到平均两秒一帧(真是有够慢的)。由于是arduino开发,不太好改速率,后面有时间慢慢深入库文件再来提高速度吧。
完整程序及相关驱动库链接