Skip to content
This repository was archived by the owner on Jan 16, 2022. It is now read-only.

Commit 9eee85c

Browse files
authored
ESP32-CAM example
1 parent 785de8a commit 9eee85c

File tree

2 files changed

+382
-0
lines changed

2 files changed

+382
-0
lines changed

examples/ESP32-CAM/ESP32-CAM.ino

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
Name: echoBot.ino
3+
Created: 20/06/2020
4+
Author: Tolentino Cotesta <cotestatnt@yahoo.com>
5+
Description: an example that show how is possible send an image captured from a ESP32-CAM board
6+
*/
7+
8+
// WARNING!!!
9+
// Make sure that you have selected ESP32 Wrover Module, or another board which has PSRAM enabled
10+
11+
#include "esp_camera.h"
12+
13+
// Select camera model
14+
//#define CAMERA_MODEL_WROVER_KIT
15+
//#define CAMERA_MODEL_ESP_EYE
16+
//#define CAMERA_MODEL_M5STACK_PSRAM
17+
//#define CAMERA_MODEL_M5STACK_WIDE
18+
#define CAMERA_MODEL_AI_THINKER
19+
#include "camera.h"
20+
21+
#include "soc/soc.h" // Brownout error fix
22+
#include "soc/rtc_cntl_reg.h" // Brownout error fix
23+
24+
// Define where store images (on board SD card reader or internal flash memory)
25+
#define USE_MMC true
26+
#ifdef USE_MMC
27+
#include <SD_MMC.h> // Use onboard SD Card reader
28+
fs::FS &filesystem = SD_MMC;
29+
#else
30+
#include <FFat.h> // Use internal flash memory
31+
fs::FS &filesystem = FFat; // Is necessary select the proper partition scheme (ex. "Default 4MB with ffta..")
32+
#endif
33+
34+
// You only need to format FFat when error on mount (don't work with MMC SD card)
35+
#define FORMAT_FS_IF_FAILED true
36+
#define FILENAME_SIZE 20
37+
#define KEEP_IMAGE true
38+
39+
#include <WiFi.h>
40+
#include <AsyncTelegram.h>
41+
AsyncTelegram myBot;
42+
43+
const char* ssid = "XXXXXXXX"; // REPLACE mySSID WITH YOUR WIFI SSID
44+
const char* pass = "XXXXXXXX"; // REPLACE myPassword YOUR WIFI PASSWORD, IF ANY
45+
const char* token = "XXXXXXXXXXXXXXXXXXXX"; // REPLACE myToken WITH YOUR TELEGRAM BOT TOKEN
46+
47+
48+
// Struct for saving time datas (needed for time-naming the image files)
49+
struct tm timeinfo;
50+
51+
52+
// List all files saved in the selected filesystem
53+
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
54+
Serial.printf("Listing directory: %s\r\n", dirname);
55+
56+
File root = fs.open(dirname);
57+
if(!root){
58+
Serial.println("- failed to open directory");
59+
return;
60+
}
61+
if(!root.isDirectory()){
62+
Serial.println(" - not a directory");
63+
return;
64+
}
65+
66+
File file = root.openNextFile();
67+
while(file){
68+
if(file.isDirectory()){
69+
Serial.printf(" DIR : %s", file.name());
70+
if(levels)
71+
listDir(fs, file.name(), levels -1);
72+
}
73+
else
74+
Serial.printf(" FILE: %s\tSIZE: %d", file.name(), file.size());
75+
76+
file = root.openNextFile();
77+
}
78+
}
79+
80+
String takePicture(fs::FS &fs){
81+
82+
// Set filename with current timestamp "YYYYMMDD_HHMMSS.jpg"
83+
char pictureName[FILENAME_SIZE];
84+
getLocalTime(&timeinfo);
85+
snprintf(pictureName, FILENAME_SIZE, "%02d%02d%02d_%02d%02d%02d.jpg", timeinfo.tm_year +1900,
86+
timeinfo.tm_mon +1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
87+
88+
// Path where new picture will be saved
89+
String path = "/";
90+
path += String(pictureName);
91+
92+
File file = fs.open(path.c_str(), FILE_WRITE);
93+
if(!file){
94+
Serial.println("Failed to open file in writing mode");
95+
return "";
96+
}
97+
98+
// Take Picture with Camera
99+
ledcWrite(15, 255); // Flash led ON
100+
camera_fb_t * fb = esp_camera_fb_get();
101+
if(!fb) {
102+
Serial.println("Camera capture failed");
103+
return "";
104+
}
105+
ledcWrite(15, 0); // Flash led OFF
106+
107+
// Save picture to memory
108+
#ifdef USE_MMC
109+
uint64_t freeBytes = SD_MMC.totalBytes() - SD_MMC.usedBytes();
110+
#else
111+
uint64_t freeBytes = filesystem.freeBytes();
112+
#endif
113+
114+
if(freeBytes> file.size() ){
115+
file.write(fb->buf, fb->len); // payload (image), payload length
116+
Serial.printf("Saved file to path: %s\n", path.c_str());
117+
file.close();
118+
}
119+
else
120+
Serial.println("Not enough space avalaible");
121+
122+
esp_camera_fb_return(fb);
123+
return path;
124+
}
125+
126+
127+
void setup() {
128+
Serial.begin(115200);
129+
Serial.setDebugOutput(true);
130+
Serial.println();
131+
132+
// Init the camera
133+
cameraSetup(FRAMESIZE_UXGA);
134+
135+
// Init WiFi connections
136+
WiFi.begin(ssid, pass);
137+
while (WiFi.status() != WL_CONNECTED) {
138+
delay(500);
139+
Serial.print(".");
140+
}
141+
Serial.print("\nWiFi connected: ");
142+
Serial.print(WiFi.localIP());
143+
144+
// Init filesystem
145+
#ifdef USE_MMC
146+
if(!SD_MMC.begin())
147+
Serial.println("SD Card Mount Failed");
148+
if(SD_MMC.cardType() == CARD_NONE)
149+
Serial.println("No SD Card attached");
150+
Serial.printf("\nTotal space: %10llu\n", SD_MMC.totalBytes());
151+
Serial.printf("Free space: %10llu\n", SD_MMC.totalBytes() - SD_MMC.usedBytes());
152+
#else
153+
// Init filesystem (format if necessary)
154+
if(!filesystem.begin(FORMAT_FS_IF_FAILED))
155+
Serial.println("\nFS Mount Failed.\nFilesystem will be formatted, please wait.");
156+
Serial.printf("\nTotal space: %10lu\n", filesystem.totalBytes());
157+
Serial.printf("Free space: %10lu\n", filesystem.freeBytes());
158+
#endif
159+
160+
listDir(filesystem, "/", 0);
161+
162+
// Set the Telegram bot properies
163+
myBot.setUpdateTime(1000);
164+
myBot.setTelegramToken(token);
165+
166+
// Check if all things are ok
167+
Serial.print("\nTest Telegram connection... ");
168+
myBot.begin() ? Serial.println("OK") : Serial.println("NOK");
169+
170+
// Init and get the system time
171+
configTime(3600, 3600, "pool.ntp.org");
172+
getLocalTime(&timeinfo);
173+
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
174+
175+
}
176+
177+
void loop() {
178+
179+
// A variable to store telegram message data
180+
TBMessage msg;
181+
182+
// if there is an incoming message...
183+
if (myBot.getNewMessage(msg)) {
184+
Serial.print("New message from chat_id: ");
185+
Serial.println(msg.sender.id);
186+
MessageType msgType = msg.messageType;
187+
188+
if (msgType == MessageText){
189+
// Received a text message
190+
if (msg.text.equalsIgnoreCase("/takePhoto")) {
191+
Serial.println("\nSending Photo from CAM");
192+
193+
// Take picture and save to file
194+
String myFile = takePicture(filesystem);
195+
if(myFile != "") {
196+
myBot.sendPhotoByFile(msg.sender.id, myFile, filesystem);
197+
198+
//If you don't need to keep image in memory, delete it
199+
if(KEEP_IMAGE == false){
200+
filesystem.remove("/" + myFile);
201+
}
202+
}
203+
}
204+
else {
205+
Serial.print("\nText message received: ");
206+
Serial.println(msg.text);
207+
String replyStr = "Message received:\n";
208+
replyStr += msg.text;
209+
replyStr += "\nTry with /takePhoto";
210+
myBot.sendMessage(msg, replyStr);
211+
}
212+
213+
}
214+
}
215+
}

examples/ESP32-CAM/camera.h

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
2+
#define FLASH_LED 4
3+
4+
#if defined(CAMERA_MODEL_WROVER_KIT)
5+
#define PWDN_GPIO_NUM -1
6+
#define RESET_GPIO_NUM -1
7+
#define XCLK_GPIO_NUM 21
8+
#define SIOD_GPIO_NUM 26
9+
#define SIOC_GPIO_NUM 27
10+
11+
#define Y9_GPIO_NUM 35
12+
#define Y8_GPIO_NUM 34
13+
#define Y7_GPIO_NUM 39
14+
#define Y6_GPIO_NUM 36
15+
#define Y5_GPIO_NUM 19
16+
#define Y4_GPIO_NUM 18
17+
#define Y3_GPIO_NUM 5
18+
#define Y2_GPIO_NUM 4
19+
#define VSYNC_GPIO_NUM 25
20+
#define HREF_GPIO_NUM 23
21+
#define PCLK_GPIO_NUM 22
22+
23+
#elif defined(CAMERA_MODEL_ESP_EYE)
24+
#define PWDN_GPIO_NUM -1
25+
#define RESET_GPIO_NUM -1
26+
#define XCLK_GPIO_NUM 4
27+
#define SIOD_GPIO_NUM 18
28+
#define SIOC_GPIO_NUM 23
29+
30+
#define Y9_GPIO_NUM 36
31+
#define Y8_GPIO_NUM 37
32+
#define Y7_GPIO_NUM 38
33+
#define Y6_GPIO_NUM 39
34+
#define Y5_GPIO_NUM 35
35+
#define Y4_GPIO_NUM 14
36+
#define Y3_GPIO_NUM 13
37+
#define Y2_GPIO_NUM 34
38+
#define VSYNC_GPIO_NUM 5
39+
#define HREF_GPIO_NUM 27
40+
#define PCLK_GPIO_NUM 25
41+
42+
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
43+
#define PWDN_GPIO_NUM -1
44+
#define RESET_GPIO_NUM 15
45+
#define XCLK_GPIO_NUM 27
46+
#define SIOD_GPIO_NUM 25
47+
#define SIOC_GPIO_NUM 23
48+
49+
#define Y9_GPIO_NUM 19
50+
#define Y8_GPIO_NUM 36
51+
#define Y7_GPIO_NUM 18
52+
#define Y6_GPIO_NUM 39
53+
#define Y5_GPIO_NUM 5
54+
#define Y4_GPIO_NUM 34
55+
#define Y3_GPIO_NUM 35
56+
#define Y2_GPIO_NUM 32
57+
#define VSYNC_GPIO_NUM 22
58+
#define HREF_GPIO_NUM 26
59+
#define PCLK_GPIO_NUM 21
60+
61+
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
62+
#define PWDN_GPIO_NUM -1
63+
#define RESET_GPIO_NUM 15
64+
#define XCLK_GPIO_NUM 27
65+
#define SIOD_GPIO_NUM 22
66+
#define SIOC_GPIO_NUM 23
67+
68+
#define Y9_GPIO_NUM 19
69+
#define Y8_GPIO_NUM 36
70+
#define Y7_GPIO_NUM 18
71+
#define Y6_GPIO_NUM 39
72+
#define Y5_GPIO_NUM 5
73+
#define Y4_GPIO_NUM 34
74+
#define Y3_GPIO_NUM 35
75+
#define Y2_GPIO_NUM 32
76+
#define VSYNC_GPIO_NUM 25
77+
#define HREF_GPIO_NUM 26
78+
#define PCLK_GPIO_NUM 21
79+
80+
#elif defined(CAMERA_MODEL_AI_THINKER)
81+
#define PWDN_GPIO_NUM 32
82+
#define RESET_GPIO_NUM -1
83+
#define XCLK_GPIO_NUM 0
84+
#define SIOD_GPIO_NUM 26
85+
#define SIOC_GPIO_NUM 27
86+
87+
#define Y9_GPIO_NUM 35
88+
#define Y8_GPIO_NUM 34
89+
#define Y7_GPIO_NUM 39
90+
#define Y6_GPIO_NUM 36
91+
#define Y5_GPIO_NUM 21
92+
#define Y4_GPIO_NUM 19
93+
#define Y3_GPIO_NUM 18
94+
#define Y2_GPIO_NUM 5
95+
#define VSYNC_GPIO_NUM 25
96+
#define HREF_GPIO_NUM 23
97+
#define PCLK_GPIO_NUM 22
98+
99+
#else
100+
#error "Camera model not selected"
101+
#endif
102+
103+
void cameraSetup(framesize_t frameSize){
104+
pinMode(FLASH_LED, OUTPUT);
105+
// configure LED PWM functionalitites (ledChannel, freq, resolution);
106+
ledcSetup(15, 5000, 8);
107+
ledcAttachPin(FLASH_LED, 15);
108+
ledcWrite(15, 0); // Flash led OFF
109+
110+
camera_config_t config;
111+
config.ledc_channel = LEDC_CHANNEL_0;
112+
config.ledc_timer = LEDC_TIMER_0;
113+
config.pin_d0 = Y2_GPIO_NUM;
114+
config.pin_d1 = Y3_GPIO_NUM;
115+
config.pin_d2 = Y4_GPIO_NUM;
116+
config.pin_d3 = Y5_GPIO_NUM;
117+
config.pin_d4 = Y6_GPIO_NUM;
118+
config.pin_d5 = Y7_GPIO_NUM;
119+
config.pin_d6 = Y8_GPIO_NUM;
120+
config.pin_d7 = Y9_GPIO_NUM;
121+
config.pin_xclk = XCLK_GPIO_NUM;
122+
config.pin_pclk = PCLK_GPIO_NUM;
123+
config.pin_vsync = VSYNC_GPIO_NUM;
124+
config.pin_href = HREF_GPIO_NUM;
125+
config.pin_sscb_sda = SIOD_GPIO_NUM;
126+
config.pin_sscb_scl = SIOC_GPIO_NUM;
127+
config.pin_pwdn = PWDN_GPIO_NUM;
128+
config.pin_reset = RESET_GPIO_NUM;
129+
config.xclk_freq_hz = 20000000;
130+
config.pixel_format = PIXFORMAT_JPEG;
131+
//init with high specs to pre-allocate larger buffers
132+
if(psramFound() && frameSize == FRAMESIZE_UXGA){
133+
config.frame_size = FRAMESIZE_UXGA;
134+
config.jpeg_quality = 10;
135+
config.fb_count = 2;
136+
} else {
137+
config.frame_size = frameSize;
138+
config.jpeg_quality = 15;
139+
config.fb_count = 1;
140+
}
141+
142+
#if defined(CAMERA_MODEL_ESP_EYE)
143+
pinMode(13, INPUT_PULLUP);
144+
pinMode(14, INPUT_PULLUP);
145+
#endif
146+
147+
// camera init
148+
esp_err_t err = esp_camera_init(&config);
149+
if (err != ESP_OK) {
150+
Serial.printf("Camera init failed with error 0x%x", err);
151+
return;
152+
}
153+
154+
sensor_t * s = esp_camera_sensor_get();
155+
//initial sensors are flipped vertically and colors are a bit saturated
156+
if (s->id.PID == OV3660_PID) {
157+
s->set_vflip(s, 1);//flip it back
158+
s->set_brightness(s, 1);//up the blightness just a bit
159+
s->set_saturation(s, -2);//lower the saturation
160+
}
161+
162+
163+
#if defined(CAMERA_MODEL_M5STACK_WIDE)
164+
s->set_vflip(s, 1);
165+
s->set_hmirror(s, 1);
166+
#endif
167+
}

0 commit comments

Comments
 (0)