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 :
#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 :
#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 :
const char* ssid = "****";
const char* password = "****";
Replace `****` with your Wi-Fi SSID and password.
3. Telegram Bot Configuration :
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 :
// 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:
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:
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:
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!