comparison espNode/garage_hall_cam/src/camera.cpp @ 1678:7831b5de3572

espNode checkpoint
author drewp@bigasterisk.com
date Mon, 27 Sep 2021 22:59:39 -0700
parents
children
comparison
equal deleted inserted replaced
1677:aa35ae7a1acc 1678:7831b5de3572
1 // from https://raw.githubusercontent.com/RuiSantosdotme/ESP32-CAM-Arduino-IDE/master/ESP32-CAM-Video-Streaming/ESP32-CAM-Video-Streaming.ino
2
3
4
5 /*********
6 Rui Santos
7 Complete project details at https://RandomNerdTutorials.com/esp32-cam-video-streaming-web-server-camera-home-assistant/
8
9 IMPORTANT!!!
10 - Select Board "AI Thinker ESP32-CAM"
11 - GPIO 0 must be connected to GND to upload a sketch
12 - After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode
13
14 Permission is hereby granted, free of charge, to any person obtaining a copy
15 of this software and associated documentation files.
16
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 *********/
20
21 #include "esp_camera.h"
22 #include <WiFi.h>
23 #include "esp_timer.h"
24 #include "img_converters.h"
25 #include "Arduino.h"
26 #include "fb_gfx.h"
27 #include "soc/soc.h" //disable brownout problems
28 #include "soc/rtc_cntl_reg.h" //disable brownout problems
29 #include "esp_http_server.h"
30
31 //Replace with your network credentials
32 const char* ssid = "REPLACE_WITH_YOUR_SSID";
33 const char* password = "REPLACE_WITH_YOUR_PASSWORD";
34
35 #define PART_BOUNDARY "123456789000000000000987654321"
36
37 // This project was tested with the AI Thinker Model, M5STACK PSRAM Model and M5STACK WITHOUT PSRAM
38 #define CAMERA_MODEL_AI_THINKER
39 //#define CAMERA_MODEL_M5STACK_PSRAM
40 //#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM
41
42 // Not tested with this model
43 //#define CAMERA_MODEL_WROVER_KIT
44
45 #if defined(CAMERA_MODEL_WROVER_KIT)
46 #define PWDN_GPIO_NUM -1
47 #define RESET_GPIO_NUM -1
48 #define XCLK_GPIO_NUM 21
49 #define SIOD_GPIO_NUM 26
50 #define SIOC_GPIO_NUM 27
51
52 #define Y9_GPIO_NUM 35
53 #define Y8_GPIO_NUM 34
54 #define Y7_GPIO_NUM 39
55 #define Y6_GPIO_NUM 36
56 #define Y5_GPIO_NUM 19
57 #define Y4_GPIO_NUM 18
58 #define Y3_GPIO_NUM 5
59 #define Y2_GPIO_NUM 4
60 #define VSYNC_GPIO_NUM 25
61 #define HREF_GPIO_NUM 23
62 #define PCLK_GPIO_NUM 22
63
64 #elif defined(CAMERA_MODEL_M5STACK_PSRAM)
65 #define PWDN_GPIO_NUM -1
66 #define RESET_GPIO_NUM 15
67 #define XCLK_GPIO_NUM 27
68 #define SIOD_GPIO_NUM 25
69 #define SIOC_GPIO_NUM 23
70
71 #define Y9_GPIO_NUM 19
72 #define Y8_GPIO_NUM 36
73 #define Y7_GPIO_NUM 18
74 #define Y6_GPIO_NUM 39
75 #define Y5_GPIO_NUM 5
76 #define Y4_GPIO_NUM 34
77 #define Y3_GPIO_NUM 35
78 #define Y2_GPIO_NUM 32
79 #define VSYNC_GPIO_NUM 22
80 #define HREF_GPIO_NUM 26
81 #define PCLK_GPIO_NUM 21
82
83 #elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM)
84 #define PWDN_GPIO_NUM -1
85 #define RESET_GPIO_NUM 15
86 #define XCLK_GPIO_NUM 27
87 #define SIOD_GPIO_NUM 25
88 #define SIOC_GPIO_NUM 23
89
90 #define Y9_GPIO_NUM 19
91 #define Y8_GPIO_NUM 36
92 #define Y7_GPIO_NUM 18
93 #define Y6_GPIO_NUM 39
94 #define Y5_GPIO_NUM 5
95 #define Y4_GPIO_NUM 34
96 #define Y3_GPIO_NUM 35
97 #define Y2_GPIO_NUM 17
98 #define VSYNC_GPIO_NUM 22
99 #define HREF_GPIO_NUM 26
100 #define PCLK_GPIO_NUM 21
101
102 #elif defined(CAMERA_MODEL_AI_THINKER)
103 #define PWDN_GPIO_NUM 32
104 #define RESET_GPIO_NUM -1
105 #define XCLK_GPIO_NUM 0
106 #define SIOD_GPIO_NUM 26
107 #define SIOC_GPIO_NUM 27
108
109 #define Y9_GPIO_NUM 35
110 #define Y8_GPIO_NUM 34
111 #define Y7_GPIO_NUM 39
112 #define Y6_GPIO_NUM 36
113 #define Y5_GPIO_NUM 21
114 #define Y4_GPIO_NUM 19
115 #define Y3_GPIO_NUM 18
116 #define Y2_GPIO_NUM 5
117 #define VSYNC_GPIO_NUM 25
118 #define HREF_GPIO_NUM 23
119 #define PCLK_GPIO_NUM 22
120 #else
121 #error "Camera model not selected"
122 #endif
123
124 static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
125 static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
126 static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
127
128 httpd_handle_t stream_httpd = NULL;
129
130 static esp_err_t stream_handler(httpd_req_t *req){
131 camera_fb_t * fb = NULL;
132 esp_err_t res = ESP_OK;
133 size_t _jpg_buf_len = 0;
134 uint8_t * _jpg_buf = NULL;
135 char * part_buf[64];
136
137 res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
138 if(res != ESP_OK){
139 return res;
140 }
141
142 // https://github.com/RuiSantosdotme/ESP32-CAM-Arduino-IDE/pull/4
143 res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
144 if(res != ESP_OK){
145 return res;
146 }
147
148 while(true){
149 fb = esp_camera_fb_get();
150 if (!fb) {
151 Serial.println("Camera capture failed");
152 res = ESP_FAIL;
153 } else {
154 if(fb->width > 400){
155 if(fb->format != PIXFORMAT_JPEG){
156 bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
157 esp_camera_fb_return(fb);
158 fb = NULL;
159 if(!jpeg_converted){
160 Serial.println("JPEG compression failed");
161 res = ESP_FAIL;
162 }
163 } else {
164 _jpg_buf_len = fb->len;
165 _jpg_buf = fb->buf;
166 }
167 }
168 }
169 if(res == ESP_OK){
170 size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
171 res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
172 }
173 if(res == ESP_OK){
174 res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
175 }
176 if(res == ESP_OK){
177 res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
178 }
179 if(fb){
180 esp_camera_fb_return(fb);
181 fb = NULL;
182 _jpg_buf = NULL;
183 } else if(_jpg_buf){
184 free(_jpg_buf);
185 _jpg_buf = NULL;
186 }
187 if(res != ESP_OK){
188 break;
189 }
190 //Serial.printf("MJPG: %uB\n",(uint32_t)(_jpg_buf_len));
191 }
192 return res;
193 }
194
195 void startCameraServer(){
196 httpd_config_t config = HTTPD_DEFAULT_CONFIG();
197 config.server_port = 80;
198
199 httpd_uri_t index_uri = {
200 .uri = "/",
201 .method = HTTP_GET,
202 .handler = stream_handler,
203 .user_ctx = NULL
204 };
205
206 //Serial.printf("Starting web server on port: '%d'\n", config.server_port);
207 if (httpd_start(&stream_httpd, &config) == ESP_OK) {
208 httpd_register_uri_handler(stream_httpd, &index_uri);
209 }
210 }
211
212 void cam_setup() {
213 WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
214
215 Serial.begin(115200);
216 Serial.setDebugOutput(false);
217
218 camera_config_t config;
219 config.ledc_channel = LEDC_CHANNEL_0;
220 config.ledc_timer = LEDC_TIMER_0;
221 config.pin_d0 = Y2_GPIO_NUM;
222 config.pin_d1 = Y3_GPIO_NUM;
223 config.pin_d2 = Y4_GPIO_NUM;
224 config.pin_d3 = Y5_GPIO_NUM;
225 config.pin_d4 = Y6_GPIO_NUM;
226 config.pin_d5 = Y7_GPIO_NUM;
227 config.pin_d6 = Y8_GPIO_NUM;
228 config.pin_d7 = Y9_GPIO_NUM;
229 config.pin_xclk = XCLK_GPIO_NUM;
230 config.pin_pclk = PCLK_GPIO_NUM;
231 config.pin_vsync = VSYNC_GPIO_NUM;
232 config.pin_href = HREF_GPIO_NUM;
233 config.pin_sscb_sda = SIOD_GPIO_NUM;
234 config.pin_sscb_scl = SIOC_GPIO_NUM;
235 config.pin_pwdn = PWDN_GPIO_NUM;
236 config.pin_reset = RESET_GPIO_NUM;
237 config.xclk_freq_hz = 20000000;
238 config.pixel_format = PIXFORMAT_JPEG;
239
240 if(psramFound()){
241 config.frame_size = FRAMESIZE_UXGA;
242 config.jpeg_quality = 10;
243 config.fb_count = 2;
244 } else {
245 config.frame_size = FRAMESIZE_SVGA;
246 config.jpeg_quality = 12;
247 config.fb_count = 1;
248 }
249
250 // Camera init
251 esp_err_t err = esp_camera_init(&config);
252 if (err != ESP_OK) {
253 Serial.printf("Camera init failed with error 0x%x", err);
254 return;
255 }
256
257 // Start streaming web server
258 startCameraServer();
259 }