Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
![]() |
| × | 2 | |||
| × | 1 | ||||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
| ||||||
![]() |
| |||||
| ||||||
![]() |
| |||||
Hand tools and fabrication machines | ||||||
![]() |
| |||||
![]() |
| |||||
![]() |
| |||||
![]() |
| |||||
![]() |
| |||||
| ||||||
![]() |
|
Our team made this project during a whole school semester. The purpose of this project was to create an automatic irrigation system to reduce the waste of water used for agriculture.
We worked with students in the agriculture field to build this project.
How does it works?The idea is to measure the humidity in both the air and the ground. When the humidity is below a certain level, our system will open the Solenoid valve to water the ground droplet by droplet, to not waste any water, and to close the Solenoid valve once the humidity level is acceptable. The humidity, as well as the luminosity and temperature, are sent to the Aggriflow website for us to observe it in real time.
At the same time, the ESP32CAM will take photos at regular interval of the crops and send it to a online directory shared with the agriculture student to help them observe the growth of their crops.
How our project looksResultson the Aggriflow website
#include <MKRWAN.h>
#include "ArduinoLowPower.h"
#include "Air_Hum_temp.hpp"
#include "Hum_sol.hpp"
#include "Luminosite.hpp"
#include "Temp_sol.hpp"
#include "Electrovanne.hpp"
#include "Batterie.hpp"
#include "Allumer_ESP.hpp"
#include "Conversion.hpp"
//int Done = 11;
#define enableCapteur 12
#define SHDN 8
#define Sleep 2
#define enableESP 10
//Duree
int frequenceCapteur = 600000; // 10 minutes en ms
int frequenceEsp = 43200000; //12 heures en ms
int dureeOuvertureElectrovanne = 5; //5 secondes
unsigned long currentMillis = 43200000; //Pour prendre une photo au dmarage du systme
unsigned long previousMillis = 0;
LoRaModem modem;
//Find this on your TTN account
String appEui = "";
String appKey = "";
bool connected;
int err_count;
short con;
void setup() {
//Serial.begin(115200);
setup_electrovanne();
setup_dht();
setup_lum();
//pinMode(Done,OUTPUT);
//pinMode(enableCapteur,OUTPUT);
pinMode(SHDN,OUTPUT);
pinMode(Sleep,OUTPUT);
pinMode(enableESP,OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
//while (!Serrial);
modem.begin(EU868);
delay(1000);
connected=false;
err_count=0;
con =0;
}
void loop() {
//Dmarrage systme
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(enableCapteur,HIGH); //Alimentation des capteurs active
//digitalWrite(Delay,HIGH);
delay(1000);
digitalWrite(SHDN,LOW); //Alimentation pont en H dsactive
digitalWrite(Sleep,LOW); //Pont en H en mode sleep
digitalWrite(enableESP,LOW); //ESP non aliment
delay(1000);
//Rcupration donne capteur
short hum_air_short = (short)(humidity_dht());
short temp_air_short = (short)(temp_dht());
short temp_sol_short = (short)(temp_sol());
delay(500);
temp_sol_short = (short)(temp_sol());
short hum_sol_short = (short) (hum_sol());
short lum_short = (short) (lum());
short battery_short = (short) (battery());
short electrovanne = (short) 0; //lectrovanne ferme
//Arrosage
if (hum_sol()/10 < 25){ //Arrosage si humidit infrieur 25%
digitalWrite(SHDN,HIGH); //Alimentation pont en H
digitalWrite(Sleep,HIGH); //Pont en H quitte le mode sleep
ouverture_fermeture(dureeOuvertureElectrovanne);
digitalWrite(SHDN,LOW); //Coupe alimentation pont en H
delay(500);
digitalWrite(Sleep,LOW); //Pont en H en mode sleep
electrovanne = (short) 1; // lectrovanne ouverte
}
//ESP
if (currentMillis - previousMillis >= frequenceEsp){ //Prend une photo chaque fois que l'intervalle coul est pass
currentMillis = millis();
previousMillis = currentMillis;
allumer_ESP();
}
//Envoi donnes
char msg[2] = {3,4};
short test = 27;
if ( !connected ) {
//Serial.print("Join test : ");
//Serial.println(++con);
int ret=modem.joinOTAA(appEui, appKey);
if ( ret ) {
connected=true;
modem.minPollInterval(60);
//Serial.println("Connected");
modem.dataRate(5); // switch to SF7
delay(100); // because ... more stable
err_count=0;
}
}
if ( connected ) {
int err=0;
modem.beginPacket();
modem.write(temp_air_short);
modem.write(hum_air_short);
modem.write(temp_sol_short);
modem.write(hum_sol_short);
modem.write(lum_short);
modem.write(battery_short);
modem.write(electrovanne);
err = modem.endPacket();
if ( err <= 0 ) {
//Serial.print("Error : ");
//Serial.println(err);
// Confirmation not received - jam or coverage fault
err_count++;
if ( err_count > 50 ) {
connected = false;
}
// wait for 2min for duty cycle with SF12 - 1.5s frame
for ( int i = 0 ; i < 120 ; i++ ) {
delay(1000);
}
} else {
err_count = 0;
// wait for 20s for duty cycle with SF7 - 55ms frame
delay(20000);
//Serial.println("Message envoy");
}
}
//Downlinks
char rcv[64];
int i = 0;
while (modem.available()){
rcv[i++] = (char) modem.read();
}
if ((int)rcv[0] == 1){
frequenceCapteur = minutesToMilliseconds((int)rcv[1]);
}
else if (rcv[0] == 2){
frequenceEsp = hoursToMilliseconds((int)rcv[1]);
}
else if (rcv[0] == 3){
dureeOuvertureElectrovanne = (int)rcv[1];
}
//Coupure alimentation capteur
digitalWrite(enableCapteur,LOW);
//Duree de fonctionnement du systeme
currentMillis = millis();
//Consommation
if (battery()/100 < 20){
digitalWrite(LED_BUILTIN, LOW);
LowPower.deepSleep(frequenceCapteur);
}
else{
digitalWrite(LED_BUILTIN, LOW);
LowPower.sleep(frequenceCapteur);
}
//digitalWrite(Delay,LOW);
//digitalWrite(enableCapteur,LOW);
//delay(60000);
}
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "Base64.h"
#include "esp_camera.h"
//========================================
//======================================== CAMERA_MODEL_AI_THINKER GPIO.
#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
//========================================
// LED Flash PIN (GPIO 4)
#define FLASH_LED_PIN 4
//======================================== Enter your WiFi ssid and password.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
//========================================
//======================================== Replace with your "Deployment ID" and Folder Name.
String myDeploymentID = "REPLACE_WITH_YOUR_DEPLOYMENT_ID";
String myMainFolderName = "ESP32-CAM";
//========================================
//======================================== Variables for Timer/Millis.
unsigned long previousMillis = 0;
const int Interval = 30000; //--> Capture and Send a photo every 30 seconds.
//========================================
// Variable to set capture photo with LED Flash.
// Set to "false", then the Flash LED will not light up when capturing a photo.
// Set to "true", then the Flash LED lights up when capturing a photo.
bool LED_Flash_ON = true;
// Initialize WiFiClientSecure.
WiFiClientSecure client;
//________________________________________________________________________________ Test_Con()
// This subroutine is to test the connection to "script.google.com".
void Test_Con() {
const char* host = "script.google.com";
while(1) {
Serial.println("-----------");
Serial.println("Connection Test...");
Serial.println("Connect to " + String(host));
client.setInsecure();
if (client.connect(host, 443)) {
Serial.println("Connection successful.");
Serial.println("-----------");
client.stop();
break;
} else {
Serial.println("Connected to " + String(host) + " failed.");
Serial.println("Wait a moment for reconnecting.");
Serial.println("-----------");
client.stop();
}
delay(1000);
}
}
//________________________________________________________________________________
//________________________________________________________________________________ SendCapturedPhotos()
// Subroutine for capturing and sending photos to Google Drive.
void SendCapturedPhotos() {
const char* host = "script.google.com";
Serial.println();
Serial.println("-----------");
Serial.println("Connect to " + String(host));
client.setInsecure();
//---------------------------------------- The Flash LED blinks once to indicate connection start.
digitalWrite(FLASH_LED_PIN, HIGH);
delay(100);
digitalWrite(FLASH_LED_PIN, LOW);
delay(100);
//----------------------------------------
//---------------------------------------- The process of connecting, capturing and sending photos to Google Drive.
if (client.connect(host, 443)) {
Serial.println("Connection successful.");
if (LED_Flash_ON == true) {
digitalWrite(FLASH_LED_PIN, HIGH);
delay(100);
}
//.............................. Taking a photo.
Serial.println();
Serial.println("Taking a photo...");
for (int i = 0; i <= 3; i++) {
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
Serial.println("Restarting the ESP32 CAM.");
delay(1000);
ESP.restart();
return;
}
esp_camera_fb_return(fb);
delay(200);
}
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
Serial.println("Restarting the ESP32 CAM.");
delay(1000);
ESP.restart();
return;
}
if (LED_Flash_ON == true) digitalWrite(FLASH_LED_PIN, LOW);
Serial.println("Taking a photo was successful.");
//..............................
//.............................. Sending image to Google Drive.
Serial.println();
Serial.println("Sending image to Google Drive.");
Serial.println("Size: " + String(fb->len) + "byte");
String url = "/macros/s/" + myDeploymentID + "/exec?folder=" + myMainFolderName;
client.println("POST " + url + " HTTP/1.1");
client.println("Host: " + String(host));
client.println("Transfer-Encoding: chunked");
client.println();
int fbLen = fb->len;
char *input = (char *)fb->buf;
int chunkSize = 3 * 1000; //--> must be multiple of 3.
int chunkBase64Size = base64_enc_len(chunkSize);
char output[chunkBase64Size + 1];
Serial.println();
int chunk = 0;
for (int i = 0; i < fbLen; i += chunkSize) {
int l = base64_encode(output, input, min(fbLen - i, chunkSize));
client.print(l, HEX);
client.print("\r\n");
client.print(output);
client.print("\r\n");
delay(100);
input += chunkSize;
Serial.print(".");
chunk++;
if (chunk % 50 == 0) {
Serial.println();
}
}
client.print("0\r\n");
client.print("\r\n");
esp_camera_fb_return(fb);
//..............................
//.............................. Waiting for response.
Serial.println("Waiting for response.");
long int StartTime = millis();
while (!client.available()) {
Serial.print(".");
delay(100);
if ((StartTime + 10 * 1000) < millis()) {
Serial.println();
Serial.println("No response.");
break;
}
}
Serial.println();
while (client.available()) {
Serial.print(char(client.read()));
}
//..............................
//.............................. Flash LED blinks once as an indicator of successfully sending photos to Google Drive.
digitalWrite(FLASH_LED_PIN, HIGH);
delay(500);
digitalWrite(FLASH_LED_PIN, LOW);
delay(500);
//..............................
}
else {
Serial.println("Connected to " + String(host) + " failed.");
//.............................. Flash LED blinks twice as a failed connection indicator.
digitalWrite(FLASH_LED_PIN, HIGH);
delay(500);
digitalWrite(FLASH_LED_PIN, LOW);
delay(500);
digitalWrite(FLASH_LED_PIN, HIGH);
delay(500);
digitalWrite(FLASH_LED_PIN, LOW);
delay(500);
//..............................
}
//----------------------------------------
Serial.println("-----------");
client.stop();
}
//________________________________________________________________________________
//________________________________________________________________________________ VOID SETUP()
void setup() {
// put your setup code here, to run once:
// Disable brownout detector.
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
Serial.println();
delay(1000);
pinMode(FLASH_LED_PIN, OUTPUT);
// Setting the ESP32 WiFi to station mode.
Serial.println();
Serial.println("Setting the ESP32 WiFi to station mode.");
WiFi.mode(WIFI_STA);
//---------------------------------------- The process of connecting ESP32 CAM with WiFi Hotspot / WiFi Router.
Serial.println();
Serial.print("Connecting to : ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// The process timeout of connecting ESP32 CAM with WiFi Hotspot / WiFi Router is 20 seconds.
// If within 20 seconds the ESP32 CAM has not been successfully connected to WiFi, the ESP32 CAM will restart.
// I made this condition because on my ESP32-CAM, there are times when it seems like it can't connect to WiFi, so it needs to be restarted to be able to connect to WiFi.
int connecting_process_timed_out = 20; //--> 20 = 20 seconds.
connecting_process_timed_out = connecting_process_timed_out * 2;
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
digitalWrite(FLASH_LED_PIN, HIGH);
delay(250);
digitalWrite(FLASH_LED_PIN, LOW);
delay(250);
if(connecting_process_timed_out > 0) connecting_process_timed_out--;
if(connecting_process_timed_out == 0) {
Serial.println();
Serial.print("Failed to connect to ");
Serial.println(ssid);
Serial.println("Restarting the ESP32 CAM.");
delay(1000);
ESP.restart();
}
}
digitalWrite(FLASH_LED_PIN, LOW);
Serial.println();
Serial.print("Successfully connected to ");
Serial.println(ssid);
//Serial.print("ESP32-CAM IP Address: ");
//Serial.println(WiFi.localIP());
//----------------------------------------
//---------------------------------------- Set the camera ESP32 CAM.
Serial.println();
Serial.println("Set the camera ESP32 CAM...");
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 = 5; //0-63 lower number means higher quality
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 2; //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);
Serial.println();
Serial.println("Restarting the ESP32 CAM.");
delay(1000);
ESP.restart();
}
sensor_t * s = esp_camera_sensor_get();
// Selectable camera resolution details :
// -UXGA = 1600 x 1200 pixels
// -SXGA = 1280 x 1024 pixels
// -XGA = 1024 x 768 pixels
// -SVGA = 800 x 600 pixels
// -VGA = 640 x 480 pixels
// -CIF = 352 x 288 pixels
// -QVGA = 320 x 240 pixels
// -HQVGA = 240 x 160 pixels
// -QQVGA = 160 x 120 pixels
s->set_framesize(s, FRAMESIZE_SXGA); //--> UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
Serial.println("Setting the camera successfully.");
Serial.println();
delay(1000);
Test_Con();
Serial.println();
Serial.println("ESP32-CAM captures and sends photos to the server every 60 seconds.");
Serial.println();
delay(2000);
}
//________________________________________________________________________________
//________________________________________________________________________________ VOID LOOP()
void loop() {
// put your main code here, to run repeatedly:
//---------------------------------------- Timer/Millis to capture and send photos to Google Drive every 20 seconds (see Interval variable).
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= Interval) {
previousMillis = currentMillis;
SendCapturedPhotos();
}
//----------------------------------------
}
//________________________________________________________________________________
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Comments