This repository was archived by the owner on Dec 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathcameraHandler.cpp
More file actions
301 lines (259 loc) · 10.6 KB
/
cameraHandler.cpp
File metadata and controls
301 lines (259 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#include "cameraHandler.hpp"
CameraHandler::CameraHandler(ProjectConfig& configManager)
: configManager(configManager) {}
void CameraHandler::setupCameraPinout() {
// Workaround for espM5SStack not having a defined camera
#ifdef CAMERA_MODULE_NAME
log_i("[Camera]: Camera module is %s", CAMERA_MODULE_NAME);
#else
log_i("[Camera]: Camera module is undefined");
#endif
// camera external clock signal frequencies
// 10000000 stable
// 16500000 optimal freq on ESP32-CAM (default)
// 20000000 max freq on ESP32-CAM
// 24000000 optimal freq on ESP32-S3
int xclk_freq_hz = 16500000;
#if CONFIG_CAMERA_MODULE_ESP_EYE
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declare it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("ESP_EYE");
#elif CONFIG_CAMERA_MODULE_CAM_BOARD
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declare it as pullup input
**/
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
log_i("CAM_BOARD");
#endif
#if ETVR_EYE_TRACKER_USB_API
/* ESP32-S3 is capable of using higher freqs */
xclk_freq_hz = 24000000;
#endif
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.grab_mode = CAMERA_GRAB_LATEST;
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 = xclk_freq_hz;
}
void CameraHandler::setupBasicResolution() {
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_240X240;
if (!psramFound()) {
log_e("[Camera]: Did not find psram, setting lower image quality");
config.fb_location = CAMERA_FB_IN_DRAM;
config.jpeg_quality = 9;
config.fb_count = 2;
return;
}
log_d("[Camera]: Found psram, setting the higher image quality");
config.jpeg_quality = 7; // 0-63 lower number = higher quality, more latency
// and less fps 7 for most fps, 5 for best quality
config.fb_count = 3;
log_d("[Camera]: Setting fb_location to CAMERA_FB_IN_PSRAM");
}
void CameraHandler::setupCameraSensor() {
log_d("[Camera]: Setting up camera sensor");
camera_sensor = esp_camera_sensor_get();
// fixes corrupted jpegs, https://github.com/espressif/esp32-camera/issues/203
// documentation https://www.uctronics.com/download/cam_module/OV2640DS.pdf
camera_sensor->set_reg(
camera_sensor, 0xff, 0xff,
0x00); // banksel, here we're directly writing to the registers.
// 0xFF==0x00 is the first bank, there's also 0xFF==0x01
camera_sensor->set_reg(camera_sensor, 0xd3, 0xff, 5); // clock
camera_sensor->set_brightness(camera_sensor, 2); // -2 to 2
camera_sensor->set_contrast(camera_sensor, 2); // -2 to 2
camera_sensor->set_saturation(camera_sensor, -2); // -2 to 2
// white balance control
camera_sensor->set_whitebal(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_awb_gain(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_wb_mode(camera_sensor,
0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 -
// Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
// controls the exposure
camera_sensor->set_exposure_ctrl(camera_sensor,
0); // 0 = disable , 1 = enable
camera_sensor->set_aec2(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_ae_level(camera_sensor, 0); // -2 to 2
camera_sensor->set_aec_value(camera_sensor, 300); // 0 to 1200
// controls the gain
camera_sensor->set_gain_ctrl(camera_sensor, 0); // 0 = disable , 1 = enable
// automatic gain control gain, controls by how much the resulting image
// should be amplified
camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30
camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t)6); // 0 to 6
// black and white pixel correction, averages the white and black spots
camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable
camera_sensor->set_wpc(camera_sensor, 1); // 0 = disable , 1 = enable
// digital clamp white balance
camera_sensor->set_dcw(camera_sensor, 0); // 0 = disable , 1 = enable
// gamma correction
camera_sensor->set_raw_gma(
camera_sensor,
1); // 0 = disable , 1 = enable (makes much lighter and noisy)
camera_sensor->set_lenc(camera_sensor, 0); // 0 = disable , 1 = enable // 0 =
// disable , 1 = enable
camera_sensor->set_colorbar(camera_sensor, 0); // 0 = disable , 1 = enable
camera_sensor->set_special_effect(
camera_sensor,
2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint,
// 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
log_d("[Camera]: Setting up camera sensor done");
}
bool CameraHandler::setupCamera() {
log_d("[Camera]: Setting up camera pinout");
this->setupCameraPinout();
log_d("[Camera]: Setting up camera with resolution");
this->setupBasicResolution();
log_d("[Camera]: Initializing camera...");
esp_err_t hasCameraBeenInitialized = esp_camera_init(&config);
log_d("[Camera]: Camera initialized: %s \r\n",
esp_err_to_name(hasCameraBeenInitialized));
if (hasCameraBeenInitialized != ESP_OK) {
log_e("[Camera]: Camera initialization failed with error: %s \r\n",
esp_err_to_name(hasCameraBeenInitialized));
log_e(
"[Camera]: Camera most likely not seated properly in the socket. "
"Please "
"fix the "
"camera and reboot the device.\r\n");
ledStateManager.setState(LEDStates_e::_Camera_Error);
return false;
}
this->setupCameraSensor();
return true;
}
void CameraHandler::loadConfigData() {
log_d("[Camera]: Loading camera config data");
ProjectConfig::CameraConfig_t cameraConfig = configManager.getCameraConfig();
this->setHFlip(cameraConfig.href);
this->setVFlip(cameraConfig.vflip);
this->setCameraResolution((framesize_t)cameraConfig.framesize);
camera_sensor->set_quality(camera_sensor, cameraConfig.quality);
camera_sensor->set_agc_gain(camera_sensor, cameraConfig.brightness);
log_d("Loading camera config data done");
}
int CameraHandler::setCameraResolution(framesize_t frameSize) {
if (camera_sensor->pixformat == PIXFORMAT_JPEG) {
try {
/*
sensor crop is relitive to one of these base resolutions
baseRes = 0 \\ 1600 x 1200 UXGA
baseRes = 1 \\ 800 x 600 SVGA
baseRes = 2 \\ 400 x 296 CIF
Setting your ROIsize to its respective Y-value above will prevent scaling
OutputSize should always be 240
*/
int outputSize = 240;
// CIF samples
/*// mimic old way FRAMESIZE_240X240 without breaking aspect ratio
int baseRes = 2; //CIF
int ROIsize = 296;
int startPointX = 52;
int startPointY = 0; */
// crop into the middle of a CIF image
int baseRes = 2; //CIF
int ROIsize = 240; // only cropping. no scaling. if using a 160º camera, this will look like a 130º lens.
int startPointX = 80;
int startPointY = 28;
/*// crop into the top left right of a CIF image
int baseRes = 2; //CIF
int ROIsize = 240; // only cropping. no scaling. if using a 160º camera, this will look like a 130º lens.
int startPointX = 0;
int startPointY = 0;*/
/*// crop into the bottom right of a CIF image
//int baseRes = 2; //CIF
//int ROIsize = 240; // only cropping. no scaling. if using a 160º camera, this will look like a 130º lens.
//int startPointX = 160;
//int startPointY = 56;*/
//SVGA samples
/*// crop into the middle of a SVGA image and rescale to 240. if using a 160º camera, it will look like a 120º lens.
int baseRes = 1; //SVGA
int ROIsize = 450;
int startPointX = 175;
int startPointY = 75;*/
/*// crop into the middle of a SVGA image and rescale to 240. if using a 160º camera, it will look like a 90º lens.
int baseRes = 1; //SVGA
int ROIsize = 340;
int startPointX = 230;
int startPointY = 130;*/
/*// pure crop into the middle of a SVGA image no scaling. if using a 160º camera, it will look like a 66º lens.
int baseRes = 1; //SVGA
int ROIsize = 240;
int startPointX = 280;
int startPointY = 180;*/
return camera_sensor->set_res_raw(camera_sensor, baseRes, 0, 0, 0, startPointX, startPointY, ROIsize, ROIsize, outputSize, outputSize, 0, 0);
} catch (...) {
// they sent us a malformed or unsupported frameSize - rather than crash -
// tell them about it
return -1;
}
}
return -1;
}
int CameraHandler::setVFlip(int direction) {
return camera_sensor->set_vflip(camera_sensor, direction);
}
int CameraHandler::setHFlip(int direction) {
return camera_sensor->set_hmirror(camera_sensor, direction);
}
int CameraHandler::setVieWindow(int offsetX,
int offsetY,
int outputX,
int outputY) {
return 0;
}
//! either hardware(1) or software(0)
void CameraHandler::resetCamera(bool type) {
if (type) {
// power cycle the camera module (handy if camera stops responding)
digitalWrite(PWDN_GPIO_NUM, HIGH); // turn power off to camera module
Network_Utilities::my_delay(0.3); // a for loop with a delay of 300ms
digitalWrite(PWDN_GPIO_NUM, LOW);
Network_Utilities::my_delay(0.3);
setupCamera();
} else {
// reset via software (handy if you wish to change resolution or image type
// etc. - see test procedure)
esp_camera_deinit();
Network_Utilities::my_delay(0.05);
setupCamera();
}
}
void CameraHandler::update(ConfigState_e event) {
switch (event) {
case ConfigState_e::configLoaded:
this->setupCamera();
this->loadConfigData();
break;
case ConfigState_e::cameraConfigUpdated:
this->loadConfigData();
break;
default:
break;
}
}
std::string CameraHandler::getName() {
return "CameraHandler";
}