Pendahuluan

Pada tutorial kali ini, kita akan membahas cara menghubungkan ESP32 CAM dengan Telegram Bot untuk mengirimkan gambar secara otomatis. Proyek ini memanfaatkan ESP32 CAM, sebuah mikrokontroller dengan modul kamera dan kemampuan Wi-Fi, serta Telegram Bot API untuk mengirimkan gambar. Proyek ini menggunakan metode penyimpanan gambar di SPIFFS (Serial Peripheral Interface Flash File System) dan pengiriman gambar menggunakan metode HTTP requests.

 

Komponen Yang Digunakan

Berikut adalah daftar komponen yang digunakan dalam proyek ini beserta link pembelian di Golite Store:

  1. ESP32 CAMBeli Disini
  2. USB To TTL FTDI  – Beli Disini
  3. Kabel Jumper (Female to Female)  – Beli Disini
  4. Kabel USB untuk FTDI Beli Disini

 

Skema Sistem

Penjelasan Skema Sistem

Pada skema sistem ini, ESP32 CAM terhubung dengan USB To TTL FTDI untuk keperluan upload program dan sebagai power supply menggunakan kabel USB. ESP32 CAM akan mengambil gambar menggunakan kamera dan menyimpannya di SPIFFS. Gambar tersebut kemudian dikirimkan ke Telegram Bot melalui koneksi internet Wi-Fi.

 

Persiapan BOT Telegram

Hal pertama setelah proses perakitan yang harus kita lakukan yaitu lanjut ke proses pembuatan bot telegram dan mendapatkan chat id dari akun telegram kita

Buka aplikasi telegram dan buat bot dengan cara cari “botfather” kemudian pilih BotFather yang sudah centang biru seperti gambar di bawah ini

Setelah itu kirim pesan /start

Kemudian ikuti langkah langkah di bawah ini , untuk nama bot dan user name bot dapat di sesuaikan. Selanjutkan simpan Token (HTTP API) untuk selanjutkan kita masukan kedalam program di ESP32 Cam nya

Setelah itu kita perlu mendapatkan Chat Id Telegram kita dengan cari akun bot “idbot”

kemudian kirim pesan ke bot tersebut dengan perintah “/getid”, dan kita harus simpan id tersebut untuk kita masukan pada program utama kita

 

Program Arduino/ESP32

Program lengkap dapat di download pada Github Idrus Project , Klik disini

Hal yang harus di perhatikan sebelum upload program di bawah ini :

  • Pastikan board ESP32 sudah terinstall pada Arduino IDE
  • Pilih jenis board AI THINKER ESP32-CAM
  • Pastikan Semua library sudah terinstal dengan baik sesuai dengan versi yang sudah tertulis pada program
  • Untuk mempermudah proses upload bisa menggunakan module Downloader untuk ESP32 Cam
  • Jika menggunakan USB To TTL / FTDI pastiakan board sudah masuk ke download mode dengan cara jumper IO0 ke GND dan klik tombol reset
#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>  //1.3.0
#include <ArduinoJson.h>           //6.15.2
#include "FS.h"
#include "SPIFFS.h"
#include <HTTPClient.h>

//ESP32 CAM AI Thinker Camera Pinout
#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 FLASH_LED_PIN 4

const char* ssid = "xxxxxxx";
const char* password = "xxxxxx";

String BOT_TOKEN = "xxxxxxx";
String CHAT_ID = "xxxxxxx";

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOT_TOKEN, clientTCP);

unsigned long botRequestsMillis;
bool sendPhoto, flashState = 0;

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  Serial.begin(115200);
  cameraConfig();
  wifiConfig();
  if (!SPIFFS.begin(true)) {
    Serial.println("SPIFFS Mount Failed");
    return;
  }
  pinMode(FLASH_LED_PIN, OUTPUT);
  digitalWrite(FLASH_LED_PIN, flashState);
}

void loop() {
  if (sendPhoto) {
    Serial.println("\nPreparing photo");
    String response = sendPhotoTelegramSpiff();
    response.trim();
    if (response == "NOK") {
      sendPhoto = 1;
    } else {
      sendPhoto = 0;
    }
  }

  if (millis() > botRequestsMillis + 1000UL) {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    while (numNewMessages) {
      Serial.println("\nGot Response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    botRequestsMillis = millis();
  }
}
void cameraConfig(){
  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.grab_mode = CAMERA_GRAB_LATEST;

  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 16;  //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;
  }
  
  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();
  }
}

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

// Remove All Files in SPIFF
void deleteAllFilesInSPIFFS() {
  File root = SPIFFS.open("/");
  File file = root.openNextFile();

  while (file) {
    Serial.print("Deleting file: ");
    Serial.println(file.name());
    SPIFFS.remove(file.name());
    file.close();
    file = root.openNextFile();
  }

  Serial.println("All files deleted in SPIFFS");
}
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 += "Berikut adalah perintah yang dapat digunakan : \n";
      welcome += "/photo : Mengambil foto baru\n";
      welcome += "/flash : Menyalakan dan mematikan lampu flash \n";
      bot.sendMessage(CHAT_ID, welcome, "");
    } else if (text == "/photo") {
      Serial.println("New photo request");
      sendPhoto = 1;
    } else if (text == "/flash") {
      Serial.println("Change flash LED state");
      flashState = !flashState;
      digitalWrite(FLASH_LED_PIN, flashState);
    }else if (text == "/remove"){
      deleteAllFilesInSPIFFS();
    }
  }
}
void captureAndSavePhoto() {
  // Remove Previous Picture
  camera_fb_t *fb = esp_camera_fb_get();
  esp_camera_fb_return(fb);

  // Get New Picture
  digitalWrite(FLASH_LED_PIN, 1);
  fb = esp_camera_fb_get();
  delay(150);
  digitalWrite(FLASH_LED_PIN, 0);

  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  // Save Picture To SPIFF
  File file = SPIFFS.open("/idrusproject.jpg", FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    esp_camera_fb_return(fb);
    return;
  }

  file.write(fb->buf, fb->len);
  file.close();
  esp_camera_fb_return(fb);

  Serial.println("Photo saved to SPIFFS");
}

String sendPhotoTelegramSpiff() {
  String serverPath = "https://api.telegram.org/bot" + String(BOT_TOKEN) + "/sendPhoto";
  captureAndSavePhoto();

  if (WiFi.status() == WL_CONNECTED) {
    WiFiClientSecure client;
    HTTPClient http;
    client.setInsecure();  // SSL Not Verified Yet

    // Start Server Connection
    http.begin(client, serverPath);

    // Open Picture From SPIFFS
    File file = SPIFFS.open("/idrusproject.jpg", "r");
    if (!file) {
      Serial.println("Failed to open file for reading");
      return "Failed to open file for reading";
    }

    // Cek ukuran file
    size_t fileSize = file.size();
    if (fileSize == 0) {
      Serial.println("File is empty");
      file.close();
      return "NOK";
    }

    // Siapkan body permintaan
    String boundary = "IdrusProject";
    String bodyHead = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\n" + String(CHAT_ID) + "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"photo.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String bodyTail = "\r\n--" + boundary + "--\r\n";

    int bodyLength = bodyHead.length() + bodyTail.length() + file.size();
    uint8_t *body = (uint8_t *)malloc(bodyLength);

    if (body == NULL) {
      Serial.println("Failed to allocate memory for body");
      file.close();
      http.end();
      return "Failed to allocate memory for body";
    }

    // Copy head to body
    memcpy(body, bodyHead.c_str(), bodyHead.length());

    // Copy file content to body
    file.readBytes((char *)body + bodyHead.length(), file.size());

    // Copy tail to body
    memcpy(body + bodyHead.length() + file.size(), bodyTail.c_str(), bodyTail.length());

    http.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

    int httpResponseCode = http.POST(body, bodyLength);
    Serial.print("HTTP Response code: ");
    if (httpResponseCode > 0) {
      String payload = http.getString();
      Serial.println(httpResponseCode);
      Serial.println("Response payload: " + payload);

      free(body);
      http.end();
      file.close();
      return payload;
    }else {
      Serial.println(httpResponseCode);
      return "NOK";
    }
  } else {
    Serial.println("WiFi Disconnected");
    return "WiFi Disconnected";
  }
}

 

Penjelasan Program

  1. Memasukan Library Program menggunakan library WiFi, WiFiClientSecure, UniversalTelegramBot, ArduinoJson, FS, SPIFFSdan HTTPClient untuk mengakses dan mengendalikan berbagai fungsi ESP32 CAM dan Telegram Bot.
  2. Variabel Global
    • ssid, password: Mengatur koneksi Wi-Fi.
    • BOT_TOKEN, CHAT_ID: Token dan ID chat untuk Telegram Bot.
  3. Setup Function
    • Inisialisasi Serial Monitor dan SPIFFS.
    • Mengatur konfigurasi LED flash dan kamera.
    • Menghubungkan ke Wi-Fi dan menginisialisasi koneksi Telegram.
  4. Loop Function
    • Mengatur waktu tunggu dan pembacaan pesan baru dari Telegram.
    • Menangani dan mengirim gambar ke Telegram jika diperlukan.

Pengujian

Selama pengujian, ESP32 CAM berhasil terhubung ke jaringan Wi-Fi dan Telegram Bot, serta berhasil mengirimkan gambar yang diambil ke chat Telegram yang dituju. Tampilan gambar dan status pengujian dapat dilihat pada gambar di atas.

Kesimpulan

Proyek ini berhasil menghubungkan ESP32 CAM dengan Telegram Bot untuk mengirimkan gambar. Dengan konfigurasi ini, Anda dapat memodifikasi dan memperluas proyek ini untuk aplikasi yang lebih kompleks, seperti sistem pemantauan dengan notifikasi berbasis gambar. Penggunaan SPIFFS memungkinkan penyimpanan gambar sementara sebelum dikirim, sehingga mengurangi beban pada memori utama.

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *






Hubungi Kami

Hubungi Kami

Kami menyediakan jasa proyek Arduino, Electrical, dan IoT (Internet of Things):
- Penyediaan komponen.
- Perancangan hardware dan software.
- Pemrograman.
- Hingga deploy server.


Cocok untuk hobi, edukasi (skripsi atau tugas akhir), dan industri.
Serahkan kepada kami, Anda tinggal terima hasil jadi!



Hubungi via WhatsApp



Ikuti Kami di TikTok (Inspirasi Project IoT)



Kunjungi YouTube Kami (Tutorial Project IoT)



Temukan Kami di Facebook



Beli Komponen Di GoLite Store