Open navdeepssidhu opened 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() {
}
This is not an issue but request, is it possible to add OTA and Telegram support (sending picture to Telegram). Thanks