Support bei ESP32-CAM Projekt

Hallo zusammen,
ich habe mir mit einem ESP32-CAM Modul eine Briefkastenüberwachung gebaut, mit der ich in Telegram ein Foto meines Briefkastens machen kann.
Allerdings hat die Powerbank nie wirklich lange gehalten und deswegen muss jetzt etwas neues her. Ich habe mir (bitte nicht steinigen :smiley: ) mit GPT und ein paar Tutorials aus dem Netz folgenden Code zusammengebaut:

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

const char* ssid = "************";         // Replace with your Wi-Fi SSID
const char* password = "*********"; // Replace with your Wi-Fi password
String BOTtoken = "************"; // Replace with your Telegram Bot Token
String CHAT_ID = "***********";                                        // Replace with your Telegram Chat ID

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);

//LED PIN
#define FLASH_LED_PIN 4
bool flashState = HIGH;

void configInitCamera() {
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = 5;
  config.pin_d1 = 18;
  config.pin_d2 = 19;
  config.pin_d3 = 21;
  config.pin_d4 = 36;
  config.pin_d5 = 39;
  config.pin_d6 = 34;
  config.pin_d7 = 35;
  config.pin_xclk = 0;
  config.pin_pclk = 22;
  config.pin_vsync = 25;
  config.pin_href = 23;
  config.pin_sscb_sda = 26;
  config.pin_sscb_scl = 27;
  config.pin_pwdn = 32;
  config.pin_reset = -1;
  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 = 10;
    config.fb_count = 1;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    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);

    return;
  }
}

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

  if (clientTCP.connect(myDomain, 443)) {
    Serial.println("Connection successful");

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

    size_t imageLen = fb->len;
    size_t extraLen = head.length() + tail.length();
    size_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=RandomNerdTutorials");
    clientTCP.println();
    clientTCP.print(head);
  
    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n = 0; n < fbLen; 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()) {
      while (clientTCP.available()) {
        char c = clientTCP.read();
        if (c == '\n') {
          if (getAll.length() == 0) {
            state = true;
          } else {
            break;
          }
        }
        if (state) {
          getBody += c;
        }
      }
    }

    clientTCP.stop();
    return getBody;
  } else {
    Serial.println("Connection failed");
    return "";
  }
}

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  pinMode(FLASH_LED_PIN, OUTPUT);
  
  // Connect to Wi-Fi
  Serial.print("Connecting to Wi-Fi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected!");

  // Configure client with the root certificate
  clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT);

  // Initialize camera
  configInitCamera();
  
  // Turn on LED using flashState
  flashState = HIGH;
  digitalWrite(FLASH_LED_PIN, flashState);
  Serial.println("LED turned ON");
  
  // Wait 5 seconds
  delay(5000);
  
  // Take picture
  camera_fb_t *fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  
  Serial.println("Taking picture...");
  
  // Turn off LED using flashState
  flashState = LOW;
  digitalWrite(FLASH_LED_PIN, flashState);
  Serial.println("LED turned OFF");
  
  // Send the picture to Telegram
  Serial.println("Sending picture to Telegram...");
  String response = sendPhotoTelegram(fb);
  
  if (response.indexOf("ok") >= 0) {
    Serial.println("Picture sent successfully.");
  } else {
    Serial.println("Failed to send picture.");
  }

  // Deep sleep for 20 seconds
  Serial.println("Going to sleep for 20 seconds...");
  esp_deep_sleep(43200000); // Sleep for 20 seconds
}

void loop() {
  // Do nothing in loop
}

Soweit so funktionabel.
Allerdings bin ich auf folgende Probleme gestoßen:

  • Die 43200000 sind keine 12 Stunden... Er macht nach gefühlt 20-30 Sekunden nochmal ein Foto.
  • Die LED wird nicht abgeschaltet sondern offenbar nur auf LOW gestellt. Um Batterie zu sparen sollte sie aber eigentlich aus gehen. Kann man das irgendwie erreichen ?

Leider kann ich von der Arduino-Code-Sprache nicht sonderlich viel verstehen (Grundkenntnisse programmieren sind vorhanden) Bitte habt nachsicht :slight_smile: Danke für eure Hilfe

Naja, 43.200.000 in Millisekunden schon, die sleeptime wird aber in Mikrosekunden erwartet, d.h. gemessen sollte er alle 43,2 Sekunden ein Bild machen.

Verstehe ich nicht, beide Seite auf GND und trotzdem nicht aus?

cu

Ah okay. Dann muss ich das nochmal umrechnen :smiley: Danke. 1 Problem weniger.
Ich hab mal ein Video vom Verhalten des ESP gemacht :slight_smile: https://www.youtube.com/shorts/N_oT7M0KZDQ
Erst auf HIGH, dann OFF, kurze Zeit später kam das Bild bei Telegram und dann ging das licht wieder an... sehr merkwürdig

Keine Ahnung, welche CAM du verwendest, aber die, die ich kenne (ESP32-CAM Al_thinker) , braucht am GPIO4 HIGH zum Leuchten und LOW, damit diese aus ist.
Und das funktioniert prima.

Das ist das board das ich habe.
Bei dem anderen Code den ich habe funktioniert das auch. Es schaltet die Lampe ja auch aus aber wenn es in den deepsleep geht geht sie wieder an. Sehr merkwürdig

Da ich den ESP32 noch nicht im deep sleep betrieben habe, kann ich zu dem Problem leider nichts sagen. Und wenn dein "anderer Code" funktioniert, dann verwende den und erweitere ihn um fehlende Funktionen.

Das hab ich schon gemacht. Funktioniert auch soweit außer wenn das Gerät in den Deepsleep geht.. :thinking:

Nein, drei Nullen dran.

Mit den GPIO im deep sleep ist es anscheinend nicht so einfach, google mal.
Man sieht ja auch, das die LED wesentlich dunkler ist.

cu

Das stimmt natürlich. Aber dunkel heißt leider trotzdem das sie weiterhin Strom zieht (was ja möglichst vermieden werden soll)
Ich hab leider nicht das krasse Know How in Programmierung mit dem ESP... Irgendwelche Ideen wie ich die LED komplett abschalten kann im DeepSleep?

Kannst du denn am Steuertransistor der Led Spannung messen ?
Ich vermute, an der Basis liegt Spannung an, so das der Transistor etwas durchsteuert. Dann liegt es wohl am ESP32, der den Ausgang auf HIGH legt.
Warum, müsste man im Datenblatt finden.

Ja, googeln, das Problem ist nicht neu.
Z.B.:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html
When a GPIO is set to hold, its state is latched at that moment and will not change when the internal signal or the IO MUX/GPIO configuration is modified (including input enable, output enable, output value, function, and drive strength values). This function can be used to retain the state of GPIOs when the power domain of where GPIO/IOMUX belongs to becomes off. For example, chip or system is reset (e.g. watchdog time-out, deep-sleep events are triggered), or peripheral power-down in light-sleep.

cu

Eine Powebank schaltet nach ca 30 Sekunden ab, wenn nicht ein gewisser Mindeststrom ( ca 50mA) fließt. (EU-Vorgeben zur Energiesparen)

Also kann man keine Elektronik in Sleepmodus an einer regulären Powerband betreiben weil diese zur Energieersparnis abschalet.

Grüße Uwe

Hab ich heute auch gemerkt... Sehr blöd wenn man will das die Bank möglichst lange hält :confused:

Man kann die Powerbank in Intervallen über Transistor und Lastwiderstand belasten, damit sie nicht abschaltet. Die Intervalle und den Strom muss man wohl experimentell ermitteln und bei Sleep dann extern, z.B. über einen NE555 steuern.

Gruß Tommy

Dann nimmt man aber bessere statt der Powerbank eine Lipo Batterie und einen Ladeschaltung und betreibt alles mit der Batteriespannung.

Grüße Uwe

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.