摘要:本文主要介绍板载的摄像头(GC0308)的使用方法,实现UVC功能摄像以及Wi-Fi图传摄像的效果;
一、硬件介绍
产品特点
AtomS3R-CAM AI Chatbot 套件由控制器与语音底座两大核心部分组成;
控制器部分采用AtomS3R-CAM (集成0.3MP GC0308摄像头、9轴IMU、IR发射管等);
语音底座部分采用Atomic Voice Base (基于ES831音频编解码芯片);

主要特性
集成 ESP32-S3-PICO-1-N8R8 主控
0.3MP GC0308 摄像头
九轴传感器系统
8MB Flash 和 8MB PSRAM
集成红外发射管
可扩展的引脚与接口
全双工 I2S 语音
MEMS 数字麦克风
功能引脚示意图

二、功能实现
1、硬件介绍
AtomS3R-CAM开发板搭载了 0.3MP 的 GC0308 摄像头,支持图像采集,摄像头前配备了保护玻璃,用于防尘并提高图像质量;

引脚原理图
使能摄像头:摄像头初始化前,需要将GPIO18置为低电平以使能供电,该操作将同时将点亮电源指示灯;

特性

实物效果搭建

2、功能效果
1、UVC功能摄像头
可通过 USB 直连电脑,打开 PC 摄像头应用即可预览图像。
UVC功能可通过USB直连电脑,打开PC摄像头应用即可预览图像;
下载UVC功能固件
打开下载的 AtomS3R-CAM-Demo-V0.1.exe ,选择对应的COM 然后进行Burn烧录;


然后打开电脑的 相机 应用;


显示效果


2、Wi-Fi图传摄像头
开发板通过连接WIFI,在同一网络下的计算机的浏览器中输入这个IP地址,即可在网页看到实时传输的画面流;
三、代码编写
Wi-Fi图传功能 主要相关代码
#include <M5Unified.h>
#include <WiFi.h>
#include "esp_camera.h"
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#define SIOD_GPIO_NUM 12
#define SIOC_GPIO_NUM 9
#define Y9_GPIO_NUM 13
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 17
#define Y6_GPIO_NUM 4
#define Y5_GPIO_NUM 48
#define Y4_GPIO_NUM 46
#define Y3_GPIO_NUM 42
#define Y2_GPIO_NUM 3
#define VSYNC_GPIO_NUM 10
#define HREF_GPIO_NUM 14
#define PCLK_GPIO_NUM 40
#define POWER_GPIO_NUM 18
const char* ssid = "WIFI";
const char* password = "WIFI密码";
WiFiServer server(80);
camera_fb_t* fb = NULL;
uint8_t* out_jpg = NULL;
size_t out_jpg_len = 0;
static void jpegStream(WiFiClient* client);
static camera_config_t camera_config = {
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
.pin_sscb_sda = SIOD_GPIO_NUM,
.pin_sscb_scl = SIOC_GPIO_NUM,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
.pin_d5 = Y7_GPIO_NUM,
.pin_d4 = Y6_GPIO_NUM,
.pin_d3 = Y5_GPIO_NUM,
.pin_d2 = Y4_GPIO_NUM,
.pin_d1 = Y3_GPIO_NUM,
.pin_d0 = Y2_GPIO_NUM,
.pin_vsync = VSYNC_GPIO_NUM,
.pin_href = HREF_GPIO_NUM,
.pin_pclk = PCLK_GPIO_NUM,
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_RGB565,
.frame_size = FRAMESIZE_QVGA, //FRAMESIZE_VGA
.jpeg_quality = 12, // 0-63
.fb_count = 2,
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_LATEST,
.sccb_i2c_port = 0,
};
void setup() {
Serial.begin(115200);
pinMode(POWER_GPIO_NUM, OUTPUT);
digitalWrite(POWER_GPIO_NUM, LOW);
delay(500);
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK) {
Serial.println("摄像头初始化失败");
delay(1000);
esp_restart();
} else {
Serial.println("摄像头初始化成功");
}
delay(100);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
WiFi.setSleep(false);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
jpegStream(&client);
}
}
// 断开连接
client.stop();
Serial.println("断开连接");
}
}
// 画面传输
#define PART_BOUNDARY "123456789000000000000987654321"
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
static void jpegStream(WiFiClient* client) {
Serial.println("Image stream start");
client->println("HTTP/1.1 200 OK");
client->printf("Content-Type: %s\r\n", _STREAM_CONTENT_TYPE);
client->println("Content-Disposition: inline; filename=capture.jpg");
client->println("Access-Control-Allow-Origin: *");
client->println();
static int64_t last_frame = 0;
if (!last_frame) {
last_frame = esp_timer_get_time();
}
for (;;) {
fb = esp_camera_fb_get();
if (fb) {
frame2jpg(fb, 255, &out_jpg, &out_jpg_len);
Serial.printf("pic size: %d\n", out_jpg_len);
client->print(_STREAM_BOUNDARY);
client->printf(_STREAM_PART, out_jpg_len);
int32_t to_sends = out_jpg_len;
int32_t now_sends = 0;
uint8_t* out_buf = out_jpg;
uint32_t packet_len = 8 * 1024;
while (to_sends > 0) {
now_sends = to_sends > packet_len ? packet_len : to_sends;
if (client->write(out_buf, now_sends) == 0) {
goto client_exit;
}
out_buf += now_sends;
to_sends -= now_sends;
}
int64_t fr_end = esp_timer_get_time();
int64_t frame_time = fr_end - last_frame;
last_frame = fr_end;
frame_time /= 1000;
Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", (long unsigned int)(out_jpg_len / 1024),
(long unsigned int)frame_time, 1000.0 / (long unsigned int)frame_time);
if (fb) {
esp_camera_fb_return(fb);
fb = NULL;
}
if (out_jpg) {
free(out_jpg);
out_jpg = NULL;
out_jpg_len = 0;
}
} else {
Serial.println("摄像头获取失败");
}
}
client_exit:
if (fb) {
esp_camera_fb_return(fb);
fb = NULL;
}
if (out_jpg) {
free(out_jpg);
out_jpg = NULL;
out_jpg_len = 0;
}
client->stop();
Serial.printf("传输结束\r\n");
}四、程序烧录
1、连接USB数据线至开发板;
2、选择端口号对应的开发板;
3、点击 上传 烧录程序到开发板上;

五、效果演示
Wi-Fi图传效果






我要赚赏金
