Is there an ADC GPIO I can use on the ESP32-CAM to read and LDR?

My Arduino project essentially consists of an ESP32-CAM sending a photo to my Telegram group every 15min, then goes to sleep. When it wakes up, it evaluates the "brightess level" by reading the voltage from an LDR, if the brightness level is too low (night time), it goes back to sleep; otherwise it connects to the internet, takes a photo and sends it to me.

I am aware the ADC pins of the ESP32 are distributed between ADC1 and ADC2 and that ADC2 should not be used when Wifi driver is in use. I am left with ADC1 pins 32 to 39. My camera is made by Ai-Thinker and the Arduino IDE shows it uses 32, 34, 35, 36 and 39.

I am left with GPIO33, 37 and 38. Unfortunately 37 and 38 and GPIO33 is used by Led1.

Can I unsolder LED1+resistor and use the pin as analog input? If not, what are my alternatives?

(Im not a programmer, but I can hammer code together with the help o DuckDuckGo).

/*
	
    Send photo every X minutes, except during dark (analogRead LDR)
	
    Based on https://RandomNerdTutorials.com/telegram-esp32-cam-photo-arduino/
	
*/

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

// Initialize Telegram BOT
String BOTtoken = "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 = "CHAT_ID";

const char* ssid = "ssid";
const char* password = "password";

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

#define ldrPin 33


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();
	}
	
	// Drop down frame size for higher initial frame rate
	sensor_t * s = esp_camera_sensor_get();
	s->set_framesize(s, FRAMESIZE_CIF);  // 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 setup() {
	
	// Set LED Flash as output
	// pinMode(FLASH_LED_PIN, OUTPUT);
	// digitalWrite(FLASH_LED_PIN, flashState);
	
	WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
	// Init Serial Monitor
	Serial.begin(115200);
	
	// Read LDR voltage divider, GPIO33
	int sensorValue = 100 * analogRead(ldrPin) / 4095;
	Serial.print("sensorValue =");
	Serial.println(sensorValue);
	
	if (sensorValue >= 15) {
		// Config and init the camera
		configInitCamera();
		
		// 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());
		
		sendPhotoTelegram();
	}
	
	esp_sleep_enable_timer_wakeup(6e7); // 1 minute
	
	Serial.println("Going to sleep now");
	delay(1000);
	esp_deep_sleep_start();
	
}

void loop() {
	
}

1 Like

If the ESP32CAM is waking up, taking a picture, saving it to SD, sending it via WiFi and then going back to sleep then, immediatly at wakeup try using one of the pins on the ESP32CAM connector to measure the LDR. If the resistance of the LDR is high enough it should not interferere with the subsequent normal operation of the SD.

srnet:
If the ESP32CAM is waking up, taking a picture, saving it to SD, sending it via WiFi and then going back to sleep then, immediatly at wakeup try using one of the pins on the ESP32CAM connector to measure the LDR. If the resistance of the LDR is high enough it should not interferere with the subsequent normal operation of the SD.

My Arduino project essentially consists of an ESP32-CAM sending a photo to my Telegram group every 15min, then goes to sleep. When it wakes up, it evaluates the "brightess level" by reading the voltage from an LDR, if the brightness level is too low (night time), it goes back to sleep; otherwise it connects to the internet, takes a photo and sends it to me.

So use any of the pins that the SD card would normally use.

I will try to remove LED1 and use GPIO33, as I want to be able to use sdcard as the project grows.

Also, those pins belong to ADC2, which cannot be used with Wifi.

If you use the sd-card in "1 wire" mode this allows you to carry on using the onboard LED/flash (gpio4) and still leaves pins 12 and 13 free for general use (12 must not be high at boot though).
You may like to have a look at my sketch which shows this in use: GitHub - alanesq/esp32cam-demo: esp32cam module demo / shows how you can easily use the esp32cam including reading raw rgb data, streaming, displaying the image etc.(ArduinoIDE or PlatformIO)
BTW - If you are not using serial you can also use pins 1 and 3

Only those pins on portB on a ESP32 can be used for analog-in. PortA is the first 32 pins. Portb are the other pins.

PortB is input only, all this info can be found in the ESP32 API.

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