ESP32-CAM not behaving accordingly to analogRead condition
Posted: Thu Jan 28, 2021 1:24 am
My project consists of an ESP32-CAM that is supposed to take a photo and send a message if it's bright enough,« then go to sleep for 15min and repeat.
It begins by taking an average of 10 reading from the ADC, then proceeds to connect to wifi and sends the data if the value is above a certain threshold, otherwise it goes back to sleep for 15min.
The problem I'm getting is that if I turn on the device in dark conditions, sometimes it doesn't boot. Also, if I turn it on in bright conditions and it boots properly, when I turn off the lights in the room for a while to test, it sometimes does not get back to sending data.
I don't know if it's due to the if/else condition or something else.
Here is the code: https://codeshare.io/aYg8ZQ
It begins by taking an average of 10 reading from the ADC, then proceeds to connect to wifi and sends the data if the value is above a certain threshold, otherwise it goes back to sleep for 15min.
The problem I'm getting is that if I turn on the device in dark conditions, sometimes it doesn't boot. Also, if I turn it on in bright conditions and it boots properly, when I turn off the lights in the room for a while to test, it sometimes does not get back to sending data.
I don't know if it's due to the if/else condition or something else.
Here is the code: https://codeshare.io/aYg8ZQ
Code: Select all
#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>
#include <ArduinoJson.h>
// Wifi credencials
const char* ssid = "";
const char* password = "";
// Telegram credencials
String BOTtoken = ""; // your Bot Token (Get from Botfather)
// 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 CHAT_ID = "";
// Get average rssi
float wifiStrength;
const int numberPoints = 7;
// Get average value from analog input GPIO33 using similar function to rssi
float LDRvalue;
WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);
#define FLASH_LED_PIN 4
bool flashState = LOW;
//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
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
// Init Serial Monitor
// Serial.begin(115200);
// Set LED Flash as output and keep it Low to avoid trouble
pinMode(FLASH_LED_PIN, OUTPUT);
digitalWrite(FLASH_LED_PIN, flashState);
configInitCamera();
// LDRvalue = getLDR(numberPoints);
// Simply get the average of 10 readings from the LDR voltage divider
int LDRvalue = 0;
for (int i = 0; i < 10; i++) {
LDRvalue = LDRvalue + analogRead(33);
}
LDRvalue = LDRvalue / 10;
LDRvalue = LDRvalue * 100 / 4095; // simple percentage
// If bright enough, connect to wifi, send photo and message with LDR and RSSI values
if (LDRvalue >= 15) {
connectToWIfi();
wifiStrength = getStrength(numberPoints);
sendPhotoTelegram();
// Send message to Telegram
String message = "LDR: " + String(LDRvalue) + " %" + "\n"; // bool sendMessage(String chat_id, String text, String parse_mode = "");
message += "rssi: " + String(wifiStrength) + " dBm" + "\n";
bot.sendMessage(CHAT_ID, message, "");
}
// Bright or not bright enough, go to sleep, wake up after 15min and go again
esp_sleep_enable_timer_wakeup(9e+8); //6e+7 1min in microseconds, 9e+8 15min in microseconds
Serial.println("Going to sleep now");
delay(1000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
void configInitCamera() {
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();
}
sensor_t * s = esp_camera_sensor_get();
// Adjusting exposure here did not work for me
// s->set_brightness(s, 0); // -2 to 2
// s->set_contrast(s, 0); // -2 to 2
// s->set_saturation(s, 0); // -2 to 2
s->set_special_effect(s, 2); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
// s->set_whitebal(s, 0); // 0 = disable , 1 = enable
// s->set_awb_gain(s, 0); // 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_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
// s->set_aec2(s, 1); // 0 = disable , 1 = enable
// s->set_ae_level(s, 0); // -2 to 2
// s->set_aec_value(s, 1200); // 0 to 1200
// s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
// s->set_agc_gain(s, 2); // 0 to 30
// s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
// s->set_bpc(s, 0); // 0 = disable , 1 = enable
// s->set_wpc(s, 0); // 0 = disable , 1 = enable
// s->set_raw_gma(s, 0); // 0 = disable , 1 = enable
// s->set_lenc(s, 0); // 0 = disable , 1 = enable
// s->set_hmirror(s, 0); // 0 = disable , 1 = enable
// s->set_vflip(s, 0); // 0 = disable , 1 = enable
// s->set_dcw(s, 1); // 0 = disable , 1 = enable
// s->set_colorbar(s, 0); // 0 = disable , 1 = enable
// adjust photos to 800x600
s->set_framesize(s, FRAMESIZE_SVGA); // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
}
String sendPhotoTelegram() {
const char* myDomain = "api.telegram.org";
String getAll = "";
String getBody = "";
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";
}
Serial.println("Connect to " + String(myDomain));
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";
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=RandomNerdTutorials");
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);
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 (c == '\n')
{
if (getAll.length() == 0) state = true;
getAll = "";
}
else if (c != '\r')
getAll += String(c);
if (state == true) getBody += 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;
}
void connectToWIfi() {
// Connect to Wi-Fi
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
}
// Take measurements of the Wi-Fi strength and return the average result.
int getStrength(int points) {
long rssi = 0;
long averageRSSI = 0;
for (int i = 0; i < points; i++) {
rssi += WiFi.RSSI();
delay(20);
}
averageRSSI = rssi / points;
return averageRSSI;
}
// Take measurements of analog input GPIO33 and return average result
int getLDR(int points) {
long ldrReadings = 0;
long averageLDR = 0;
for (int i = 0; i < points; i++) {
ldrReadings += analogRead(33);
delay(20);
}
averageLDR = ldrReadings / points;
averageLDR = averageLDR * 100 / 4095; // simple percentage
return averageLDR;
}