#include <WiFi.h> // Pour se connecter au réseau wifi
#include "esp_camera.h" // Pour capturer une image
#include <esp_http_client.h> // Pour envoyer la photo au serveur
#include "soc/sens_reg.h" // Pour la ruse ADC2
// Les valeurs du cycle d'arrosage
#define NB_CYCLE_WATERING 1
#define TIME_BTWN_WATERING 5000
#define WATERING_TIME 3000
// Le temps d'attente avant de lire de nouveau
// le capteur d'humidité (1h en millisecondes)
#define SLEEPING_TIME (3600*1000)
// Les valeurs seuils du capteur d'humidité
#define MAX_MOIST_VAL 2000
#define MIN_MOIST_VAL 3000
// Les pins de l'ESP-WROOM-32 pour la caméra OV2640 du modèle 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
camera_fb_t * fb = NULL; // Camera buffer
uint64_t reg_b; // valeur du registre pour analogread()
// Les broches gpio
int moist_pin = 14;
int relay_pin = 2;
int led_pin = 4;
// Les états des broches on l'on écrit
int relay_state = LOW;
int led_state = LOW;
// Le réseau wifi
const char* ssid = "le_reseau_local";
const char* password = "le_mot_de_passe_local";
// AnalogRead alternatif
int alt_analogRead(int pin) {
WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, reg_b);
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
return analogRead(pin);
}
// Fonction pour amorcer la caméra
void init_camera() {
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;
if (psramFound()) {
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Erreur lors de l'initialisation de la caméra : 0x%x", err);
return;
}
}
void send_a_picture() {
esp_http_client_config_t config = {
.url = "http://192.168.1.254/plantbot/reception_image.php"
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_post_field(client, (const char *)fb->buf, fb->len);
esp_http_client_set_method(client, HTTP_METHOD_POST);
esp_http_client_set_header(client, "Content-type", "image/jpg");
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
Serial.println("Image envoyée");
else
Serial.printf("erreur %d lors de l'envoi de l'image\r\n", err);
esp_http_client_cleanup(client);
esp_camera_fb_return(fb);
}
void take_a_picture() {
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Echec de la capture d'image :(");
return;
} else {
Serial.println("Image enregistrée avec succès :)");
}
}
void start_wifi() {
WiFi.begin(ssid, password);
delay(1);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("On attend la connection wifi...");
yield(); // Pour éviter que le watchdog ne fasse redémarrer la carte.
}
Serial.println("");
Serial.println("WiFi connecté");
Serial.println(WiFi.localIP());
wifi_status = true;
}
void end_wifi() {
WiFi.disconnect();
delay(1);
WiFi.mode(WIFI_OFF);
delay(1);
while(WiFi.status() == WL_CONNECTED) {
delay(500);
Serial.println("On attend la déconnection du wifi");
yield();
}
Serial.println("WiFi déconnecté");
}
// Allumer le flash
void lights_on() {
digitalWrite(led_pin, HIGH);
}
// Éteindre le flash
void lights_off() {
digitalWrite(led_pin, LOW);
}
// Arrosage
void watering() {
for(int i=0; i<NB_CYCLE_WATERING; ++i) {
Serial.print(" -> Cycle numero ");
Serial.println(i);
relay_state = HIGH;
digitalWrite(relay_pin, relay_state); // On arrose !
delay(WATERING_TIME);
relay_state = !relay_state;
digitalWrite(relay_pin, relay_state); // On éteint l'arrosage
delay(TIME_BTWN_WATERING); // On attend un peu que l'eau pénetre dans la terre
}
}
void setup() {
Serial.begin(115200);
pinMode(moist_pin, INPUT);
pinMode(relay_pin, OUTPUT);
pinMode(led_pin, OUTPUT);
digitalWrite(relay_pin, relay_state);
digitalWrite(led_pin, led_state);
init_camera();
lights_off();
reg_b = READ_PERI_REG(SENS_SAR_READ_CTRL2_REG);
delay(2000); // Pour s'assurer que tout est bien initialisé (capteurs, wifi, etc..)
}
void loop() {
int v_moist = alt_analogRead(moist_pin);
Serial.print("Taux d'humidité de la terre : ");
Serial.println(v_moist);
if(v_moist <= MAX_MOIST_VAL) { // tres mouillé
Serial.print("C'est mouillé ! on va faire dodo pendant ");
Serial.print(SLEEPING_TIME);
Serial.println(" milli-secondes");
delay(SLEEPING_TIME);
} else if(v_moist >= MIN_MOIST_VAL) { // tres sec
start_wifi();
lights_on();
take_a_picture();
lights_off();
send_a_picture();
end_wifi();
watering();
Serial.println("Arrosage terminé");
delay(2000);
}
}