-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMotion-Cam.ino
275 lines (261 loc) · 8.37 KB
/
Motion-Cam.ino
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
//
// I leave anyone that find this useful the ultimate freedom of using, changing, alter, missuse as they please
// I don't promise it will work, neither do I promise that your equipment will work after trying it.
//
#include "esp_camera.h"
#include <FS.h>
#include "SD_MMC.h"
#include "EEPROM.h"
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define motionPin 3
const char* ssid = "YourAPHere"; // Note!! This is where you put your AP
const char* password = "YourPWDHere";// Note!! This is where you put your PWD!
AsyncWebServer server(80); // If this address doesn't fit you, by all means chose another! But you have to remeber the port to be able to check on the pictures!
String fileNames[520]; // Just so I can keep the file names in an array
int fileCount = 0; // Counter is a counter is a counter.
// All this you can find everywhere, I was a bit stupid and spent hours on reading when it was readily available on all places.
void configCamera() {
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
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_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
esp_err_t err = esp_camera_init(&config);
sensor_t* s = esp_camera_sensor_get();
s->set_brightness(s, 0);
s->set_contrast(s, 0);
s->set_saturation(s, 0);
s->set_special_effect(s, 0);
s->set_whitebal(s, 1);
s->set_awb_gain(s, 1);
s->set_wb_mode(s, 0);
s->set_exposure_ctrl(s, 1);
s->set_aec2(s, 0);
s->set_ae_level(s, 0);
s->set_aec_value(s, 300);
s->set_gain_ctrl(s, 1);
s->set_agc_gain(s, 0);
s->set_gainceiling(s, (gainceiling_t)0);
s->set_bpc(s, 0);
s->set_wpc(s, 1);
s->set_raw_gma(s, 1);
s->set_lenc(s, 1);
s->set_hmirror(s, 0);
s->set_vflip(s, 0);
s->set_dcw(s, 1);
s->set_colorbar(s, 0);
}
unsigned int incCounter() {
unsigned int cnt = 0;
EEPROM.get(0, cnt);
EEPROM.put(0, cnt + 1);
EEPROM.commit();
fileCount = 0;
return cnt;
}
//Found this on the Internet I haven't got a clue what it does but it seems important to use?? Why?? More reading to do!
void skipPictures(int n) {
for(int i=0; i<n; i++) {
camera_fb_t* fb = esp_camera_fb_get();
esp_camera_fb_return(fb);
}
}
void takePicture() {
camera_fb_t* fb = esp_camera_fb_get();
unsigned int cnt = incCounter();
String path = "/img" + String(cnt) + ".jpg";
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if(!file){
Serial.println("Failed to open file in writing mode");
Serial.println("Path: " + path);
Serial.println("Is the file already open?");
Serial.println("Is the SD card full?");
Serial.println("Is the filename format correct?");
return;
}else{
file.write(fb->buf, fb->len);
Serial.println("Filen skriven");
}
file.close();
esp_camera_fb_return(fb);
delay(100);
updateFileList();// Update the list so that the webpage is up to date
delay(500);
}
void setupWiFi(){
WiFi.persistent(false); // Not really needed but I forgot to remove it so it just as well stay. (was testing with another webserver library that needed it)
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
WiFi.setSleep(false);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("Kopplad mot nätet"); //Connected
Serial.print("Adress: ");// Your address to connect to the server
Serial.println(WiFi.localIP());//The numbers!
}
void setupCardReader() {
if (!SD_MMC.begin()) {
Serial.println("\nKortfel!");// Something wrong
return;
}
Serial.println("\nKort initialiserat");
File root = SD_MMC.open("/");
if (!root) {
Serial.println("Kunde inte öppna /!");
return;
}
File file = root.openNextFile();
while (file) {
String fileName = file.name();
fileNames[fileCount++] = fileName; // Lägg till filnamnet i arrayen
file = root.openNextFile();
}
if(!SD_MMC.exists("/oldpictures")){
SD_MMC.mkdir("/oldpictures");
}
}
void updateFileList(){
fileCount = 1;
File root = SD_MMC.open("/");
if (!root) {
Serial.println("Kunde inte öppna /!");
return;
}
File file = root.openNextFile();
while (file) {
String fileName = file.name();
fileNames[fileCount++] = fileName; // Lägg till filnamnet i arrayen
if (fileCount >= 511){
moveJpgToOldPictures(SD_MMC,"/");
fileCount = 1;
}
file = root.openNextFile();
}
}
void moveJpgToOldPictures(fs::FS &fs, const char * dirname){
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(!file.isDirectory()){
String fileName = file.name();
if(fileName.endsWith(".jpg")){
String newFileName = "/oldpictures/" + fileName;
fs.rename(file.name(), newFileName.c_str());
Serial.println("Moved file: " + fileName + " to " + newFileName);
}
}
file = root.openNextFile();
}
resetEEPROM();
}
void resetEEPROM(){
unsigned int resetValue = 0;
EEPROM.put(0, resetValue);
EEPROM.commit(); // Skriv ändringarna permanent till EEPROM.
Serial.println("Räknaren har nollställts.");
}
void setup() {
Serial.begin(115200);
Serial.println("\n");
pinMode(motionPin, INPUT/*_PULLUP*/);
digitalWrite(motionPin, LOW);
setupWiFi();
setupCardReader();
EEPROM.begin(9);
SD_MMC.begin();
configCamera();
skipPictures(10);
takePicture();
Serial.println("Startar Server");
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
Serial.println("/");
Serial.println(request->url());
String html = "<html><head><meta http-equiv='refresh' content='15'>";// I am not sure but if I remember correct this should update the
html += "</head><body><h1>Fil Lista:</h1><ul>"; // browser once every 15 seconds.
for (int i = 0; i < fileCount; i++) {
html += "<li><a href='/";
html += fileNames[i].substring(fileNames[i].lastIndexOf('/') + 1); // Endast filnamn
html += "'>";
html += fileNames[i].substring(fileNames[i].lastIndexOf('/') + 1); // Endast filnamn
html += "</a></li>";
}
html += "</ul></body></html>";
request->send(200, "text/html", html);
});
server.on("/*", HTTP_GET, [](AsyncWebServerRequest* request) {
String filePath = "/" + request->url().substring(request->url().lastIndexOf('/') + 1);
Serial.print("Försöker öppna fil: ");
Serial.println(filePath);
File file = SD_MMC.open(filePath);
if (file) {
request->send(SD_MMC, filePath, "image/jpeg"); // Skicka filen / Sending file
} else {
request->send(404, "text/plain", "Filen hittades inte"); // Not found
}
file.close();
});
server.begin();
Serial.print("IP adress: " ); // Once more just for fun!
Serial.println(WiFi.localIP());
}
void loop() {
int reading = digitalRead(motionPin);
//Serial.println(reading);
if (reading == HIGH){
//Serial.println("Hög"); // only used when testing
takePicture();
delay(2000); // Shorten this or make it longer up to you. But I recomend a delay of at least 1 second. Looks like it takes some time for the camera to save the file.
}
/*if (reading == LOW){
//Serial.println("Låg"); // only used when testing
}*/
delay(1000); // Reapete once a second. Adjust to your liking.
}