ESP_IOT v2.5
IOT ESP Coding
CameraModule.cpp
Go to the documentation of this file.
1#include "CameraModule.h"
2#ifdef USE_CAMERA_MODULE
3
4
5
6//! 1.20.24 try to merge the RTSP server (not Web yet)
7//!Stream Link: rtsp://192.168.0.221:8554/mjpeg/1
8//! 8.16.25 MQTT
9//! if not MQTT then try the RTSPServer
10#ifdef TRY_RTSP_SERVER //TODO..
11#define ENABLE_RTSPSERVER
12#endif
13
14#define ENABLE_RTSPSERVER
15
16#ifdef ENABLE_RTSPSERVER
17
18//#include "src/SimStreamer.h"
19#include "src/OV2640Streamer.h"
20#include "src/CRtspSession.h"
21
22OV2640 _camera;
23
24WiFiServer _rtspServer(8554);
25
26#endif //ENABLE_RTSPSERVER
27
28
29//! Users/scott/Library/Arduino15/packages/m5stack/hardware/esp32/2.0.3/tools/sdk
30#include "esp_camera.h"
31
32#include "FS.h" // SD Card ESP32
33#include "soc/soc.h" // Disable brownour problems
34#include "soc/rtc_cntl_reg.h" // Disable brownour problems
35
36// define the number of bytes you want to access
37#define EEPROM_SIZE 1
38
39// Pin definition for CAMERA_MODEL_AI_THINKER
40#define PWDN_GPIO_NUM -1
41#define RESET_GPIO_NUM 15
42#define XCLK_GPIO_NUM 27
43#define SIOD_GPIO_NUM 25
44#define SIOC_GPIO_NUM 23
45
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#define CAMERA_LED_GPIO 2
60
61#define BAT_OUTPUT_HOLD_PIN 33
62#define BAT_ADC_PIN 38
63
64#define Ext_PIN_1 4
65#define Ext_PIN_2 13
66
67int _pictureNumber = 0;
68
69
70/**
71 * @brief Data structure of camera frame buffer
72 */
73#ifdef JUST_COMMENT
74typedef struct {
75 uint8_t * buf; /*!< Pointer to the pixel data */
76 size_t len; /*!< Length of the buffer in bytes */
77 size_t width; /*!< Width of the buffer in pixels */
78 size_t height; /*!< Height of the buffer in pixels */
79 pixformat_t format; /*!< Format of the pixel data */
80 struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */
81} camera_fb_t;
82#endif
83
84
85//!! split this up.. Sure seems like the picture is taken right now!!
86void initCameraSensor();
87
88//! config of camera
89camera_config_t _cameraConfig;
90
91//! setup
92void setup_CameraModule()
93{
94 SerialDebug.println("setup_CameraModule");
95
96 //! config of camera
97 // camera_config_t cameraConfig;
98
99 //disable brownout detector
100 WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
101
102 _cameraConfig.ledc_channel = LEDC_CHANNEL_0;
103 _cameraConfig.ledc_timer = LEDC_TIMER_0;
104 _cameraConfig.pin_d0 = Y2_GPIO_NUM;
105 _cameraConfig.pin_d1 = Y3_GPIO_NUM;
106 _cameraConfig.pin_d2 = Y4_GPIO_NUM;
107 _cameraConfig.pin_d3 = Y5_GPIO_NUM;
108 _cameraConfig.pin_d4 = Y6_GPIO_NUM;
109 _cameraConfig.pin_d5 = Y7_GPIO_NUM;
110 _cameraConfig.pin_d6 = Y8_GPIO_NUM;
111 _cameraConfig.pin_d7 = Y9_GPIO_NUM;
112 _cameraConfig.pin_xclk = XCLK_GPIO_NUM;
113 _cameraConfig.pin_pclk = PCLK_GPIO_NUM;
114 _cameraConfig.pin_vsync = VSYNC_GPIO_NUM;
115 _cameraConfig.pin_href = HREF_GPIO_NUM;
116 _cameraConfig.pin_sscb_sda = SIOD_GPIO_NUM;
117 _cameraConfig.pin_sscb_scl = SIOC_GPIO_NUM;
118 _cameraConfig.pin_pwdn = PWDN_GPIO_NUM;
119 _cameraConfig.pin_reset = RESET_GPIO_NUM;
120 _cameraConfig.xclk_freq_hz = 20000000;
121 _cameraConfig.pixel_format = PIXFORMAT_JPEG; //YUV422,GRAYSCALE,RGB565,JPEG
122
123 if(psramFound())
124 {
125 //SerialTemp.println("psramFound");
126
127 _cameraConfig.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
128 //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
129
130 _cameraConfig.jpeg_quality = 12; //0-63 lower number means higher quality
131 _cameraConfig.fb_count = 2; //if more than one, i2s runs in continuous mode. Use only with JPEG
132 }
133 else
134 {
135 //SerialTemp.println("psram NOT Found");
136
137 _cameraConfig.frame_size = FRAMESIZE_SVGA;
138 _cameraConfig.jpeg_quality = 12;
139 _cameraConfig.fb_count = 1;
140 }
141
142 // Init Camera
143 esp_err_t err = esp_camera_init(&_cameraConfig);
144 if (err != ESP_OK)
145 {
146 SerialError.printf("Camera init failed with error 0x%x", err);
147 return;
148 }
149 SerialTemp.println("*** Camera Initialized ****");
150
151 //!try initializing each time..
152 initCameraSensor();
153
154#ifdef ENABLE_RTSPSERVER
155 {
156 IPAddress ip;
157
158 //! done in MQTTNetworking.cpp
159 WiFi.mode(WIFI_STA);
160 WiFi.begin("SunnyWhiteriver", "sunny2021");
161 //! TODO: the MQTT isn't initialized yet .. so values are crap
162 //! NEEDS A CALLBACK registered when the internet is availabe ...
163 //SerialDebug.printf("SSID = %s, PASS= %s\n",get_WIFI_SSID(), get_WIFI_PASSWORD() );
164 //WiFi.begin(get_WIFI_SSID(), get_WIFI_PASSWORD());
165
166 int count = 0;
167 while (WiFi.status() != WL_CONNECTED)
168 {
169 delay(500);
170 SerialDebug.print(F("."));
171 if (count++ > 20)
172 return;
173 }
174 ip = WiFi.localIP();
175 SerialDebug.println(F("WiFi connected"));
176 SerialDebug.println("");
177 SerialDebug.println(ip);
178 SerialDebug.print("Stream Link: rtsp://");
179 SerialDebug.print(ip);
180 SerialDebug.println(":8554/mjpeg/1");
181 }
182#endif
183
184#ifdef ENABLE_RTSPSERVER
185 _rtspServer.begin();
186#endif
187}
188
189
190//! 8.17.25 add this for when SSID is set
191//!clean the SSID eprom (MQTT_CALLBACK_SSID_DETECTED)
192void ssidDetected_MessageCallback(char *message)
193{
194 SerialDebug.printf("TODO ssidDetected_MessageCallback %s\n", message);
195 //! call the code above to start the RTSP Server
196}
197
198//!! split this up.. Sure seems like the picture is taken right now!!
199void initCameraSensor()
200{
201
202 sensor_t *s = esp_camera_sensor_get();
203 //! initial sensors are flipped vertically and colors are a bit saturated
204 s->set_vflip(s, 1); // flip it back
205
206 s->set_brightness(s, 1); // up the blightness just a bit
207 s->set_saturation(s, -2); // lower the saturation
208
209 s->set_hmirror(s, 0); //?? horizontal mirror?
210
211 // drop down frame size for higher initial frame rate
212 // s->set_framesize(s, FRAMESIZE_QVGA);
213 // s->set_framesize(s, FRAMESIZE_UXGA);
214
215 SerialTemp.println("*** Camera Sensor Initialized ****");
216}
217
218#ifdef ENABLE_RTSPSERVER
219CStreamer *_rtsp_streamer;
220CRtspSession *_rtsp_session;
221WiFiClient _rtsp_client; // FIXME, support multiple clients
222
223#endif
224
225//!loop
226void loop_CameraModule()
227{
228#ifdef ESP_M5_CAMERA
229 // blink the light on the camera
230 // delay(100);
231 //digitalWrite(2, HIGH);
232 //delay(100);
233 // digitalWrite(2, LOW);
234#endif
235
236#ifdef ENABLE_RTSPSERVER
237 uint32_t msecPerFrame = 100;
238 static uint32_t lastimage = millis();
239
240 // If we have an active _rtsp_client connection, just service that until gone
241 // (FIXME - support multiple simultaneous _rtsp_clients)
242 if(_rtsp_session)
243 {
244 // SerialDebug.println("loop: _rtsp_session");
245 // we don't use a timeout here,
246 // instead we send only if we have new enough frames
247 _rtsp_session->handleRequests(0);
248
249 uint32_t now = millis();
250 // handle clock rollover
251 if(now > lastimage + msecPerFrame || now < lastimage)
252 {
253 _rtsp_session->broadcastCurrentFrame(now);
254 lastimage = now;
255
256 // check if we are overrunning our max frame rate
257 now = millis();
258 if(now > lastimage + msecPerFrame)
259 SerialDebug.printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
260 }
261
262 if(_rtsp_session->m_stopped)
263 {
264 delete _rtsp_session;
265 delete _rtsp_streamer;
266 _rtsp_session = NULL;
267 _rtsp_streamer = NULL;
268 }
269 }
270 else
271 {
272 _rtsp_client = _rtspServer.accept();
273
274
275 if(_rtsp_client)
276 {
277 //_rtsp_streamer = new SimStreamer(&_rtsp_client, true); // our _rtsp_streamer for UDP/TCP based RTP transport
278 _rtsp_streamer = new OV2640Streamer(&_rtsp_client, _camera); // our _rtsp_streamer for UDP/TCP based RTP transport
279
280 _rtsp_session = new CRtspSession(&_rtsp_client, _rtsp_streamer); // our threads RTSP _rtsp_session and state
281 // SerialDebug.printf("loop2: _rtsp_session: %d\n ", _rtsp_session);
282 }
283 else
284 {
285 // SerialDebug.printf(" ** still no rtsp_client %d\n", _rtspServer);
286 }
287 }
288
289#endif
290}
291
292//!@see https://github.com/m5stack/M5Stack-Camera
293//!take a picture
294void takePicture_CameraModule_internal(boolean publishBinary)
295{
296 //!try initializing each time..
297 // initCameraSensor();
298
299 //!turn on light
300 digitalWrite(2, HIGH);
301 //! cameras frame buffer
302 camera_fb_t *cameraFB = NULL;
303
304 //! Take Picture with Camera
305 cameraFB = esp_camera_fb_get();
306 if(!cameraFB)
307 {
308 SerialError.println("Camera capture failed");
309 return;
310 }
311 //we could use our EPROM for the next file name..
312#ifdef M5_CAPTURE_SCREEN
313
314 //for now save in SPIFF
315 writeFB_SPIFFModule(cameraFB->buf, /*!< Pointer to the pixel data */
316 cameraFB->len, /*!< Length of the buffer in bytes */
317 (char*)"/CameraPicture.jpg");
318#endif
319
320 //!turn off light
321 digitalWrite(2, LOW);
322
323 //! 8.16.25 MQTT
324 if (publishBinary)
325 publishBinaryFile((char*)"usersP/bark/images", cameraFB->buf, cameraFB->len, "jpg");
326 //!close it up
327 esp_camera_fb_return(cameraFB);
328
329}
330
331//!@see https://github.com/m5stack/M5Stack-Camera
332//!take a picture
333void takePicture_CameraModule()
334{
335 //! take 2 pics, so the framebuffer of 2 is flushed
336 //! 1.20.24
337 takePicture_CameraModule_internal(false);
338 delay(50);
339// takePicture_CameraModule_internal(false);
340// delay(50);
341// takePicture_CameraModule_internal(false);
342// delay(50);
343 takePicture_CameraModule_internal(true);
344 delay(50);
345
346}
347
348//!turn off on-board LED flash
349void flashConfig_CameraModule(boolean turnOn)
350{
351
352 // Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
353 pinMode(4, OUTPUT);
354 digitalWrite(4, LOW);
355 //?? rtc_gpio_hold_en(GPIO_NUM_4);
356}
357
358//!sleep the device
359void sleep_CameraModule()
360{
361 SerialDebug.println("Going to sleep now");
362 delay(2000);
363 esp_deep_sleep_start();
364}
365
366
367//! good example:
368//! https://randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card/
369
370
371
372//! BUTTON PROCESSING abstraction
373//!short press on buttonA (top button)
374void buttonA_ShortPress_CameraModule()
375{
376
377}
378//!long press on buttonA (top button)
379void buttonA_LongPress_CameraModule()
380{
381
382}
383#endif //use camera module
void publishBinaryFile(char *topic, uint8_t *buf, size_t len, String fileExtension)
void writeFB_SPIFFModule(uint8_t *buf, size_t len, char *fileName)
writes a FB to a file..
unsigned long millis()
Definition: TinyGPS.cpp:35