├── FaceDoorEntryESP32Cam.ino ├── HTML_interface.html ├── README.md ├── camera_index.h ├── camera_pins.h ├── partitions.csv └── rzo_partitions.csv /FaceDoorEntryESP32Cam.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "esp_http_server.h" 3 | #include "esp_timer.h" 4 | #include "esp_camera.h" 5 | #include "camera_index.h" 6 | #include "Arduino.h" 7 | #include "fd_forward.h" 8 | #include "fr_forward.h" 9 | #include "fr_flash.h" 10 | 11 | const char* ssid = "NSA"; 12 | const char* password = "Orange"; 13 | 14 | #define ENROLL_CONFIRM_TIMES 5 15 | #define FACE_ID_SAVE_NUMBER 7 16 | 17 | // Select camera model 18 | //#define CAMERA_MODEL_WROVER_KIT 19 | //#define CAMERA_MODEL_ESP_EYE 20 | //#define CAMERA_MODEL_M5STACK_PSRAM 21 | //#define CAMERA_MODEL_M5STACK_WIDE 22 | #define CAMERA_MODEL_AI_THINKER 23 | #include "camera_pins.h" 24 | 25 | using namespace websockets; 26 | WebsocketsServer socket_server; 27 | 28 | camera_fb_t * fb = NULL; 29 | 30 | long current_millis; 31 | long last_detected_millis = 0; 32 | 33 | #define relay_pin 2 // pin 12 can also be used 34 | unsigned long door_opened_millis = 0; 35 | long interval = 5000; // open lock for ... milliseconds 36 | bool face_recognised = false; 37 | 38 | void app_facenet_main(); 39 | void app_httpserver_init(); 40 | 41 | typedef struct 42 | { 43 | uint8_t *image; 44 | box_array_t *net_boxes; 45 | dl_matrix3d_t *face_id; 46 | } http_img_process_result; 47 | 48 | 49 | static inline mtmn_config_t app_mtmn_config() 50 | { 51 | mtmn_config_t mtmn_config = {0}; 52 | mtmn_config.type = FAST; 53 | mtmn_config.min_face = 80; 54 | mtmn_config.pyramid = 0.707; 55 | mtmn_config.pyramid_times = 4; 56 | mtmn_config.p_threshold.score = 0.6; 57 | mtmn_config.p_threshold.nms = 0.7; 58 | mtmn_config.p_threshold.candidate_number = 20; 59 | mtmn_config.r_threshold.score = 0.7; 60 | mtmn_config.r_threshold.nms = 0.7; 61 | mtmn_config.r_threshold.candidate_number = 10; 62 | mtmn_config.o_threshold.score = 0.7; 63 | mtmn_config.o_threshold.nms = 0.7; 64 | mtmn_config.o_threshold.candidate_number = 1; 65 | return mtmn_config; 66 | } 67 | mtmn_config_t mtmn_config = app_mtmn_config(); 68 | 69 | face_id_name_list st_face_list; 70 | static dl_matrix3du_t *aligned_face = NULL; 71 | 72 | httpd_handle_t camera_httpd = NULL; 73 | 74 | typedef enum 75 | { 76 | START_STREAM, 77 | START_DETECT, 78 | SHOW_FACES, 79 | START_RECOGNITION, 80 | START_ENROLL, 81 | ENROLL_COMPLETE, 82 | DELETE_ALL, 83 | } en_fsm_state; 84 | en_fsm_state g_state; 85 | 86 | typedef struct 87 | { 88 | char enroll_name[ENROLL_NAME_LEN]; 89 | } httpd_resp_value; 90 | 91 | httpd_resp_value st_name; 92 | 93 | void setup() { 94 | Serial.begin(115200); 95 | Serial.setDebugOutput(true); 96 | Serial.println(); 97 | 98 | digitalWrite(relay_pin, LOW); 99 | pinMode(relay_pin, OUTPUT); 100 | 101 | camera_config_t config; 102 | config.ledc_channel = LEDC_CHANNEL_0; 103 | config.ledc_timer = LEDC_TIMER_0; 104 | config.pin_d0 = Y2_GPIO_NUM; 105 | config.pin_d1 = Y3_GPIO_NUM; 106 | config.pin_d2 = Y4_GPIO_NUM; 107 | config.pin_d3 = Y5_GPIO_NUM; 108 | config.pin_d4 = Y6_GPIO_NUM; 109 | config.pin_d5 = Y7_GPIO_NUM; 110 | config.pin_d6 = Y8_GPIO_NUM; 111 | config.pin_d7 = Y9_GPIO_NUM; 112 | config.pin_xclk = XCLK_GPIO_NUM; 113 | config.pin_pclk = PCLK_GPIO_NUM; 114 | config.pin_vsync = VSYNC_GPIO_NUM; 115 | config.pin_href = HREF_GPIO_NUM; 116 | config.pin_sscb_sda = SIOD_GPIO_NUM; 117 | config.pin_sscb_scl = SIOC_GPIO_NUM; 118 | config.pin_pwdn = PWDN_GPIO_NUM; 119 | config.pin_reset = RESET_GPIO_NUM; 120 | config.xclk_freq_hz = 20000000; 121 | config.pixel_format = PIXFORMAT_JPEG; 122 | //init with high specs to pre-allocate larger buffers 123 | if (psramFound()) { 124 | config.frame_size = FRAMESIZE_UXGA; 125 | config.jpeg_quality = 10; 126 | config.fb_count = 2; 127 | } else { 128 | config.frame_size = FRAMESIZE_SVGA; 129 | config.jpeg_quality = 12; 130 | config.fb_count = 1; 131 | } 132 | 133 | #if defined(CAMERA_MODEL_ESP_EYE) 134 | pinMode(13, INPUT_PULLUP); 135 | pinMode(14, INPUT_PULLUP); 136 | #endif 137 | 138 | // camera init 139 | esp_err_t err = esp_camera_init(&config); 140 | if (err != ESP_OK) { 141 | Serial.printf("Camera init failed with error 0x%x", err); 142 | return; 143 | } 144 | 145 | sensor_t * s = esp_camera_sensor_get(); 146 | s->set_framesize(s, FRAMESIZE_QVGA); 147 | 148 | #if defined(CAMERA_MODEL_M5STACK_WIDE) 149 | s->set_vflip(s, 1); 150 | s->set_hmirror(s, 1); 151 | #endif 152 | 153 | WiFi.begin(ssid, password); 154 | while (WiFi.status() != WL_CONNECTED) { 155 | delay(500); 156 | Serial.print("."); 157 | } 158 | Serial.println(""); 159 | Serial.println("WiFi connected"); 160 | 161 | app_httpserver_init(); 162 | app_facenet_main(); 163 | socket_server.listen(82); 164 | 165 | Serial.print("Camera Ready! Use 'http://"); 166 | Serial.print(WiFi.localIP()); 167 | Serial.println("' to connect"); 168 | } 169 | 170 | static esp_err_t index_handler(httpd_req_t *req) { 171 | httpd_resp_set_type(req, "text/html"); 172 | httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); 173 | return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len); 174 | } 175 | 176 | httpd_uri_t index_uri = { 177 | .uri = "/", 178 | .method = HTTP_GET, 179 | .handler = index_handler, 180 | .user_ctx = NULL 181 | }; 182 | 183 | void app_httpserver_init () 184 | { 185 | httpd_config_t config = HTTPD_DEFAULT_CONFIG(); 186 | if (httpd_start(&camera_httpd, &config) == ESP_OK) 187 | Serial.println("httpd_start"); 188 | { 189 | httpd_register_uri_handler(camera_httpd, &index_uri); 190 | } 191 | } 192 | 193 | void app_facenet_main() 194 | { 195 | face_id_name_init(&st_face_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES); 196 | aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3); 197 | read_face_id_from_flash_with_name(&st_face_list); 198 | } 199 | 200 | static inline int do_enrollment(face_id_name_list *face_list, dl_matrix3d_t *new_id) 201 | { 202 | ESP_LOGD(TAG, "START ENROLLING"); 203 | int left_sample_face = enroll_face_id_to_flash_with_name(face_list, new_id, st_name.enroll_name); 204 | ESP_LOGD(TAG, "Face ID %s Enrollment: Sample %d", 205 | st_name.enroll_name, 206 | ENROLL_CONFIRM_TIMES - left_sample_face); 207 | return left_sample_face; 208 | } 209 | 210 | static esp_err_t send_face_list(WebsocketsClient &client) 211 | { 212 | client.send("delete_faces"); // tell browser to delete all faces 213 | face_id_node *head = st_face_list.head; 214 | char add_face[64]; 215 | for (int i = 0; i < st_face_list.count; i++) // loop current faces 216 | { 217 | sprintf(add_face, "listface:%s", head->id_name); 218 | client.send(add_face); //send face to browser 219 | head = head->next; 220 | } 221 | } 222 | 223 | static esp_err_t delete_all_faces(WebsocketsClient &client) 224 | { 225 | delete_face_all_in_flash_with_name(&st_face_list); 226 | client.send("delete_faces"); 227 | } 228 | 229 | void handle_message(WebsocketsClient &client, WebsocketsMessage msg) 230 | { 231 | if (msg.data() == "stream") { 232 | g_state = START_STREAM; 233 | client.send("STREAMING"); 234 | } 235 | if (msg.data() == "detect") { 236 | g_state = START_DETECT; 237 | client.send("DETECTING"); 238 | } 239 | if (msg.data().substring(0, 8) == "capture:") { 240 | g_state = START_ENROLL; 241 | char person[FACE_ID_SAVE_NUMBER * ENROLL_NAME_LEN] = {0,}; 242 | msg.data().substring(8).toCharArray(person, sizeof(person)); 243 | memcpy(st_name.enroll_name, person, strlen(person) + 1); 244 | client.send("CAPTURING"); 245 | } 246 | if (msg.data() == "recognise") { 247 | g_state = START_RECOGNITION; 248 | client.send("RECOGNISING"); 249 | } 250 | if (msg.data().substring(0, 7) == "remove:") { 251 | char person[ENROLL_NAME_LEN * FACE_ID_SAVE_NUMBER]; 252 | msg.data().substring(7).toCharArray(person, sizeof(person)); 253 | delete_face_id_in_flash_with_name(&st_face_list, person); 254 | send_face_list(client); // reset faces in the browser 255 | } 256 | if (msg.data() == "delete_all") { 257 | delete_all_faces(client); 258 | } 259 | } 260 | 261 | void open_door(WebsocketsClient &client) { 262 | if (digitalRead(relay_pin) == LOW) { 263 | digitalWrite(relay_pin, HIGH); //close (energise) relay so door unlocks 264 | Serial.println("Door Unlocked"); 265 | client.send("door_open"); 266 | door_opened_millis = millis(); // time relay closed and door opened 267 | } 268 | } 269 | 270 | void loop() { 271 | auto client = socket_server.accept(); 272 | client.onMessage(handle_message); 273 | dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, 320, 240, 3); 274 | http_img_process_result out_res = {0}; 275 | out_res.image = image_matrix->item; 276 | 277 | send_face_list(client); 278 | client.send("STREAMING"); 279 | 280 | while (client.available()) { 281 | client.poll(); 282 | 283 | if (millis() - interval > door_opened_millis) { // current time - face recognised time > 5 secs 284 | digitalWrite(relay_pin, LOW); //open relay 285 | } 286 | 287 | fb = esp_camera_fb_get(); 288 | 289 | if (g_state == START_DETECT || g_state == START_ENROLL || g_state == START_RECOGNITION) 290 | { 291 | out_res.net_boxes = NULL; 292 | out_res.face_id = NULL; 293 | 294 | fmt2rgb888(fb->buf, fb->len, fb->format, out_res.image); 295 | 296 | out_res.net_boxes = face_detect(image_matrix, &mtmn_config); 297 | 298 | if (out_res.net_boxes) 299 | { 300 | if (align_face(out_res.net_boxes, image_matrix, aligned_face) == ESP_OK) 301 | { 302 | 303 | out_res.face_id = get_face_id(aligned_face); 304 | last_detected_millis = millis(); 305 | if (g_state == START_DETECT) { 306 | client.send("FACE DETECTED"); 307 | } 308 | 309 | if (g_state == START_ENROLL) 310 | { 311 | int left_sample_face = do_enrollment(&st_face_list, out_res.face_id); 312 | char enrolling_message[64]; 313 | sprintf(enrolling_message, "SAMPLE NUMBER %d FOR %s", ENROLL_CONFIRM_TIMES - left_sample_face, st_name.enroll_name); 314 | client.send(enrolling_message); 315 | if (left_sample_face == 0) 316 | { 317 | ESP_LOGI(TAG, "Enrolled Face ID: %s", st_face_list.tail->id_name); 318 | g_state = START_STREAM; 319 | char captured_message[64]; 320 | sprintf(captured_message, "FACE CAPTURED FOR %s", st_face_list.tail->id_name); 321 | client.send(captured_message); 322 | send_face_list(client); 323 | 324 | } 325 | } 326 | 327 | if (g_state == START_RECOGNITION && (st_face_list.count > 0)) 328 | { 329 | face_id_node *f = recognize_face_with_name(&st_face_list, out_res.face_id); 330 | if (f) 331 | { 332 | char recognised_message[64]; 333 | sprintf(recognised_message, "DOOR OPEN FOR %s", f->id_name); 334 | open_door(client); 335 | client.send(recognised_message); 336 | } 337 | else 338 | { 339 | client.send("FACE NOT RECOGNISED"); 340 | } 341 | } 342 | dl_matrix3d_free(out_res.face_id); 343 | } 344 | 345 | } 346 | else 347 | { 348 | if (g_state != START_DETECT) { 349 | client.send("NO FACE DETECTED"); 350 | } 351 | } 352 | 353 | if (g_state == START_DETECT && millis() - last_detected_millis > 500) { // Detecting but no face detected 354 | client.send("DETECTING"); 355 | } 356 | 357 | } 358 | 359 | client.sendBinary((const char *)fb->buf, fb->len); 360 | 361 | esp_camera_fb_return(fb); 362 | fb = NULL; 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /HTML_interface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Face Recognition Access Control 8 | 114 | 115 | 116 |
117 |
118 |
119 |
120 |
121 |
122 | 123 |
124 |
125 | 126 | 127 |
128 |
129 | 130 | 131 |
132 |
133 |

Captured Faces

134 |
    135 |
136 |
137 |
138 | 139 |
140 |
141 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32-CAM Access Control System 2 | Using an ESP32-CAM to unlock a door when a face is recognised. A simple access control system based on face recognition with the ESP32-CAM and the Arduino IDE. 3 | 4 | ![Interface](https://robotzero.one/wp-content/uploads/bfi_thumb/featured-master-1-6qb32y1978bm9yf6ne9nypfey83yf3pvisk7rozvfi8.jpg) 5 | 6 | Note: If you are using release 1.0.5 of the ESP32 Arduino Hardware Libraries you can now run the entire project with just these files 7 | 8 | FaceDoorEntryESP32Cam.ino 9 | camera_index.h 10 | camera_pins.h 11 | partitions.csv 12 | 13 | There is no need to create new partitions in the Arduino IDE 14 | 15 | Note: Releases 2.x.x of the ESP32 Hardware Libraries don't support face recognition on the ESP32 modules. The algorithm has been 'improved' and now runs too slowly on these processors. 16 | 17 | Full details on the blog: https://robotzero.one/access-control-with-face-recognition/ 18 | -------------------------------------------------------------------------------- /camera_index.h: -------------------------------------------------------------------------------- 1 | 2 | //File: index_ov2640.html.gz, Size: 4316 3 | #define index_ov2640_html_gz_len 4316 4 | const uint8_t index_ov2640_html_gz[] = { 5 | 0x1f,0x8b,0x08,0x08,0x76,0x8e,0x5e,0x5d,0x00,0xff,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x2e,0x67,0x7a,0x00,0xb5,0x58,0x6d,0x6f,0x22,0x39,0x12,0xfe,0x3c,0xfc,0x0a,0x5f,0xef,0x9d,0x8e,0xdc,0x42,0x43,0x42,0x76,0x95,0x61,0x42,0x74,0x4c,0x86,0xdc,0xac,0x94,0xb9,0x48,0x49,0x46,0x7b,0xdf,0x66,0x4d,0xb7,0x01,0xdf,0xb8,0xdb,0xbd,0xb6,0x1b,0xc2,0xad,0xf2,0xdf,0xb7,0xca,0x2f,0x8d,0x9b,0x90,0x49,0x76,0xa5,0x03,0x89,0x06,0xbb,0xea,0x71,0xd5,0xe3,0xaa,0x72,0x99,0xf3,0xbf,0xe4,0x32,0x33,0xdb,0x8a,0x91,0x95,0x29,0xc4,0x45,0xe7,0x3c,0x3c,0x18,0xcd,0xe1,0x51,0x30,0x43,0x49,0xb6,0xa2,0x4a,0x33,0x33,0x49,0x6a,0xb3,0xe8,0x9f,0x25,0x61,0xb8,0xa4,0x05,0x9b,0x24,0x6b,0xce,0x36,0x95,0x54,0x26,0x21,0x99,0x2c,0x0d,0x2b,0x41,0x6c,0xc3,0x73,0xb3,0x9a,0xe4,0x6c,0xcd,0x33,0xd6,0xb7,0x3f,0x7a,0xbc,0xe4,0x86,0x53,0xd1,0xd7,0x19,0x15,0x6c,0x72,0x8c,0x18,0x86,0x1b,0xc1,0x2e,0xae,0x68,0xc6,0xc8,0x2d,0xcb,0xe4,0x12,0x25,0x64,0x49,0xa6,0x59,0xc6,0xb4,0x26,0x97,0x00,0xa6,0xa4,0x38,0x1f,0x38,0xb1,0xce,0xb9,0x36,0x5b,0x7c,0xfe,0xb3,0x60,0x39,0xa7,0x44,0x96,0x62,0x4b,0x74,0xa6,0x18,0x2b,0x09,0x2d,0x73,0xd2,0x2d,0x78,0xe9,0x96,0x1a,0x93,0xb3,0x1f,0x86,0xd5,0xc3,0x11,0xf9,0xad,0xf3,0x66,0x2e,0xf3,0x2d,0x3e,0xdf,0x90,0x9c,0xeb,0x4a,0xd0,0xed,0x98,0x2c,0x04,0x7b,0x78,0xd7,0x79,0xf3,0xd8,0x79,0x43,0xbe,0xf3,0x06,0xf7,0x15,0x5f,0xae,0x8c,0x93,0x2b,0xa8,0x5a,0x02,0x92,0x60,0x0b,0x33,0x26,0xc7,0x80,0x83,0xb2,0x84,0x74,0x1e,0x3b,0x1e,0x8b,0xe0,0x6b,0x01,0x8a,0xfd,0x05,0x2d,0xb8,0x00,0xc4,0xa9,0x02,0xc7,0x7a,0xe4,0x23,0x13,0x6b,0x66,0x78,0x46,0x7b,0x44,0xd3,0x52,0xf7,0x35,0x53,0x7c,0xf1,0xce,0xc9,0xcf,0x69,0xf6,0x75,0xa9,0x64,0x5d,0xe6,0x63,0xf2,0xdd,0xf1,0x19,0xbe,0xfd,0x4c,0x26,0x85,0x54,0x30,0x38,0xbb,0xc2,0xb7,0x1f,0xb4,0xf0,0x9a,0xff,0x8f,0x81,0x09,0x3f,0xa2,0x09,0x8f,0x9d,0x9d,0xb1,0x68,0x5a,0xb0,0xa3,0xa0,0x0f,0xc1,0xe9,0xd3,0xa1,0x33,0xd6,0x3a,0x08,0x7a,0x6d,0xa5,0xe0,0xe1,0xeb,0xb4,0xb4,0x51,0x8c,0x16,0x41,0xdc,0x8b,0x1e,0x0f,0x87,0x7f,0x0b,0xd3,0xd4,0xd4,0xba,0xef,0x29,0x0d,0x62,0x2b,0x86,0x6b,0x8c,0xc9,0xc9,0x0f,0x88,0xe8,0xdc,0x96,0x2a,0x67,0xe0,0x5d,0x29,0x4b,0xe6,0x87,0x2a,0x9a,0xe7,0xbc,0x5c,0x06,0x6e,0x1b,0x77,0x61,0xe0,0xac,0x7a,0x18,0x9c,0x9c,0x54,0x0f,0x4f,0xe9,0xf3,0x9b,0x32,0x97,0xc6,0xc8,0xa2,0xa5,0xea,0x56,0xe8,0x2b,0x9a,0xf3,0x5a,0x8f,0x49,0xb4,0x74,0xc4,0xf8,0x12,0xa3,0xc4,0x8f,0x1b,0xf6,0x60,0xfa,0x54,0xf0,0x65,0x39,0x26,0x19,0x30,0xc3,0x94,0xf3,0xa9,0x62,0x4a,0x43,0xf0,0xb5,0x5c,0x76,0x1e,0xff,0x19,0xe7,0x4e,0xc0,0xc2,0xff,0xb7,0x87,0x8a,0xb9,0x08,0x89,0xd6,0x9f,0xcb,0x07,0x0c,0x1b,0x6b,0x82,0xd7,0x83,0x21,0xeb,0xe0,0xbc,0x06,0xe4,0xc6,0xbf,0x26,0x1b,0xe6,0x42,0x66,0x5f,0x5b,0x36,0xd8,0x25,0xc8,0x70,0xdf,0xa3,0x21,0x39,0x06,0xc3,0xf7,0x5c,0x0f,0x52,0x21,0x98,0xce,0x02,0x5d,0x82,0x97,0xac,0xdf,0x70,0x06,0x6e,0x87,0x68,0xaf,0x81,0x65,0x50,0xac,0x24,0x77,0xd4,0xb7,0x72,0x60,0xb1,0x38,0x98,0x2f,0x8b,0xc5,0x68,0x38,0x3a,0x7d,0x89,0x8e,0x27,0x39,0x63,0x47,0x65,0x6d,0xd0,0x16,0x6b,0x2a,0xb0,0x90,0x3a,0x1a,0xf4,0x5e,0xcc,0x9e,0x5a,0xba,0x1b,0x96,0xc6,0x2b,0xb9,0x66,0x2a,0xc8,0xec,0xd9,0x72,0xfa,0xf6,0x34,0x8f,0x65,0x69,0x66,0xf8,0x9a,0x1d,0x16,0x3e,0x39,0xce,0x4e,0x5c,0x4a,0x79,0x61,0xe0,0x9d,0xce,0x05,0xcb,0x83,0x78,0xe0,0x23,0x67,0x0b,0x5a,0x0b,0x73,0xc8,0x7b,0x3a,0xc4,0xb7,0xb3,0x3e,0x4e,0xfd,0x85,0x90,0x14,0xc8,0xc5,0x21,0x37,0xd9,0x4a,0x71,0x3f,0x6b,0xc7,0xdc,0x34,0x2f,0xe8,0x92,0xf5,0xb1,0x1e,0x50,0x20,0xa4,0xf1,0xae,0x92,0xda,0x96,0x5d,0x90,0x65,0x82,0xa2,0x2b,0x4e,0xbc,0x5d,0x02,0x9e,0x56,0x0c,0x90,0xa9,0x45,0x98,0x16,0x5c,0x03,0xf7,0x58,0x9f,0x0f,0xa7,0xc3,0x6e,0x97,0x7c,0x8c,0x39,0x7f,0x04,0x6f,0xac,0x88,0x24,0xc3,0x56,0xe5,0x4c,0x30,0xf3,0x0c,0xb1,0xdf,0x88,0x08,0x48,0xda,0x5d,0xb8,0x3d,0x09,0xac,0x43,0xe9,0xff,0x34,0x62,0x31,0x51,0x9f,0x8b,0x58,0x30,0x6d,0x35,0xda,0xf1,0xd2,0x4a,0xdb,0x91,0x63,0xe6,0x7c,0xe0,0xcf,0xaa,0xf3,0x81,0x3f,0x45,0xf1,0xec,0x80,0x47,0xce,0xd7,0x84,0xe7,0x93,0x24,0x2e,0xe5,0x70,0x12,0x12,0xd2,0xcc,0x38,0xda,0x77,0xdb,0x04,0x87,0xaa,0xa0,0x5a,0x4f,0x92,0xbd,0xed,0x4b,0x2e,0xc8,0x39,0x2f,0x96,0x91,0x4e,0x42,0xb4,0xca,0x26,0x09,0x4e,0x0c,0x00,0x0d,0x17,0x77,0x8f,0xfd,0x45,0x6d,0x4c,0xec,0xaf,0x1a,0x17,0x74,0x84,0xd0,0x15,0x2d,0x9d,0x56,0xad,0x14,0x6a,0x39,0x91,0xe4,0x02,0x7c,0x83,0xa9,0x66,0x91,0x08,0xc4,0x55,0xd0,0x3e,0x36,0x05,0x16,0x1d,0xa6,0x78,0x59,0xd5,0x26,0x9a,0x4c,0x08,0x36,0x1a,0x93,0x04,0x77,0x21,0x21,0x6b,0x2a,0x6a,0xf8,0x91,0x10,0x58,0x34,0x63,0x2b,0x29,0x60,0x1b,0x27,0xc9,0x3d,0xb6,0x22,0x66,0xc5,0x88,0x53,0xf9,0xbb,0xb6,0x6d,0x06,0x64,0xaa,0x72,0xb0,0xed,0x85,0x3d,0x3b,0x3e,0xad,0xc3,0xba,0xbe,0xd8,0xe1,0xc2,0xee,0x2b,0x98,0xef,0x38,0xf2,0xf2,0x8e,0xf8,0xbb,0xfb,0xdb,0xd9,0xf4,0x13,0xb9,0x9c,0x7e,0x9a,0xdd,0x4e,0xcf,0x07,0x4e,0xf4,0x59,0x88,0x1c,0xa2,0x31,0xc3,0x2e,0xc7,0x41,0x78,0x1a,0x3f,0xcc,0xee,0x67,0x97,0xf7,0xe4,0x6a,0x7a,0x39,0xbb,0x8b,0x21,0xfe,0x9c,0x99,0x19,0xad,0x4c,0x0d,0x8e,0xb6,0xec,0x24,0xb6,0x03,0x9a,0x24,0x33,0x0c,0x40,0xe2,0xda,0x2e,0x42,0xe7,0x50,0xa3,0xc8,0x9c,0x2d,0xa4,0x62,0xc4,0xa9,0x41,0x02,0xc1,0xec,0x02,0xb8,0x4c,0x2e,0xa6,0x1f,0x3e,0x90,0xcf,0x77,0xb3,0xdb,0x17,0xbd,0x52,0xae,0xf3,0xd2,0xbb,0x35,0xbd,0x63,0xd3,0x4b,0xf0,0xe8,0x8e,0x5c,0xde,0xfc,0xfb,0xfe,0xf6,0xe6,0xfa,0x45,0xd7,0x2a,0x26,0x2b,0xd1,0x6c,0xfc,0x6a,0x74,0x71,0xe9,0x5c,0xc9,0x09,0x36,0x78,0x1a,0x32,0x61,0xe4,0xe7,0x6a,0xe8,0x2e,0xed,0x97,0x81,0xfb,0xf6,0x07,0x99,0x72,0x65,0xe1,0x0b,0x15,0x02,0xc9,0xbf,0x06,0xfa,0xc9,0xf4,0xfa,0x90,0x7d,0xe1,0x01,0x4d,0x22,0xaf,0xcc,0x45,0x07,0xda,0xdc,0xba,0x80,0x50,0x4e,0xa1,0xd6,0xcc,0xd6,0xf0,0xe5,0x1a,0xaa,0x16,0x83,0x5c,0xea,0x26,0x1f,0x6e,0x3e,0x61,0xbb,0x89,0x63,0x92,0xe6,0x2c,0x4f,0x7a,0x64,0x51,0x97,0x50,0xd8,0x65,0xd9,0x65,0x28,0x8a,0xcd,0x24,0x81,0x80,0x55,0x50,0x87,0x34,0xfb,0x28,0xb5,0x21,0x13,0xd2,0x00,0xc2,0x19,0x0a,0x95,0x53,0x96,0xa9,0x04,0xee,0xb8,0xed,0x34,0x50,0xd4,0xc5,0xdc,0x67,0x25,0x40,0xb6,0x51,0xfb,0x9e,0x24,0xe3,0xb3,0xe3,0x04,0x65,0x20,0x21,0x61,0xe0,0xe7,0xbb,0x2f,0x9f,0x6f,0xaf,0x41,0x24,0xd9,0xe8,0xf1,0x60,0x90,0x80,0xc4,0x86,0x97,0xb9,0xdc,0xec,0x60,0x57,0x8d,0xe2,0x49,0xa4,0xb8,0xd1,0xa0,0x54,0xb2,0x0d,0xf9,0x99,0xcd,0xef,0xe0,0x14,0x67,0xa6,0xeb,0xb0,0x8e,0xde,0x75,0x1a,0x21,0x6c,0xce,0x63,0x53,0x97,0xcc,0xcc,0x04,0xc3,0xaf,0xef,0xb7,0x3f,0xe5,0xdd,0x50,0x3b,0x40,0x25,0x68,0xb8,0xb4,0xbb,0x92,0xaa,0xb8,0xe2,0x4c,0xe4,0xdf,0x52,0xf6,0x49,0x1d,0x29,0x3b,0xb8,0xf7,0x6e,0xb7,0xbe,0xa1,0xd9,0xce,0xca,0x08,0xc0,0x25,0xd9,0xab,0x01,0x7c,0x4e,0x46,0x00,0x3e,0x83,0x5e,0x8d,0x10,0x32,0x2e,0x82,0x68,0x52,0xe2,0xd5,0x20,0xbb,0x24,0x6a,0xb9,0x82,0x81,0x3a,0x15,0xe2,0x65,0x98,0x28,0xa6,0xdd,0xe6,0x0d,0x06,0x64,0x09,0x75,0x1e,0xc2,0x50,0xb1,0x5f,0x6b,0x56,0x66,0xdb,0x1e,0xc9,0x6b,0x65,0xc3,0x01,0xa6,0xe9,0x04,0xf7,0x7d,0x5a,0xe7,0x5c,0xda,0xb8,0x7d,0x30,0x5d,0xbb,0x70,0x08,0x5a,0x02,0x77,0x2c,0x65,0xee,0xf0,0xb4,0xec,0x6e,0x7a,0x0f,0xbd,0xed,0x91,0x3b,0xaf,0xd6,0x13,0x9a,0xc2,0x95,0x89,0x1a,0x76,0xa3,0x33,0x2e,0xe0,0xbc,0x97,0xca,0x69,0x12,0x52,0x37,0x73,0xff,0x82,0x95,0xc3,0xe8,0x3a,0x05,0x67,0x4a,0xe0,0xb8,0x5b,0x37,0x23,0x8d,0x4d,0xa9,0xab,0xe0,0xfe,0xa8,0x5c,0xa7,0xae,0xb8,0xeb,0x5f,0x6b,0x0a,0x84,0x7a,0xd4,0x46,0x9f,0xc2,0x81,0xae,0x0d,0x2f,0xad,0x0f,0x61,0xcd,0x14,0xbd,0xf4,0x30,0x9b,0x7f,0x0c,0xd3,0x21,0x74,0x4b,0x0e,0x0b,0xce,0x1b,0x85,0x4a,0xfe,0xfc,0xb9,0xe7,0x05,0x6b,0x0c,0xd0,0x46,0x56,0xed,0xa9,0xef,0xb7,0xa8,0x3c,0x3c,0xb6,0x22,0x8f,0xc8,0xe0,0x46,0xa7,0xb2,0x94,0x15,0xdc,0x0e,0x27,0xa4,0x7b,0x44,0x26,0x17,0xfe,0xc8,0xc6,0xbd,0x91,0x82,0x41,0x72,0x2d,0xbb,0xbf,0x00,0x79,0x68,0x1b,0x14,0x29,0x23,0xc9,0x5f,0x7f,0x73,0xe9,0xf3,0xf8,0x8b,0x43,0xc1,0x0f,0x8b,0x52,0xc0,0x75,0x14,0x0e,0x5f,0x00,0x6a,0xbe,0x05,0x34,0xbe,0x20,0x5d,0xf4,0x5a,0x2e,0xc2,0x5c,0x9a,0x53,0xb8,0x19,0x4f,0x26,0x90,0xcf,0x10,0xdd,0x50,0x92,0x13,0x57,0x3b,0x82,0x74,0x2c,0x96,0xea,0x7a,0x0e,0x42,0xdd,0x61,0x8f,0x9c,0x81,0x89,0xa0,0x82,0x8d,0x94,0x2d,0xe0,0x3b,0x25,0xd8,0xed,0x3c,0xc7,0x1a,0x7a,0x2f,0xef,0xec,0x75,0xf7,0x20,0xc4,0xdb,0x23,0xcf,0x0e,0x18,0x4e,0x98,0xd0,0xec,0xc9,0x62,0x16,0xdf,0x07,0x1a,0x2e,0xa1,0x5b,0x6b,0x34,0xc1,0x6a,0xab,0xf5,0x95,0x92,0x85,0x5f,0xec,0x75,0xb0,0x52,0xaa,0x2f,0x48,0x76,0x0b,0x13,0x2c,0xdf,0x85,0xe1,0xf1,0xb0,0x77,0x32,0x1a,0xf5,0xa0,0x3b,0x3b,0x7a,0x17,0x8f,0x8f,0x7a,0x3f,0x0e,0x47,0xbd,0x13,0x1c,0x6e,0x2f,0x14,0xe3,0x3c,0x9b,0x38,0x7b,0xdd,0xc9,0x51,0xca,0x61,0x43,0xd5,0xc7,0xfb,0x4f,0x58,0x50,0x63,0x33,0x03,0xf8,0x37,0xd1,0xf6,0xda,0xa0,0x23,0x08,0x34,0x68,0xe3,0xd2,0x5d,0xeb,0x89,0x55,0xda,0x5e,0x26,0x7d,0x74,0x63,0xac,0xed,0x3e,0x9f,0x50,0xc3,0xa1,0x0c,0xd0,0x32,0xc3,0xe8,0x78,0x2f,0xe4,0x7c,0xc7,0x0d,0x9e,0x0e,0xb5,0x12,0x37,0xf3,0xff,0x42,0xf4,0x01,0x28,0x44,0x5d,0xc8,0x4b,0x3b,0x04,0xbf,0x5b,0x48,0x0d,0x37,0x58,0xce,0x53,0xe8,0xf3,0x40,0xa7,0xd1,0x77,0x73,0x68,0x82,0x0d,0xfc,0xb8,0x04,0x43,0xf0,0x66,0x82,0x67,0x5f,0xf7,0x72,0x00,0xa2,0x5a,0x33,0xe0,0xbe,0x55,0xfd,0x6d,0xbc,0xc7,0xe5,0xf7,0x25,0xe5,0xb8,0xf6,0x5a,0xe5,0x56,0xe9,0x7d,0x46,0xdb,0x1d,0x19,0x5f,0x6c,0x0b,0xf3,0x8a,0x93,0xc5,0x95,0x06,0xe7,0x61,0xb3,0xb0,0x5f,0x67,0x8c,0x47,0x65,0x84,0xb7,0x33,0x64,0xaf,0x80,0xbf,0xe4,0xc8,0x5e,0xf5,0xf6,0x44,0xb4,0x8a,0xf7,0xcb,0x5c,0xc4,0x05,0xdc,0x63,0xec,0x9d,0xa4,0x80,0xf1,0x95,0x6d,0xeb,0x6a,0xbf,0x20,0xb5,0x58,0x6b,0x2e,0x88,0x13,0x68,0xe4,0x20,0x0d,0x3c,0x58,0x5c,0xdb,0x9f,0x4f,0x55,0x8f,0x08,0x87,0x87,0x93,0xd1,0xb6,0x19,0xb4,0xb7,0x33,0x88,0x45,0x32,0x57,0x72,0x03,0xff,0x39,0xd8,0xbf,0xce,0x9a,0x5a,0x68,0xac,0x0c,0xb6,0x42,0xf1,0x7e,0x40,0x7d,0x57,0xdb,0x3b,0x00,0xc9,0xf0,0x84,0x48,0x6a,0xef,0x16,0x78,0xbc,0xe2,0x82,0x91,0x6e,0xd0,0x49,0x17,0x5c,0x69,0x73,0x09,0x83,0xf9,0x2e,0xba,0x0f,0x4c,0xa6,0x8a,0x15,0xd0,0xaf,0x86,0x6a,0xe2,0xf2,0x65,0x9f,0x1f,0xbb,0xd7,0x98,0x62,0x3e,0xbb,0x9e,0x65,0xc6,0x28,0x17,0x13,0x36,0xde,0x77,0x67,0xde,0x5e,0x99,0x8c,0x43,0x23,0x2a,0xfe,0x7f,0xd0,0x61,0xe0,0xd1,0x12,0xf8,0x93,0x61,0x45,0xac,0xe0,0xd2,0xd5,0x07,0x6d,0x17,0x0a,0x77,0xac,0x90,0x09,0xa9,0xd9,0x0b,0x1a,0x78,0x8d,0x0a,0x3a,0x8d,0x7c,0x6a,0xdb,0x5f,0x4b,0x1e,0xb8,0x13,0xe2,0xea,0xa9,0x18,0x47,0x1a,0x22,0x07,0xf7,0xe7,0x9f,0xb6,0xb8,0x36,0x7c,0xe3,0xbe,0x76,0xb7,0x5f,0x51,0x22,0xe0,0x26,0x1d,0xcc,0x2b,0x20,0x3b,0xf8,0xe7,0xc9,0x48,0x69,0x05,0x05,0x3f,0xb7,0xdb,0xdb,0xf5,0x48,0xcf,0xfa,0x0a,0xff,0xe4,0xe2,0x49,0x68,0xc5,0x8e,0x52,0x6c,0x58,0x7c,0xbf,0x7d,0xc8,0x8d,0x83,0x2b,0x34,0xbe,0xed,0xab,0x27,0xff,0xf1,0xe1,0xd2,0x84,0x5d,0xac,0x16,0xb0,0x76,0x8d,0xc1,0x0b,0x51,0x85,0x6e,0xc2,0x1d,0xd7,0xdf,0x19,0xe0,0x5a,0xe1,0x6e,0xee,0x03,0xfb,0xaf,0xf8,0xef,0x5f,0x9e,0x6a,0x05,0x2c,0x17,0x00,0x00 6 | }; 7 | -------------------------------------------------------------------------------- /camera_pins.h: -------------------------------------------------------------------------------- 1 | 2 | #if defined(CAMERA_MODEL_WROVER_KIT) 3 | #define PWDN_GPIO_NUM -1 4 | #define RESET_GPIO_NUM -1 5 | #define XCLK_GPIO_NUM 21 6 | #define SIOD_GPIO_NUM 26 7 | #define SIOC_GPIO_NUM 27 8 | 9 | #define Y9_GPIO_NUM 35 10 | #define Y8_GPIO_NUM 34 11 | #define Y7_GPIO_NUM 39 12 | #define Y6_GPIO_NUM 36 13 | #define Y5_GPIO_NUM 19 14 | #define Y4_GPIO_NUM 18 15 | #define Y3_GPIO_NUM 5 16 | #define Y2_GPIO_NUM 4 17 | #define VSYNC_GPIO_NUM 25 18 | #define HREF_GPIO_NUM 23 19 | #define PCLK_GPIO_NUM 22 20 | 21 | #elif defined(CAMERA_MODEL_ESP_EYE) 22 | #define PWDN_GPIO_NUM -1 23 | #define RESET_GPIO_NUM -1 24 | #define XCLK_GPIO_NUM 4 25 | #define SIOD_GPIO_NUM 18 26 | #define SIOC_GPIO_NUM 23 27 | 28 | #define Y9_GPIO_NUM 36 29 | #define Y8_GPIO_NUM 37 30 | #define Y7_GPIO_NUM 38 31 | #define Y6_GPIO_NUM 39 32 | #define Y5_GPIO_NUM 35 33 | #define Y4_GPIO_NUM 14 34 | #define Y3_GPIO_NUM 13 35 | #define Y2_GPIO_NUM 34 36 | #define VSYNC_GPIO_NUM 5 37 | #define HREF_GPIO_NUM 27 38 | #define PCLK_GPIO_NUM 25 39 | 40 | #elif defined(CAMERA_MODEL_M5STACK_PSRAM) 41 | #define PWDN_GPIO_NUM -1 42 | #define RESET_GPIO_NUM 15 43 | #define XCLK_GPIO_NUM 27 44 | #define SIOD_GPIO_NUM 25 45 | #define SIOC_GPIO_NUM 23 46 | 47 | #define Y9_GPIO_NUM 19 48 | #define Y8_GPIO_NUM 36 49 | #define Y7_GPIO_NUM 18 50 | #define Y6_GPIO_NUM 39 51 | #define Y5_GPIO_NUM 5 52 | #define Y4_GPIO_NUM 34 53 | #define Y3_GPIO_NUM 35 54 | #define Y2_GPIO_NUM 32 55 | #define VSYNC_GPIO_NUM 22 56 | #define HREF_GPIO_NUM 26 57 | #define PCLK_GPIO_NUM 21 58 | 59 | #elif defined(CAMERA_MODEL_M5STACK_WIDE) 60 | #define PWDN_GPIO_NUM -1 61 | #define RESET_GPIO_NUM 15 62 | #define XCLK_GPIO_NUM 27 63 | #define SIOD_GPIO_NUM 22 64 | #define SIOC_GPIO_NUM 23 65 | 66 | #define Y9_GPIO_NUM 19 67 | #define Y8_GPIO_NUM 36 68 | #define Y7_GPIO_NUM 18 69 | #define Y6_GPIO_NUM 39 70 | #define Y5_GPIO_NUM 5 71 | #define Y4_GPIO_NUM 34 72 | #define Y3_GPIO_NUM 35 73 | #define Y2_GPIO_NUM 32 74 | #define VSYNC_GPIO_NUM 25 75 | #define HREF_GPIO_NUM 26 76 | #define PCLK_GPIO_NUM 21 77 | 78 | #elif defined(CAMERA_MODEL_AI_THINKER) 79 | #define PWDN_GPIO_NUM 32 80 | #define RESET_GPIO_NUM -1 81 | #define XCLK_GPIO_NUM 0 82 | #define SIOD_GPIO_NUM 26 83 | #define SIOC_GPIO_NUM 27 84 | 85 | #define Y9_GPIO_NUM 35 86 | #define Y8_GPIO_NUM 34 87 | #define Y7_GPIO_NUM 39 88 | #define Y6_GPIO_NUM 36 89 | #define Y5_GPIO_NUM 21 90 | #define Y4_GPIO_NUM 19 91 | #define Y3_GPIO_NUM 18 92 | #define Y2_GPIO_NUM 5 93 | #define VSYNC_GPIO_NUM 25 94 | #define HREF_GPIO_NUM 23 95 | #define PCLK_GPIO_NUM 22 96 | 97 | #else 98 | #error "Camera model not selected" 99 | #endif 100 | -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x300000, 5 | fr, 32, 32, 0x310000, 0xF0000, 6 | -------------------------------------------------------------------------------- /rzo_partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x280000, 5 | fr, 32, 32, 0x290000, 0xEF000, 6 | eeprom, data, 0x99, 0x37f000, 0x1000, 7 | spiffs, data, spiffs, 0x380000, 0x2F000, --------------------------------------------------------------------------------