Maker.io main logo

ESP32-CAM with PIR motion sensor PLUS Telegram?

481

2022-07-17 | By M5Stack

License: General Public License Arduino ESP32

* Thanks for the source code and project information provided by @c010rblind3ngineer

 

Things used in this project

Arduino UNO

M5Stack ESP32 Camera Module Development Board

HC-SR501 PIR sensor

5 mm LED: Green

Resistor 220 ohm

Breadboard (generic)

Jumper wires (generic)

 

Software apps and online services

Arduino IDE

 

Story

 

I wanted to create a network camera that can capture movement and allow me to access it easily through an app. Furthermore, the Telegram app is something that I am familiar with as it has been on the market for quite some time now.

The idea of this project is to use the ESP32-CAM with the PIR sensor to notify me if a delivery person is at my door (since sometimes there's no one at home... or I could be busy blasting my earbuds with music 😅).

So I had this ESP32-CAM for a few years now and ashamed to say... didn't really do anything with it. Alas! I took the courage to make something out of it.

Luckily, I stumbled upon Rui Santos's amazing website, and it did make it clearer for me to carry out this project since he has already done a similar build.

In his website you can also follow his step-by-step tutorial on how to install the intended libraries to run this project too!

I hope this project serves well for you! 😊

 

 

 

                                          Watch this video to see how it works!

 

Schematics

Circuit:

2

 

Schematic:

1

 

Code

Code:Arduino

Copy Code
/* ESP32-CAM PIR motion sensor to Telegram alert

   Using the below mentioned project as the base template,
   I wanted to create a network camera that is capable of
   capturing movement and be able to access it easily
   through an app. The idea was to use it to notify me if
   the delivery person is at my door (as sometimes there's no one at home).
   
   Luckily I stumbled upon Rui Santos's amazing website,
   and it did make it easier for me since he has already done
   such a project. 
   
   You can follow his step by step tutorial on how to 
   install the intended libraries to run this project too!

   Components:
                - Arduino Uno
                - ESP32-CAM
                - HC-SR501 PIR sensor
                - Green LED 
                - 220Ohm resistor
                - Helping-Hands tool with alligator clips
                - Breadboard
                - Some jumper wires    
                
///////////////////////////////////////////////////////////////////////////////////////////////////
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/telegram-esp32-cam-photo-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>

const char* ssid = "ENTER YOUR WIFI NETWORK";
const char* password = "*************";

// Initialize Telegram BOT
String BOTtoken = "**********:***********************************";  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
String CHAT_ID = "**********";

bool sendPhoto = false;

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);

#define FLASH_LED_PIN 4
bool flashState = LOW;

//Checks for new messages every 1 second.
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;

const int PIRsensor = 13;
const int led = 12;
int PIRstate = LOW; // we start, assuming no motion detected
int val = 0;

// the time we give the sensor to calibrate (approx. 10-60 secs according to datatsheet)
const int calibrationTime = 30; // 30 secs

//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


void configInitCamera() {
  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;

  //init with high specs to pre-allocate larger buffers
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;  //0-63 lower number means higher quality
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;  //0-63 lower number means higher quality
    config.fb_count = 1;
  }

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    delay(1000);
    ESP.restart();
  }

  // Drop down frame size for higher initial frame rate
  sensor_t * s = esp_camera_sensor_get();
  s->set_framesize(s, FRAMESIZE_CIF);  // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
}

void handleNewMessages(int numNewMessages) {
  Serial.print("Handle New Messages: ");
  Serial.println(numNewMessages);

  for (int i = 0; i < numNewMessages; i  ) {
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

    // Print the received message
    String text = bot.messages[i].text;
    Serial.println(text);

    String from_name = bot.messages[i].from_name;
    if (text == "/start") {
      String welcome = "Welcome , "   from_name   "\n";
      welcome  = "Use the following commands to interact with the ESP32-CAM \n";
      welcome  = "/photo : takes a new photo\n";
      welcome  = "/flash : toggles flash LED \n";
      bot.sendMessage(CHAT_ID, welcome, "");
    }
    if (text == "/flash") {
      flashState = !flashState;
      digitalWrite(FLASH_LED_PIN, flashState);
      Serial.println("Change flash LED state");
    }
    if (text == "/photo") {
      sendPhoto = true;
      Serial.println("New photo request");
    }
  }
}

String sendPhotoTelegram() {
  const char* myDomain = "api.telegram.org";
  String getAll = "";
  String getBody = "";

  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 (clientTCP.connect(myDomain, 443)) {
    Serial.println("Connection successful");

    String head = "--c010blind3ngineer\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n"   CHAT_ID   "\r\n--c010blind3ngineer\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--c010blind3ngineer--\r\n";

    uint16_t imageLen = fb->len;
    uint16_t extraLen = head.length()   tail.length();
    uint16_t totalLen = imageLen   extraLen;

    clientTCP.println("POST /bot"   BOTtoken   "/sendPhoto HTTP/1.1");
    clientTCP.println("Host: "   String(myDomain));
    clientTCP.println("Content-Length: "   String(totalLen));
    clientTCP.println("Content-Type: multipart/form-data; boundary=c010blind3ngineer");
    clientTCP.println();
    clientTCP.print(head);

    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n = 0; n < fbLen; n = n   1024) {
      if (n   1024 < fbLen) {
        clientTCP.write(fbBuf, 1024);
        fbBuf  = 1024;
      }
      else if (fbLen % 1024 > 0) {
        size_t remainder = fbLen % 1024;
        clientTCP.write(fbBuf, remainder);
      }
    }

    clientTCP.print(tail);

    esp_camera_fb_return(fb);

    int waitTime = 10000;   // timeout 10 seconds
    long startTimer = millis();
    boolean state = false;

    while ((startTimer   waitTime) > millis()) {
      Serial.print(".");
      delay(100);
      while (clientTCP.available()) {
        char c = clientTCP.read();
        if (state == true) getBody  = String(c);
        if (c == '\n') {
          if (getAll.length() == 0) state = true;
          getAll = "";
        }
        else if (c != '\r')
          getAll  = String(c);
        startTimer = millis();
      }
      if (getBody.length() > 0) break;
    }
    clientTCP.stop();
    Serial.println(getBody);
  }
  else {
    getBody = "Connected to api.telegram.org failed.";
    Serial.println("Connected to api.telegram.org failed.");
  }
  return getBody;
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  // Init Serial Monitor
  Serial.begin(115200);

  // Set LED Flash as output
  pinMode(FLASH_LED_PIN, OUTPUT);
  digitalWrite(FLASH_LED_PIN, flashState);

  // Set PIR sensor as input and LED as output
  pinMode(PIRsensor, INPUT);
  pinMode(led, OUTPUT);

  // Give some time for the PIR sensor to warm up
  Serial.println("Waiting for the sensor to warm up on first boot");
  delay(calibrationTime * 1000); // Time converted back to miliseconds

  // Blink LED 3 times to indicate PIR sensor warmed up
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  Serial.println("PIR sensor is ACTIVE");

  // Config and init the camera
  configInitCamera();

  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("ESP32-CAM IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  val = digitalRead(PIRsensor);

  if (val == HIGH) {
    digitalWrite(led, HIGH);
    if (PIRstate == LOW) {
      // we have just turned on because movement is detected
      Serial.println("Motion detected!");
      delay(500);
      Serial.println("Sending photo to Telegram");
      sendPhotoTelegram();
      PIRstate = HIGH;
    }
  }
  else if (sendPhoto) {
    Serial.println("Preparing photo");
    digitalWrite(FLASH_LED_PIN, HIGH);
    Serial.println("Flash state set to HIGH");
    delay(500);
    sendPhotoTelegram();
    sendPhoto = false;
    digitalWrite(FLASH_LED_PIN, LOW);
    Serial.println("Flash state set to LOW");
  }
  else if (millis() > lastTimeBotRan   botRequestDelay)  {
    int numNewMessages = bot.getUpdates(bot.last_message_received   1);
    while (numNewMessages) {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received   1);
    }
    lastTimeBotRan = millis();
  }
  else {
    digitalWrite(led, LOW);
    if (PIRstate == HIGH) {
      Serial.println("Motion ended!");
      PIRstate = LOW;
    }
  }
}

Repository link:

https://github.com/c010rblind3ngineer/ESP32CAM-PIRTelegram

Mfr Part # U109
UNIT CAM WI-FI CAMERA (OV2640)
M5Stack Technology Co., Ltd.
More Info
View More Details
Mfr Part # U109-X
UNIT CAM WI-FI CAMERA DIY KIT
M5Stack Technology Co., Ltd.
16,37 €
View More Details
Mfr Part # A000066
ARDUINO UNO R3 ATMEGA328P BOARD
Arduino
23,84 €
View More Details
Mfr Part # 189
PIR (MOTION) SENSOR
Adafruit Industries LLC
8,59 €
View More Details
Mfr Part # XCVG12D
LED GREEN DIFFUSED T-1 3/4 T/H
SunLED
0,23 €
View More Details
Mfr Part # CFR-12JB-52-220R
RES 220 OHM 5% 1/6W AXIAL
YAGEO
0,09 €
View More Details
Mfr Part # BB-32621
BREADBOARD TERM STRIP 3.20X2.08"
Bud Industries
4,26 €
View More Details
Mfr Part # 12795
JUMPER WIRE M/M 6" 20COND
SparkFun Electronics
2,55 €
View More Details
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.