Richiesta di aiuto - Birdcam con ESP32-CAM e invio a Telegram

Ciao a tutti,

Premesso che non sono uno sviluppatore ma solo un appassionato, ho costruito una Birdcam con ESP32-Cam partendo dal progetto (e dal codice) su ESP32-CAM Shield PCB with Telegram: Photos, Outputs, Sensor, Motion | Random Nerd Tutorials

Ecco i link di alcune foto della realizzazione (Case 3D disegnato da me)

Ho modificato sia il progetto HQ che il codice, rimuovendo il sensore BME280 e aggiungendo alcune funzionalità sw/abilitando altri comandi (start/stop detection; flash quando si scatta foto; mostrare il Boot time ; comando di reboot) che non erano presenti nel progetto originale ma mi sono rimasti 2 problemi abbastanza bloccanti che non riesco a risolvere .. nonostante ci abbia provato per diverso tempo senza successo.. :frowning:

Per questo chiedo il vostro aiuto..

I 2 problemi che ho sono i seguenti:

  1. quando viene scattata una foto (sia con rilevamento automatico del movimento che con comando manuale "/photo" tramite Telegram) l'immagine inviata a Telegram NON è quella scattata in quel momento ma sembra essere quella scattata nel loop precedente o comunque in un momento diverso (antecedente allo scatto)
    Spero di essermi spiegato chiaramente..

  2. Il flash (che credevo di aver attivato prima del momento dello scatto e disattivato dopo 1000 msec) è invece attivato nel momento sbagliato... quindi le immagini sono completamente nere se le foto sono scattate al buio/di notte (ho bisogno del flash proprio perché vorrei usarlo anche di notte)..

Entrambi i problemi sembrano essere legati a loop/timing errati... ma non sono riuscito a identificare l'errore nel codice, che riporto qui sotto

C'è qualcuno che vuole aiutarmi?

Grazie in anticipo



/*
  by Stefano
*/

#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>
#include <Wire.h>
#include "SparkFunBME280.h"

// Replace with your network credentials
const char* ssid = "myssid";
const char* password = "mypassword";

// 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 chatId = "mychatid";

// Initialize Telegram BOT
String BOTtoken = "mytoken";

//aggiunti da Stefano
bool sendPhoto = false;
unsigned long bootTime = 0; // Variable to store the boot time

WiFiClientSecure clientTCP;

UniversalTelegramBot bot(BOTtoken, clientTCP);



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

#define FLASH_LED_PIN 4
bool flashState = LOW;

// Motion Sensor
bool motionDetected = false;

//aggiunti da Stefano
bool capturestop = false;
bool rebootloop = false;

int botRequestDelay = 1000;   // mean time between scan messages
long lastTimeBotRan;     // last time messages' scan has been done

void handleNewMessages(int numNewMessages);
String sendPhotoTelegram();

// Indicates when motion is detected
static void IRAM_ATTR detectsMovement(void * arg) {
//Serial.println("MOTION DETECTED!!!");
motionDetected = true;
}

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

  pinMode(FLASH_LED_PIN, OUTPUT);
  digitalWrite(FLASH_LED_PIN, flashState);

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

  // Save the boot time
  bootTime = millis();

  // Give some time for the PIR sensor to warm up
  Serial.println("Waiting 20 sec for the sensor to warm up on first boot");
  delay(20000); // 20 seconds
  
 // Blink LED 3 times to indicate PIR sensor warmed up
  digitalWrite(4, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  delay(100);
  digitalWrite(4, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  delay(100);
  digitalWrite(4, HIGH);
  delay(200);
  digitalWrite(4, LOW);
  Serial.println("PIR sensor is ACTIVE");


 
  // Send welcome message to Telegram
  // appare solo al boot
  String welcomeMessage = "Hello! I'm now online.";
  bot.sendMessage(chatId, welcomeMessage);


  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_XGA);  // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA

  // PIR Motion Sensor mode INPUT_PULLUP
  //err = gpio_install_isr_service(0);
  err = gpio_isr_handler_add(GPIO_NUM_13, &detectsMovement, (void *) 13);
  if (err != ESP_OK) {
    Serial.printf("handler add failed with error 0x%x \r\n", err);
  }
  err = gpio_set_intr_type(GPIO_NUM_13, GPIO_INTR_POSEDGE);
  if (err != ESP_OK) {
    Serial.printf("set intr type failed with error 0x%x \r\n", err);
  }
}


// Inizio LOOP

void loop() {

  if (sendPhoto) {
    Serial.println("Preparing photo");
    sendPhotoTelegram();
    sendPhoto = false;
  }

  if (capturestop) {
    if (motionDetected) {
      bot.sendMessage(chatId, "Motion detected!!", "");
      Serial.println("Motion Detected");
      // Accende il flash
      pinMode(4, OUTPUT);
      digitalWrite(4, HIGH);
      sendPhotoTelegram();
      motionDetected = false;
      // Spegni il flash dopo aver scattato la foto
      delay(1000);
      digitalWrite(4, LOW);     
      delay (20000);
    }
  }

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

// Function to handle the reboot command
    if (rebootloop) {
      handleRebootCommand();
      rebootloop = false;
   }

}

// Fine LOOP

// Function to handle the reboot command     
    void handleRebootCommand() {
// Perform a complete reboot of the ESP32
    delay (1000);
    ESP.restart();
    delay (1000);
   }
 

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

  // Accende il flash
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);

  // Scattare una foto
  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";
  }

  // Spegni il flash dopo aver scattato la foto
  delay(1000);
  digitalWrite(4, LOW);


  Serial.println("Connect to " + String(myDomain));

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

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

    //    Da capire a cosa serve?
    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;
}
// Fine Sendphoto to Telegram

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

  for (int i = 0; i < numNewMessages; i++) {
    // Chat id of the requester
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != chatId) {
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

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

    String fromName = bot.messages[i].from_name;

    if (text == "/flash") {
      flashState = !flashState;
      digitalWrite(FLASH_LED_PIN, flashState);
    }
    if (text == "/photo") {
      sendPhoto = true;
      Serial.println("New photo request");
    }
    
    if  (text == "/reboot") {
      bot.sendMessage(chatId, "OK, Rebooting ESP32 .... ");
      delay(500);
      rebootloop = true;
    }
    
    if  (text == "/stop") {
      capturestop = false;
      bot.sendMessage(chatId, "Capture stopped");
    }
    
    if  (text == "/start") {
      capturestop = true;
      bot.sendMessage(chatId, "Capture started");
    }

if (text == "/boot") {
      unsigned long uptime = millis() - bootTime;
      unsigned long seconds = uptime / 1000;
      unsigned long hours = seconds / 3600;
      unsigned long minutes = (seconds % 3600) / 60;
      seconds = seconds % 60;
      
      String uptimeStr = String(hours) + "h " + String(minutes) + "m " + String(seconds) + "s";
      String message = "ESP32-CAM è acceso da: " + uptimeStr;
      bot.sendMessage(chatId, message, "");
    }

    if (text == "/help") {
      String welcome = "Welcome to the ESP32-CAM BirdCam Telegram bot.\n";
      welcome += "/start: Start detection\n";
      welcome += "/stop: Stop detection\n";
      welcome += "/reboot : Reboot Birdcam\n";
      welcome += "/photo: Takes a new photo\n";
      welcome += "/flash: Toggle flash LED\n";
      welcome += "/boot: Boot time ESP32-CAM\n";
      welcome += "To start capture pls run the /start command\n";
      welcome += "You'll receive a photo whenever motion is detected.\n";
      bot.sendMessage(chatId, welcome, "Markdown");
    }
  }
}

Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Ok provvedo subito..
Grazie

Fatto

spero che ora ci sia qualcuno disposto ad aiutarmi...
ringrazio anticipatamente chiunque voglia farlo.

Con tutti quei delay cosi lunghi non mi stupisce che non funzioni come ti aspetti.

I bot Telegram funzionano secondo il principio del polling, in pratica il tuo ESP32 deve "interrogare" il server regolarmente per conoscere se ci sono nuovi messaggi oppure no.

 if (capturestop) {
    if (motionDetected) {
      bot.sendMessage(chatId, "Motion detected!!", "");
      Serial.println("Motion Detected");
      // Accende il flash
      pinMode(4, OUTPUT);
      digitalWrite(4, HIGH);
      sendPhotoTelegram();
      motionDetected = false;
      // Spegni il flash dopo aver scattato la foto
      delay(1000);
      digitalWrite(4, LOW);     
      delay (20000);
    }
  }

Quando il tuo sensore rileva del movimento, mandi prima un messaggio di testo e poi mandi l'immagine.
Non conosco nel dettaglio la libreria UniversalTelegramBot, ma ipotizzo che quando chiami l'istruzione sendPhotoTelegram() il bot non è "pronto" perché deve ancora completare la richiesta precedente. Dopodiché aspetti 20 secondi senza far nulla e quindi senza nemmeno aggiornare il bot.

Grazie mille per la risposta..

Per il problema 1 immagino sia quello il motivo.. hai suggerimenti su come ottimizzare il tutto?

Per il problema 2 pensi che il motivo della mancata accensione del flash/led al momento giusto (cioè poco prima dello scatto per poi spegnerlo dopo lo scatto) sia sempre quello del punto 1? Come posso risolvere?
(quando dici che mando un messaggio di testo prima dell'invio della foto a quale riga di codice ti riferisci?)?

Il delay di 20 secondi l'ho aggiunto io (pensando di averlo messo nel giusto punto del loop, ma evidentemente anche qui mi sbaglio, e accetto consigli su come modificarlo) per evitare di scattare una foto dopo l'altra nel caso il sensore di movimento rilevi di continuo dei movimenti (se l'oggetto rilevato rimane nel raggio del sensore per diverso tempo)

Grazie ancora

Come linea generale se un firmware deve essere reattivo, delay dell'ordine dei secondi sono da evitare a prescindere.

La mia è solo un'ipotesi, ma del resto ad una prima occhiata non vedo errori particolari.
Lo sketch è abbastanza simile agli esempi che ho incluso nella mia libreria ad eccezione della funzione per eseguire il POST che io ho incluso direttamente nei sorgenti della libreria stessa.

Modificare uno sketch che è stato pensato in modo sequenziale usando i delay() di solito ha come conseguenza quello di riscrivere tutto perché l'approccio è sostanzialmente diverso e si basa sull'uso della funzione millis() e sul concetto che la funzione loop() è l'unico loop bloccante che deve essere presente (scusa il gioco di parole).

In questo caso se vuoi limitarti solo al blocco dove hai inserito il delay(20000) potresti fare cosi:

 if (capturestop) {
    static unsigned long captureTime = 0;

    if (motionDetected && millis() - captureTime  > 20000) {
      // Questa blocco verrà eseguito solo se dall'ultimo scatto sono passati almeno 20 secondi
      // (purtroppo vale anche al boot, per evitare potresti inizializzare captureTime con un valore di -20000 usando però il tipo dati long)

      // Salvo il tempo in cui è stato eseguito l'ultimo scatto
      captureTime  = millis();    
      bot.sendMessage(chatId, "Motion detected!!", "");
      Serial.println("Motion Detected");
      // Accende il flash
      pinMode(4, OUTPUT);
      digitalWrite(4, HIGH);
      sendPhotoTelegram();
      motionDetected = false;
      // Spegni il flash dopo aver scattato la foto
      delay(1000);    // <------- secondo me non serve tenere il led acceso tutto questo tempo
      digitalWrite(4, LOW);     
    }
  }

Grazie ancora!

Proverò come suggerisci..

Attendere 20 secondi anche al boot non è un problema (tra l'altro c'è gia un delay al boot cosi come l'accensione sequenziale del flash che visivamente fa vedere che il sistema e' avviato)

Ti faro sapere

Ciao

Se ha tempo e voglia, prova anche l'esempio di cui ti ho messo il link.
Su quella libreria posso sicuramente essere di maggior aiuto visto che la conosco fin nei minimi dettagli :laughing:

Ci proverò sicuramente..
Grazie mille
Buona domenica

Dunque.. preso dalla curiosità ho provato subito il tuo codice (examples/ESP32/ESP32-CAM-PIR) e ho già alcune richieste .. :wink:

Nonostante abbia inserito un delay di 20 secondi qui
#define PIR_PIN GPIO_NUM_13
#define NUM_PHOTO 3 // Total number of photos to send on motion detection
#define DELAY_PHOTO 20000

Appena partito mi sono arrivate una sfilza di foto una dietro l'altra.. senza alcun delay di 20 secondi..
Come mai?

Riguardo il flash.. noto che si accende in modo davvero quasi impercettibile.. e non illumina un bel niente.. ma non sono riuscito a capire quali parametri modificare per "allungare" il tempo di accensione del flash (mi sembra anche che tu lo accendi non sempre alla massima intensità.. vedo una formula.. ma non ho capito qual'è la logica)

Altre modifiche (ma la vedo difficile che da solo riesca a farle) che mi piacerebbe fare sono le seguenti:

  1. aggiungere un output di help (msg a Telegram) con lista di comandi al boot
  2. aggiungere comando /help per forzare output di help (quello del punto 1 al boot ma su comando)
  3. aggiungere comando /start e /stop detection per appunto far partire o fermare il funzionamento del PIR (come avevo nell'altro programma)
    Al boot dovrebbe essere in modalità stop.. e solo dopo lo start parte il detection
  4. aggiungere comando /reboot per far fare restart all'ESP32 (come avevo nell'altro programma)
  5. aggiungere comando /boot per mostrare il tempo di boot (come avevo nell'altro programma)

Per ora è tutto (non vorrei approfittare troppo della tua gentilezza) :wink:

Grazie mille

Ciao

Figurati nessun problema.

Mi sono dimenticato di evidenziare che siccome l'ho provato con un pulsante e non con un PIR vero, l'ingresso è iniziliazzato a PULLUP, cosa che non va bene con un PIR che invece a riposo è LOW e quindi l'ingesso sarebbe sempre attivo causando il malfunzionamento che riscontri.

Devi modificare mettendo:

   // PIR Motion Sensor setup
  pinMode(PIR_PIN, INPUT);

e devi modificar anche qui mettendo HIGH (in effetti pensandoci meglio è bene che io aggiorni l'esempio in tal senso visto che faccio riferimento al PIR).

if(digitalRead(PIR_PIN) == LOW) {

Lo sketh inoltre è stato pensato non per scattare una sola fotografia, ma una sequenza di scatti a breve distanza. Se vuoi un solo scatto ogni 20 secondi, dovrai impostare le opzioni in questo modo:

#define NUM_PHOTO     1               // Total number of photos to send on motion detection
#define DELAY_PHOTO   20000           // Waiting time between one photo and the next 

Per quanto riguarda il flash, viene impostato ad un valore compreso tra 0 e 100 nella funzione setLamp(); la formula serve solo per linearizzare la risposta dell'intensità luminosa usando un andamento logaritmico.
Con Il piccolo led onboard è inutile, ma se usi un'illuminatore esterno potrebbe servire. Ad ogni modo puoi semplicemente usare in alternativa un classico digitalWrite() aggiungendo un breve delay() per allungare il tempo in cui rimane acceso.

Lo sketch in questione ha inoltre la peculiarità di usare un task FreeRTOS per quanto riguarda la gestione del bot Telegram. Questo proprio perché io sono un po' fissato con la reattività di un software e se il micro è impegnato ad inviare una fotografia appena scattata non sarà in grado di fare nient'altro per almeno un paio di secondi. Con un task che gira in parallelo posso superare questo ostacolo.

Se vuoi aggiungere le funzionalità di cui accenni è li che devi intervenire. Ad esempio per un semplice restart:

    else if (msg.text.equalsIgnoreCase("/reboot")) {
      myBot.sendMessage(msg, "Restarting in few seconds...");
      // per evitare un bootloop dovuto al messaggio "in sospeso" 
      // è necessario aspettare che il server Telegram sia sincronizzato con il bot
      while (!myBot.noNewMessage()) {
        Serial.print(".");
        delay(50);
      }
      ESP.restart();
    }

Il resto è più semplice: per lo start/stop ti basta aggiungere una variabile bool inizializzata a false e che metti true quando ricevi il comando come hai già fatto. La variabile poi la metti in AND con il segnale del PIR.

.....
captureStart = true;
.....

if(digitalRead(PIR_PIN) == HIGH && captureStart) {   

Stessa cosa per le altre funzionalità, basta fare un po' di copia incolla ed adattare dove serve.

Comunque se riesco più tardi lo ri-provo perché è da un po' che l'ho sviluppato e magari nel frattempo c'è stato qualche aggiornamento nel core ESP32 che potrebbe richiedere qualche piccola modifica.

Sei fantastico!

Seguirò le tue indicazioni per correggere i problemi che ho riscontrato...

Confermo che il tuo approccio all'invio su Telegram è super efficiente (molto meglio di quello dell'altro codice che stavo provando)..

Per le nuove feature proverò a realizzarle da solo.. ma ... non essendo un programmatore (sono totalmente autodidatta) non sono sicuro di riuscirci..
Ci proverò e riproverò.. ma ti anticipo che in caso di problemi tornerò a chiedere il tuo aiuto :wink:

Grazie ancora per la grande disponibilità (e competenza) che hai

A presto

Ciao

1 Like

riguardo questa parte... immagino che questa parte di codice

 // Take Picture with Camera and store in ram buffer fb
  setLamp(100);
  camera_fb_t* fb = esp_camera_fb_get();
  setLamp(0);
  if (!fb) {
    Serial.println("Camera capture failed");
    return 0;

dovrebbe diventare cosi?

dopo void setup aggiungo

  pinMode(FLASH_LED_PIN, OUTPUT);
  digitalWrite(FLASH_LED_PIN, flashState);

e questo diventa

 // Take Picture with Camera and store in ram buffer fb
       // Accende il flash
      pinMode(4, OUTPUT);
      digitalWrite(4, HIGH);
  camera_fb_t* fb = esp_camera_fb_get();
      // Spegni il flash dopo aver scattato la foto
      delay(1000);
      digitalWrite(4, LOW);     
  if (!fb) {
    Serial.println("Camera capture failed");
    return 0;

giusto? O sto sbagliando qualcosa?
:wink:

e serve anche
#define FLASH_LED_PIN 4
giusto?

Questo va fatto solo nel setup, è inutile farlo ogni volta. Il #define FLASH_LED_PIN 4 è un modo per evitare di riscrivere 4 ogni volta.

In pratica ogni volta che vedi un #define XXXX YYYY devi immaginare che il compilatore andrà brutalmente a sostituire ogni occorrenza di XXXX con YYYY.

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