24. Telegram-Enabled ESP32-CAM Photobot with Arduino

Introduction :

    In the world of DIY electronics, combining the power of microcontrollers and internet connectivity opens up exciting possibilities. In this blog post, we'll explore the creation of a Telegram-enabled ESP32-CAM photobot using the Arduino IDE. This project allows you to remotely command your ESP32-CAM to capture photos and send them directly to your Telegram chat. Let's dive into the details of the code and how to set up this intriguing project.

Requirements :

    Before we begin, make sure you have the following:

        1. ESP32-CAM module.

        2. Arduino IDE with ESP32 core installed.

        3. Wi-Fi network credentials.

        4. Telegram Bot token obtained from Botfather.

        5. Telegram chat ID for the destination.

Libraries and Code Setup :

    The project relies on various libraries, including the ESP32 core, WiFi, camera, Telegram Bot, and JSON parsing. Ensure these are installed in your Arduino IDE. The code initializes the necessary components, sets up Wi-Fi, configures the camera, and connects to the Telegram Bot API.

Wi-Fi and Telegram Configuration :

    Replace placeholders like `ssid`, `password`, `BOTtoken`, and `CHAT_ID` with your actual Wi-Fi credentials and Telegram Bot details. These are crucial for connecting the ESP32-CAM to your network and enabling Telegram communication.

Camera Configuration :

    The ESP32-CAM features a built-in camera, and its configuration involves assigning GPIO pins and settings such as frame size, quality, and pixel format. These parameters can be adjusted based on your preferences and project requirements.

Telegram Bot Functions :

    The code includes functions for handling incoming messages. Commands like `/start`, `/flash`, and `/photo` trigger specific actions. For example, the `/flash` command toggles the flash LED, while `/photo` instructs the bot to capture and send a new photo.

Camera Functions :

    Functions like `configInitCamera` initialize and configure the ESP32-CAM's camera module. The `sendPhotoTelegram` function captures a photo and sends it to the specified Telegram chat using the Telegram Bot API.

Setting Up and Running the Project :

    1. Connect the ESP32-CAM to your computer.

    2. Open the Arduino IDE, load the sketch, and ensure all libraries are installed.

    3. Replace placeholder values in the code with your Wi-Fi and Telegram credentials.

    4. Upload the code to your ESP32-CAM.

Usage :

    1. Power on the ESP32-CAM and wait for it to connect to the Wi-Fi network.

    2. Start a chat with your Telegram Bot and send commands like `/start`, `/flash`, or `/photo`.

   3. Receive responses from the ESP32-CAM, toggle the flash LED, or get new photos sent directly to your Telegram chat.

Code :

C++

#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 = "****";

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;

 

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

}

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 = "--electroniclinic\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--electroniclinic\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";

    String tail = "\r\n--electroniclinic--\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=electroniclinic");

    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);

  // 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() {

    if (sendPhoto) {

    Serial.println("Preparing photo");

    sendPhotoTelegram();

    sendPhoto = false;

  }

  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();

  }

}


Certainly! Let's break down the code step by step:

1. Library Inclusions :

C++

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

  

  These lines include necessary libraries for the ESP32-CAM, Wi-Fi, Telegram communication, and JSON parsing.

2. Wi-Fi Configuration :

C++

const char* ssid = "****";

const char* password = "****";

    Replace `****` with your Wi-Fi SSID and password.

3. Telegram Bot Configuration :

C++

 String BOTtoken = "************";

 String CHAT_ID = "*****";

   Replace `************` with your Telegram bot token obtained from Botfather and `*****` with the chat ID of the user or group you want the bot to interact with.

4. Camera Configuration :

C++

  // Camera pin configurations

   // ...


   // Configuration settings

   // ...


   void configInitCamera() {

       // Function to initialize and configure the camera

       // ...

   }

   The code sets up the pin configurations for the ESP32-CAM camera module and initializes the camera with specific settings using the `configInitCamera` function.

5. Telegram Bot Functions:

C++

void handleNewMessages(int numNewMessages) {

       // Function to handle new incoming messages and perform actions

       // ...

   }


   String sendPhotoTelegram() {

       // Function to capture a photo and send it to Telegram

       // ...

   }

   These functions handle new incoming messages and send photos to Telegram based on user commands.

6. Setup Function:

C++

void setup() {

       // Setup function initializes necessary components

       // ...

   }

   The `setup` function initializes the serial communication, sets up the flash LED pin, configures and initializes the camera, connects to Wi-Fi, and prints the ESP32-CAM's IP address.

7. Loop Function:

C++

void loop() {

       // Loop function checks for new messages and sends photos if requested

       // ...

   }

   The `loop` function periodically checks for new messages, handles them, and sends a photo if requested. The timing is controlled by the `botRequestDelay` variable. Ensure you replace placeholder values with your actual credentials, and understand that this code requires the ESP32 core and relevant libraries to be installed in the Arduino IDE.

Conclusion :

    Building a Telegram-enabled ESP32-CAM photobot is a fun and educational project that combines hardware, software, and internet communication. It showcases the versatility of the ESP32 platform and demonstrates how you can integrate IoT capabilities into everyday devices. Whether you're exploring the world of DIY electronics or looking for a creative way to interact with your gadgets remotely, this project offers a fantastic starting point. Customize and expand upon the code to add more features and functionality to your Telegram-connected ESP32-CAM photobot. Happy tinkering!

Post a Comment (0)
Previous Post Next Post