Im Rahmen des GET-Fachpraktikums [[1]] entsteht das Projekt „Überwachungskamera“. Sinn des Projektes ist es, ein mechatronisches System zu entwerfen, zu fertigen und zu testen. Dabei sollen vor allem die Kenntnisse aus dem Modul Mess- und Regelungstechnik zur Hilfe genommen werden.
Das System registriert mit Hilfe der Sensoren ungewöhnliche Ereignisse aufgrund von Bewegungen bzw. Geräuschen. Daraufhin macht die Kamera ein Foto und sendet dieses per Telegram-Bot [2] an den Nutzer.
Gehäuse
Das komplette Gehäuse ist mittels 3D-Druck erstellt worden. Die Verbindung der einzelnen Komponenten ist mittels Schrauben gelöst worden, um die Kamera leicht auseinandernehmbar zu gestalten.
Um die Verschiedenen Teile stabil Drucken zu können wurden vereinzelt Komponenten, wie z.B. die Kamerarückwand und die Verbindung an die Halterung.
Das Gehäuse ist in 3 Schichten Unterteilt: 1. Vorderseite (Bietet Aussparungen für die Kamera, Mikrofon und PIR), 2. Mittelring (Dient zu Fixierung der Bauteile ohne diese Anzukleben / Festzuschrauben), 3. Die Rückseite (Bietet erhöhtes Volumen für die Verkabelung und Stromzufuhr)
Halterung
Die Halterung kann in 2 Dimensionen Hoch/Runter und Links/Rechts bewegt werden. Hierbei dienen Schrauben zur Fixierung der Position, indem sie mittels "Quetschscheiben" die Bewegung verhindern.
An der Rückseite bietet die Halterung eine Platte zur Befestigung mittels Schrauben für einen Gewindedurchmesser von 4mm in allen 4 Ecken.
Schaltung
Das Mikrofon und der PIR sind an digitalen Pins des Mikrokontrollers angeschlossen. Mittels Widerstand ist ein Schwellwert eingestellt worden.
Die Kamera sowie der Wifi-Chip sind direkt auf dem Mikrokontrollers implementiert.
Code
Die Implementierung von Telegramm und das Verschicken von Bildern ist in Anlehnung an "https://randomnerdtutorials.com/telegram-esp32-cam-photo-arduino/" implementiert worden.
In "BOT_TOKEN" muss der Unique-Token des Erstellten Bots eingefügt werden. In "USER_CHAT_IDS" können eine beliebige Anzahl von Telegramm Accounts eingebunden werden, die ein Bild erhalten wollen.
Mit dem Befehl "/picture" kann ein manuell erstelltes Bild angefordert werden.
Mithilfe von den Variablen "motionState" und "micState" kan verhindert werden, dass aufgrund des selben Eingangssignals 2 identische Bilder direkt hintereinander versendet werden.
//WIFI#include<WiFi.h>#include<WiFiClientSecure.h>//TELEGRAM#include<UniversalTelegramBot.h>#include<ArduinoJson.h>//CAMERA#include"esp_camera.h"#include"camera_pins.h"//SENSOR#define MOTION_PIN 2boolmotionState=false;#define MIC_PIN 13boolmicState=false;//WIFIchar*SSID_WIFI="<SSID>";char*PASSWORD_WIFI="<PASSWORT>";//TELEGRAMStringBOT_TOKEN="<TOKEN:TOKEN>";intUSER_CHAT_ID_LENGTH=1;StringUSER_CHAT_IDS[]={"<USER ID>","<USER ID2>"};//TELEGRAMWiFiClientSecureclient;UniversalTelegramBotbot(BOT_TOKEN,client);//REQUEST TIMEintrequestDelay=1000;unsignedlonglastTime;voidprintNewMessage(intindex){Serial.println("------------------------");Serial.println("NEW MESSAGE:");Serial.print("USER: ");Serial.println(bot.messages[index].from_name);Serial.print("USER ID: ");Serial.println(bot.messages[index].chat_id);Serial.print("TEXT: ");Serial.println(bot.messages[index].text);Serial.println("------------------------");}voidprocessMessage(intmessageNum){for(inti=0;i<messageNum;i++){printNewMessage(i);Stringchat_id=String(bot.messages[i].chat_id);if(chatIdIsInChatIdList(chat_id)==true){Stringtext=bot.messages[i].text;Stringuser=bot.messages[i].from_name;if(text=="/start"){Stringresponse="";response+="Welcome, "+user+".\n";response+="Use the following commands to control your outputs.\n\n";response+="/picture to take a picture \n";response+="/start to get information\n";bot.sendMessage(chat_id,response,"");}elseif(text=="/picture"){Stringresponse="";response+="Take an Image...";bot.sendMessage(chat_id,response,"");sendPicture(chat_id,false);}else{Stringresponse="";response+="Unbekannter Befehl!\n";response+="Bitte versuche es erneut.";bot.sendMessage(chat_id,response,"");}}else{bot.sendMessage(chat_id,"Unauthorized User","");continue;}}}boolchatIdIsInChatIdList(Stringchat_id){for(inti=0;i<USER_CHAT_ID_LENGTH;i++){if(chat_id==USER_CHAT_IDS[i]){returntrue;}}returnfalse;}StringsendPicture(Stringchat_id,boolflash){constchar*myDomain="api.telegram.org";StringgetAll="";StringgetBody="";camera_fb_t*fb=NULL;fb=esp_camera_fb_get();if(!fb){Serial.println("Camera capture failed");delay(1000);ESP.restart();return"Camera capture failed";}Serial.println("Connect to "+String(myDomain));if(client.connect(myDomain,443)){Serial.println("Connection successful");//X ==> BoundaryStringhead="--X\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n"+chat_id+"\r\n--X\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";Stringtail="\r\n--X--\r\n";uint16_timageLen=fb->len;uint16_textraLen=head.length()+tail.length();uint16_ttotalLen=imageLen+extraLen;client.println("POST /bot"+BOT_TOKEN+"/sendPhoto HTTP/1.1");client.println("Host: "+String(myDomain));client.println("Content-Length: "+String(totalLen));client.println("Content-Type: multipart/form-data; boundary=X");client.println();client.print(head);uint8_t*fbBuf=fb->buf;size_tfbLen=fb->len;for(size_tn=0;n<fbLen;n=n+1024){if(n+1024<fbLen){client.write(fbBuf,1024);fbBuf+=1024;}elseif(fbLen%1024>0){size_tremainder=fbLen%1024;client.write(fbBuf,remainder);}}client.print(tail);esp_camera_fb_return(fb);intwaitTime=10000;// timeout 10 secondslongstartTimer=millis();booleanstate=false;while((startTimer+waitTime)>millis()){Serial.print(".");delay(100);while(client.available()){charc=client.read();if(c=='\n'){if(getAll.length()==0)state=true;getAll="";}elseif(c!='\r')getAll+=String(c);if(state==true)getBody+=String(c);startTimer=millis();}if(getBody.length()>0)break;}client.stop();Serial.println(getBody);}else{getBody="Connected to api.telegram.org failed.";Serial.println("Connected to api.telegram.org failed.");}returngetBody;}voidsetup(){startSerial();connectToWifi();setTelegramCertificate();setupCamera();}voidsetupHardware(){/* pinMode(MOTION_PIN, INPUT); pinMode(MIC_PIN, INPUT); */}voidstartSerial(){Serial.begin(115200);Serial.println("Start SERIAL");}voidsetTelegramCertificate(){client.setCACert(TELEGRAM_CERTIFICATE_ROOT);}voidconnectToWifi(){Serial.println("Connect to WIFI");WiFi.begin(SSID_WIFI,PASSWORD_WIFI);while(WiFi.status()!=WL_CONNECTED){delay(500);Serial.print(".");}Serial.println("");Serial.print("IP: ");Serial.println(WiFi.localIP());}voidsetupCamera(){Serial.println("Setup CAMERA");camera_config_tconfig;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_SVGA;//SVGA 800x600 / UXGA 1600x1200config.jpeg_quality=10;config.fb_count=2;esp_err_terr=esp_camera_init(&config);if(err!=ESP_OK){Serial.printf("Setup CAMERA failed with ERROR: ",err);return;}}voidloop(){checkSensors();checkMessagingServer();}voidcheckSensors(){//PIR MOTION SENSOR//Serial.println(digitalRead(MOTION_PIN));if(motionState==true&&digitalRead(MOTION_PIN)==0){motionState=false;}if(motionState==false&&digitalRead(MOTION_PIN)==1){for(inti=0;i<USER_CHAT_ID_LENGTH;i++){bot.sendMessage(USER_CHAT_IDS[i],"MOTION detected","");sendPicture(USER_CHAT_IDS[i],false);}motionState=true;}//MICROFONSerial.println(digitalRead(MIC_PIN));if(micState==true&&digitalRead(MIC_PIN)==0){micState=false;}if(micState==false&&digitalRead(MIC_PIN)==1){for(inti=0;i<USER_CHAT_ID_LENGTH;i++){bot.sendMessage(USER_CHAT_IDS[i],"SOUND detected","");sendPicture(USER_CHAT_IDS[i],false);}micState=true;}}voidcheckMessagingServer(){if(millis()>lastTime+requestDelay){intnumOfMessages=bot.getUpdates(bot.last_message_received+1);if(numOfMessages!=0){boolnewMessage=true;while(newMessage){processMessage(numOfMessages);// is there another new messagenumOfMessages=bot.getUpdates(bot.last_message_received+1);if(numOfMessages==0){newMessage=false;}}}lastTime=millis();}}
Zusammenbau
Beim Zusammenbau wurde darauf geachtet, dass die Kabel nicht direkt an die Kontakte gelötet werden, um später noch Änderungen am Programmcode vornehmen zu können.
Aus diesem Grund sind die Sensoren und der Mikrokontroller mittels Steckverbinder verschaltet.
Komponententest
Ergebnis
Zusammenfassung
Lessons Learned
Projektunterlagen
Projektplan
Umsetzung (HW/SW)
Tabelle 3: Bearbeitung der Meilensteine
ID
Meilensteine
Erledigt am
Erledigt von
1
PIR Sensor wird vom Mikrocontroller eingelesen und detektiert Bewegung korrekt
12.10.2022
Henry Fröse
2
Mikrofon wird vom Mikrocontroller eingelesen und detektiert Lautstärke korrekt
12.10.2022
Henry Fröse
3
Inbetriebnahme der Kamera mittels enthaltenem Beispielprogramm
15.10.2022
Henry Fröse
4
Verbinden des Mikrocontrollers mit dem Heimnetzwerk
16.10.2022
Henry Fröse
5
Erstellung eines Telegramm-Bots
22.10.2022
Kevin Mudczinski
6
Verbindung zwischen Telegram-Bot und Mikrocontroller aufgebaut
22.10.2022
Kevin Mudczinski
7
Erstellung einfacher Testbefehle mit Textzurückgabe
24.10.2022
Kevin Mudczinski
8
Verschicken von Bilder mittels Telegram-Bot
28.10.2022
Kevin Mudczinski
9
Automatische Versendung von Bildern bei Bewegungen und Geräuschen