Skip to content

Commit 2b553ce

Browse files
larideHorion0415
andauthored
feat: add camera functions (ESP-SparkBot) (#687)
Co-authored-by: lvhaiyu <[email protected]>
1 parent 391aa74 commit 2b553ce

File tree

3 files changed

+112
-7
lines changed

3 files changed

+112
-7
lines changed

main/boards/common/esp32_camera.cc

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,34 @@ Esp32Camera::Esp32Camera(const camera_config_t& config) {
3030
preview_image_.header.cf = LV_COLOR_FORMAT_RGB565;
3131
preview_image_.header.flags = LV_IMAGE_FLAGS_ALLOCATED | LV_IMAGE_FLAGS_MODIFIABLE;
3232

33-
if (config.frame_size == FRAMESIZE_VGA) {
34-
preview_image_.header.w = 640;
35-
preview_image_.header.h = 480;
36-
} else if (config.frame_size == FRAMESIZE_QVGA) {
37-
preview_image_.header.w = 320;
38-
preview_image_.header.h = 240;
33+
switch (config.frame_size) {
34+
case FRAMESIZE_SVGA:
35+
preview_image_.header.w = 800;
36+
preview_image_.header.h = 600;
37+
break;
38+
case FRAMESIZE_VGA:
39+
preview_image_.header.w = 640;
40+
preview_image_.header.h = 480;
41+
break;
42+
case FRAMESIZE_QVGA:
43+
preview_image_.header.w = 320;
44+
preview_image_.header.h = 240;
45+
break;
46+
case FRAMESIZE_128X128:
47+
preview_image_.header.w = 128;
48+
preview_image_.header.h = 128;
49+
break;
50+
case FRAMESIZE_240X240:
51+
preview_image_.header.w = 240;
52+
preview_image_.header.h = 240;
53+
break;
54+
default:
55+
ESP_LOGE(TAG, "Unsupported frame size: %d, image preview will not be shown", config.frame_size);
56+
preview_image_.data_size = 0;
57+
preview_image_.data = nullptr;
58+
return;
3959
}
60+
4061
preview_image_.header.stride = preview_image_.header.w * 2;
4162
preview_image_.data_size = preview_image_.header.w * preview_image_.header.h * 2;
4263
preview_image_.data = (uint8_t*)heap_caps_malloc(preview_image_.data_size, MALLOC_CAP_SPIRAM);
@@ -81,6 +102,16 @@ bool Esp32Camera::Capture() {
81102
}
82103
}
83104

105+
// 如果预览图片 buffer 为空,则跳过预览
106+
// 但仍返回 true,因为此时图像可以上传至服务器
107+
if (preview_image_.data_size == 0) {
108+
ESP_LOGW(TAG, "Skip preview because of unsupported frame size");
109+
return true;
110+
}
111+
if (preview_image_.data == nullptr) {
112+
ESP_LOGE(TAG, "Preview image data is not initialized");
113+
return true;
114+
}
84115
// 显示预览图片
85116
auto display = Board::GetInstance().GetDisplay();
86117
if (display != nullptr) {
@@ -169,7 +200,7 @@ std::string Esp32Camera::Explain(const std::string& question) {
169200
frame2jpg_cb(fb_, 80, [](void* arg, size_t index, const void* data, size_t len) -> unsigned int {
170201
auto jpeg_queue = (QueueHandle_t)arg;
171202
JpegChunk chunk = {
172-
.data = (uint8_t*)heap_caps_malloc(len, MALLOC_CAP_SPIRAM),
203+
.data = (uint8_t*)heap_caps_aligned_alloc(16, len, MALLOC_CAP_SPIRAM),
173204
.len = len
174205
};
175206
memcpy(chunk.data, data, len);

main/boards/esp-sparkbot/config.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,32 @@ typedef enum {
6868
LIGHT_MODE_MAX
6969
} light_mode_t;
7070

71+
/* Camera PINs*/
72+
#define SPARKBOT_CAMERA_XCLK (GPIO_NUM_15)
73+
#define SPARKBOT_CAMERA_PCLK (GPIO_NUM_13)
74+
#define SPARKBOT_CAMERA_VSYNC (GPIO_NUM_6)
75+
#define SPARKBOT_CAMERA_HSYNC (GPIO_NUM_7)
76+
#define SPARKBOT_CAMERA_D0 (GPIO_NUM_11)
77+
#define SPARKBOT_CAMERA_D1 (GPIO_NUM_9)
78+
#define SPARKBOT_CAMERA_D2 (GPIO_NUM_8)
79+
#define SPARKBOT_CAMERA_D3 (GPIO_NUM_10)
80+
#define SPARKBOT_CAMERA_D4 (GPIO_NUM_12)
81+
#define SPARKBOT_CAMERA_D5 (GPIO_NUM_18)
82+
#define SPARKBOT_CAMERA_D6 (GPIO_NUM_17)
83+
#define SPARKBOT_CAMERA_D7 (GPIO_NUM_16)
84+
85+
#define SPARKBOT_CAMERA_PWDN (GPIO_NUM_NC)
86+
#define SPARKBOT_CAMERA_RESET (GPIO_NUM_NC)
87+
#define SPARKBOT_CAMERA_XCLK (GPIO_NUM_15)
88+
#define SPARKBOT_CAMERA_PCLK (GPIO_NUM_13)
89+
#define SPARKBOT_CAMERA_VSYNC (GPIO_NUM_6)
90+
#define SPARKBOT_CAMERA_HSYNC (GPIO_NUM_7)
91+
92+
#define SPARKBOT_CAMERA_XCLK_FREQ (16000000)
93+
#define SPARKBOT_LEDC_TIMER (LEDC_TIMER_0)
94+
#define SPARKBOT_LEDC_CHANNEL (LEDC_CHANNEL_0)
95+
96+
#define SPARKBOT_CAMERA_SIOD (GPIO_NUM_NC)
97+
#define SPARKBOT_CAMERA_SIOC (GPIO_NUM_NC)
98+
7199
#endif // _BOARD_CONFIG_H_

main/boards/esp-sparkbot/esp_sparkbot_board.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <driver/i2c_master.h>
1414
#include <driver/spi_common.h>
1515

16+
#include "esp32_camera.h"
17+
1618
#define TAG "esp_sparkbot"
1719

1820
LV_FONT_DECLARE(font_puhui_20_4);
@@ -45,6 +47,7 @@ class EspSparkBot : public WifiBoard {
4547
i2c_master_bus_handle_t i2c_bus_;
4648
Button boot_button_;
4749
Display* display_;
50+
Esp32Camera* camera_;
4851

4952
void InitializeI2c() {
5053
// Initialize I2C peripheral
@@ -122,6 +125,44 @@ class EspSparkBot : public WifiBoard {
122125
});
123126
}
124127

128+
void InitializeCamera() {
129+
camera_config_t camera_config = {};
130+
131+
camera_config.pin_pwdn = SPARKBOT_CAMERA_PWDN;
132+
camera_config.pin_reset = SPARKBOT_CAMERA_RESET;
133+
camera_config.pin_xclk = SPARKBOT_CAMERA_XCLK;
134+
camera_config.pin_pclk = SPARKBOT_CAMERA_PCLK;
135+
camera_config.pin_sscb_sda = SPARKBOT_CAMERA_SIOD;
136+
camera_config.pin_sscb_scl = SPARKBOT_CAMERA_SIOC;
137+
138+
camera_config.pin_d0 = SPARKBOT_CAMERA_D0;
139+
camera_config.pin_d1 = SPARKBOT_CAMERA_D1;
140+
camera_config.pin_d2 = SPARKBOT_CAMERA_D2;
141+
camera_config.pin_d3 = SPARKBOT_CAMERA_D3;
142+
camera_config.pin_d4 = SPARKBOT_CAMERA_D4;
143+
camera_config.pin_d5 = SPARKBOT_CAMERA_D5;
144+
camera_config.pin_d6 = SPARKBOT_CAMERA_D6;
145+
camera_config.pin_d7 = SPARKBOT_CAMERA_D7;
146+
147+
camera_config.pin_vsync = SPARKBOT_CAMERA_VSYNC;
148+
camera_config.pin_href = SPARKBOT_CAMERA_HSYNC;
149+
camera_config.pin_pclk = SPARKBOT_CAMERA_PCLK;
150+
camera_config.xclk_freq_hz = SPARKBOT_CAMERA_XCLK_FREQ;
151+
camera_config.ledc_timer = SPARKBOT_LEDC_TIMER;
152+
camera_config.ledc_channel = SPARKBOT_LEDC_CHANNEL;
153+
camera_config.fb_location = CAMERA_FB_IN_PSRAM;
154+
155+
camera_config.sccb_i2c_port = I2C_NUM_0;
156+
157+
camera_config.pixel_format = PIXFORMAT_RGB565;
158+
camera_config.frame_size = FRAMESIZE_240X240;
159+
camera_config.jpeg_quality = 12;
160+
camera_config.fb_count = 1;
161+
camera_config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
162+
163+
camera_ = new Esp32Camera(camera_config);
164+
}
165+
125166
// 物联网初始化,添加对 AI 可见设备
126167
void InitializeIot() {
127168
auto& thing_manager = iot::ThingManager::GetInstance();
@@ -137,6 +178,7 @@ class EspSparkBot : public WifiBoard {
137178
InitializeDisplay();
138179
InitializeButtons();
139180
InitializeIot();
181+
InitializeCamera();
140182
GetBacklight()->RestoreBrightness();
141183
}
142184

@@ -155,6 +197,10 @@ class EspSparkBot : public WifiBoard {
155197
static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT);
156198
return &backlight;
157199
}
200+
201+
virtual Camera* GetCamera() override {
202+
return camera_;
203+
}
158204
};
159205

160206
DECLARE_BOARD(EspSparkBot);

0 commit comments

Comments
 (0)