raduprv / esp32-cam_ov2640-timelapse

A timelapse program for esp32 cam with ov2640 sensor. The exposure is done manually based on the light level, and the image quality is far better than the default settings.
Apache License 2.0
38 stars 5 forks source link

OTA #7

Open navdeepssidhu opened 2 years ago

navdeepssidhu commented 2 years ago

This is not an issue but request, is it possible to add OTA and Telegram support (sending picture to Telegram). Thanks

FBMinis commented 2 years ago

I can't help with OTA but I put together this program based on Radu's work to send a photo to Telegram every X second, them deepsleep.

/*
   Compiled using: Windows 10; Arduino IDE 1.8.19; Arduino Core for ESP32 2.0.4; AsyncTelegram2 2.1.6
   Modified version of RADU-cam_ov2640-timelapse https://github.com/raduprv/esp32-cam_ov2640-timelapse
   Sends photo to Telegram bot after Power ON, deep sleeps during a user-defined period
*/
  /********************************************************************************************************************
 *  Board Settings:
 *  Board: "ESP32 Wrover Module"
 *  Upload Speed: "921600"
 *  Flash Frequency: "80MHz"
 *  Flash Mode: "QIO"
 *  Partition Scheme: "Hue APP (3MB No OTA/1MB SPIFFS)"
 *  Core Debug Level: "None"
 *  COM Port: Depends *On Your System*
 *********************************************************************************************************************/

#include <WiFi.h>
#include <AsyncTelegram2.h>
#include "esp_camera.h"
#include "soc/soc.h"           // Brownout error fix
#include "soc/rtc_cntl_reg.h"  // Brownout error fix

#include <WiFiClientSecure.h>
WiFiClientSecure client;

const char* ssid = "yourssid";  // SSID WiFi network
const char* pass = "ssidpassword";  // Password  WiFi network
const char* token = "yourbottoken";

// Check the userid with the help of bot @JsonDumpBot or @getidsbot (work also with groups)
// https://t.me/JsonDumpBot  or  https://t.me/getidsbot
int64_t userid = 000000000; // replace with you userid

#define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  30        /* Time ESP32 will go to sleep (in seconds) */

// Timezone definition to get properly time from NTP server
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"

AsyncTelegram2 myBot(client);

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

int light = 0;
int day_switch_value = 140;

int lampChannel = 7;           // a free PWM channel (some channels used by camera)
const int pwmfreq = 50000;     // 50K pwm frequency
const int pwmresolution = 9;   // duty cycle bit range
const int pwmMax = pow(2, pwmresolution) - 1;

// Lamp Control
void setLamp(int newVal) {
  if (newVal != -1) {
    // Apply a logarithmic function to the scale.
    int brightness = round((pow(2, (1 + (newVal * 0.02))) - 2) / 6 * pwmMax);
    ledcWrite(lampChannel, brightness);
    Serial.print("Lamp: ");
    Serial.print(newVal);
    Serial.print("%, pwm = ");
    Serial.println(brightness);
  }
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);       // disable brownout detector

  //  setCpuFrequencyMhz(240);

  pinMode(LAMP_PIN, OUTPUT);                       // set the lamp pin as output
  ledcSetup(lampChannel, pwmfreq, pwmresolution);  // configure LED PWM channel
  setLamp(0);                                      // set default value
  ledcAttachPin(LAMP_PIN, lampChannel);            // attach the GPIO pin to the channel

  Serial.begin(115200);
  delay(100);

  // Init the camera module (accordind the camera_config_t defined)
  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.frame_size = FRAMESIZE_UXGA;
  config.jpeg_quality = 10;
  config.fb_count = 2;

  //initialize camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK)
  {
    Serial.printf("Camera init failed with error 0x%x", err);
    //    return;
  }

  // delay(3000); solve over exposure?

  // Get a reference to the sensor
  sensor_t* s = esp_camera_sensor_get();

  // Dump camera module, warn for unsupported modules.
  switch (s->id.PID) {
    case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
    case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
    case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
    case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
    default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
  }

  // Adjust sensor settings
  s->set_whitebal(s, 1);       // 0 = disable , 1 = enable
  s->set_awb_gain(s, 1);       // 0 = disable , 1 = enable
  s->set_wb_mode(s, 2);        // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
  //    s->set_hmirror(s, 0);        // 0 = disable , 1 = enable
  //    s->set_vflip(s, 0);          // 0 = disable , 1 = enable

  s->set_reg(s, 0xff, 0xff, 0x01); //banksel

  light = s->get_reg(s, 0x2f, 0xff);
  Serial.print("First light is ");
  Serial.println(light);
  Serial.print("Old 0x0 value is");
  Serial.println(s->get_reg(s, 0x0, 0xff));

  if (light < day_switch_value) {

    //here we are in night mode
    if (light < 45)s->set_reg(s, 0x11, 0xff, 1); //frame rate (1 means longer exposure)
    s->set_reg(s, 0x13, 0xff, 0); //manual everything
    s->set_reg(s, 0x0c, 0x6, 0x8); //manual banding

    s->set_reg(s, 0x45, 0x3f, 0x3f); //really long exposure (but it doesn't really work)

  } else {

    //here we are in daylight mode
    s->set_reg(s, 0x2d, 0xff, 0x0); //extra lines
    s->set_reg(s, 0x2e, 0xff, 0x0); //extra lines

    s->set_reg(s, 0x47, 0xff, 0x0); //Frame Length Adjustment MSBs

    if (light < 150) {
      s->set_reg(s, 0x46, 0xff, 0xd0); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0xff); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0xff); //exposure (doesn't seem to work)
    } else if (light < 160) {
      s->set_reg(s, 0x46, 0xff, 0xc0); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0xb0); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 170) {
      s->set_reg(s, 0x46, 0xff, 0xb0); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x80); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 180) {
      s->set_reg(s, 0x46, 0xff, 0xa8); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x80); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 190) {
      s->set_reg(s, 0x46, 0xff, 0xa6); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x80); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x90); //exposure (doesn't seem to work)
    } else if (light < 200) {
      s->set_reg(s, 0x46, 0xff, 0xa4); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x80); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 210) {
      s->set_reg(s, 0x46, 0xff, 0x98); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x60); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 220) {
      s->set_reg(s, 0x46, 0xff, 0x80); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x20); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 230) {
      s->set_reg(s, 0x46, 0xff, 0x70); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x20); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 240) {
      s->set_reg(s, 0x46, 0xff, 0x60); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x20); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0x80); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else if (light < 253) {
      s->set_reg(s, 0x46, 0xff, 0x10); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x0); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0x40); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x10); //exposure (doesn't seem to work)
    } else {
      s->set_reg(s, 0x46, 0xff, 0x0); //Frame Length Adjustment LSBs
      s->set_reg(s, 0x2a, 0xff, 0x0); //line adjust MSB
      s->set_reg(s, 0x2b, 0xff, 0x0); //line adjust
      s->set_reg(s, 0x45, 0xff, 0x0); //exposure (doesn't seem to work)
      s->set_reg(s, 0x10, 0xff, 0x0); //exposure (doesn't seem to work)
    }

    s->set_reg(s, 0x0f, 0xff, 0x4b); //no idea
    s->set_reg(s, 0x03, 0xff, 0xcf); //no idea
    s->set_reg(s, 0x3d, 0xff, 0x34); //changes the exposure somehow, has to do with frame rate

    s->set_reg(s, 0x11, 0xff, 0x0); //frame rate
    s->set_reg(s, 0x43, 0xff, 0x11); //11 is the default value
  }

  // Get first frame
  Serial.print("Getting first frame at "); Serial.println(millis());
  camera_fb_t* fb = esp_camera_fb_get();

  if (light == 0) {
    s->set_reg(s, 0x47, 0xff, 0x40); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xf0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 1) {
    s->set_reg(s, 0x47, 0xff, 0x40); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xd0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 2) {
    s->set_reg(s, 0x47, 0xff, 0x40); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xb0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 3) {
    s->set_reg(s, 0x47, 0xff, 0x40); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x70); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 4) {
    s->set_reg(s, 0x47, 0xff, 0x40); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x40); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 5) {
    s->set_reg(s, 0x47, 0xff, 0x20); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x80); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 6) {
    s->set_reg(s, 0x47, 0xff, 0x20); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x40); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 7) {
    s->set_reg(s, 0x47, 0xff, 0x20); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x30); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 8) {
    s->set_reg(s, 0x47, 0xff, 0x20); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x20); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 9) {
    s->set_reg(s, 0x47, 0xff, 0x20); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x10); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light == 10) {
    s->set_reg(s, 0x47, 0xff, 0x10); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x70); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 12) {
    s->set_reg(s, 0x47, 0xff, 0x10); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x60); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 14) {
    s->set_reg(s, 0x47, 0xff, 0x10); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x40); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 18) {
    s->set_reg(s, 0x47, 0xff, 0x08); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xb0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 20) {
    s->set_reg(s, 0x47, 0xff, 0x08); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x80); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 23) {
    s->set_reg(s, 0x47, 0xff, 0x08); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x60); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 27) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xd0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 31) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x80); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 35) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x60); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light <= 40) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x70); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light < 45) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x40); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  }
  //after this the frame rate is higher, so we need to compensate
  else if (light < 50) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0xa0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light < 55) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x70); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light < 65) {
    s->set_reg(s, 0x47, 0xff, 0x04); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x30); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light < 75) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x80); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xff); //line adjust
  } else if (light < 90) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x50); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0xbf); //line adjust
  } else if (light < 100) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x20); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0x8f); //line adjust
  } else if (light < 110) {
    s->set_reg(s, 0x47, 0xff, 0x02); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x10); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0x7f); //line adjust
  } else if (light < 120) {
    s->set_reg(s, 0x47, 0xff, 0x01); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x10); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0x5f); //line adjust
  } else if (light < 130) {
    s->set_reg(s, 0x47, 0xff, 0x00); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0x2f); //line adjust
  } else if (light < 140) {
    s->set_reg(s, 0x47, 0xff, 0x00); //Frame Length Adjustment MSBs
    s->set_reg(s, 0x2a, 0xf0, 0x0); //line adjust MSB
    s->set_reg(s, 0x2b, 0xff, 0x0); //line adjust
  }

  if (light < day_switch_value)s->set_reg(s, 0x43, 0xff, 0x40); //magic value to give us the frame faster (bit 6 must be 1)

  s->set_reg(s, 0xff, 0xff, 0x00); //banksel
  s->set_reg(s, 0xd3, 0xff, 0x8); //clock

  s->set_reg(s, 0x42, 0xff, 0x2f); //image quality (lower is bad)
  s->set_reg(s, 0x44, 0xff, 3); //quality

  //s->set_reg(s,0x96,0xff,0x10);//bit 4, disable saturation

  //s->set_reg(s,0xbc,0xff,0xff);//red channel adjustment, 0-0xff (the higher the brighter)
  //s->set_reg(s,0xbd,0xff,0xff);//green channel adjustment, 0-0xff (the higher the brighter)
  //s->set_reg(s,0xbe,0xff,0xff);//blue channel adjustment, 0-0xff (the higher the brighter)

  //s->set_reg(s,0xbf,0xff,128);//if the last bit is not set, the image is dim. All other bits don't seem to do anything but ocasionally crash the camera

  //s->set_reg(s,0xa5,0xff,0);//contrast 0 is none, 0xff is very high. Not really useful over 20 or so at most.

  //s->set_reg(s,0x8e,0xff,0x30);//bits 5 and 4, if set make the image darker, not very useful
  //s->set_reg(s,0x91,0xff,0x67);//really weird stuff in the last 4 bits, can also crash the camera

  //no sharpening
  s->set_reg(s, 0x92, 0xff, 0x1);
  s->set_reg(s, 0x93, 0xff, 0x0);

  if (fb)esp_camera_fb_return(fb);

  // Get second frame
  Serial.print("Getting second frame at "); Serial.println(millis());
  fb = esp_camera_fb_get();

  // Start WiFi connection
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());

  // Sync time with NTP
  configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
  client.setCACert(telegram_cert);

  // Set the Telegram bot properies
  myBot.setUpdateTime(1000);
  myBot.setTelegramToken(token);

  // Check if all things are ok
  Serial.print("\nTest Telegram connection... ");
  myBot.begin() ? Serial.println("OK") : Serial.println("NOK");

  //Take and send photo
  if (fb) {
    Serial.println("Camera capture requested");
    size_t len = fb->len;
    myBot.sendPhoto(userid, fb->buf, fb->len);
  } else {
    myBot.sendTo(userid, "Error, picture not sent.");
  }

  // Clear buffer
  esp_camera_fb_return(fb);

  //since we got the frame buffer, we reset the sensor and put it to sleep while saving the file
  s->set_reg(s, 0xff, 0xff, 0x01); //banksel
  s->set_reg(s, 0x12, 0xff, 0x80); //reset (we do this to clear the sensor registries, it seems to get more consistent images this way)
  delay(100);
  s->set_reg(s, 0x09, 0x10, 0x10); //stand by

  // Go to sleep
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
  Serial.print("Going to sleep now: "); Serial.println(millis());
  Serial.flush();
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {

}