Tuto DiY - La box connectée - Système de monitoring à distance (Temp/Hum/Lumière/Sol/Co2) pour 12€


Messages recommandés

Hello la communauté! 

 

Je reviens vous donner des nouvelles de mes essais avec les relais. C'est hyper concluant, je suis carrément satisfait! L'installation est câblée et en test depuis un bon mois, la mise en route de mon brumisateur ainsi que la vitesse de mon extracteur sont sous le contrôle de l'ESP. Le système dépasse mes attentes, c'est génial! :yeah:

 

J'ai suivi tes conseils Raphiki, désormais l'ESP héberge la page web permettant de contrôler le système. L'accès au serveur web peut se faire depuis n'importe quelle connexion, il est sécurisé de façon sommaire par identification/mot de passe.
Pour la gestion des relais, il est possible d'agir manuellement, ou alors on peut enclencher un mode automatique qui ajustera l'état des relais en fonction des seuils de température et d’humidité définis dans le code.

 

Je me suis aperçu que l'ESP avait tendance a redémarrer assez souvent. Dans le code de base, le système redémarre si les datas ne sont pas reçues par thingspeak. En fait, c'est très souvent le cas, cela peut aussi être à cause de micro-coupures de connexion internet auxquelles Free m'a habitué...
Bref, ça me posait problème car je ne veux pas que l'ESP se mette à commuter mes relais de façon frénétique à cause de redémarrages intempestifs. ^^
J'ai modifié le code en ajoutant un compteur de fail que j'ai incrémenté jusqu'à ne plus avoir de redémarrages inutiles. Désormais le système ne redémarre qu'après dix messages consécutifs non reçus par thingspeak.
Le système démarre en mode manuel avec les relais OFF, de cette façon je n'ai pas de risque de faire jouer des claquettes à mon extra et brumisateur suite à des soucis de réseau.

 

D'autre part, j'ai ajouté dans le code une alerte envoyée directement à telegram à chaque démarrage du système. Pour cela j'ai utilisé cette librairie : 
https://github.com/Gianbacchio/ESP8266-TelegramBot
J'ai aussi mis en place un "No Data Check" dans les React thingspeak. Avec tout ça, le système est vraiment sous contrôle c'est au top!

 

En image :

Révélation

L'ESP et ses sondes dans le placo :

SmartGrowEngine.thumb.jpg.675b676370fc7be81fb0a20151708ca1.jpg

 

Le câblage des relais. Il y a aussi un relais timer pour l'alimentation du brumisateur. Cela me permet de le faire fonctionner par cycle de trois minutes ON, trois minutes OFF, réglage adapté par rapport à la taille de mon placo et à l'extraction.

https://www.velleman.eu/products/view/?id=341552

SmartGrowRelay.jpg.76f4178f59d69c5d1591ed705dc12063.jpg

 

Screenshot de l'interface web :

SmartGrowWebPage.thumb.png.f281161492450cb5aecbf65520a54e96.png

 

Voici le code sur lequel je me suis arrêté. J'ai essayé d'être au plus clair possible mais comme je n'y connais rien c'est pas facile! Il vous faudra remplacer les XXXXXXX par vos divers identifiants.
Un document qui m'a bien aidé :
http://www.esploradores.com/wp-content/uploads/2018/04/A-Beginners-Guide-to-the-ESP8266-1.pdf

 

Révélation

/*
 * ESP8266 NodeMCU SmartGrow
 */

#include "DHT22.h"
#include "YL100.h"
#include "MAX44009.h"
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <ESP8266TelegramBOT.h>

//---------------------------------------------------------------
//HTML webpage contents in program memory

const char MAIN_page[] PROGMEM = R"=====(

<!DOCTYPE html>
<html>

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Smart Grow Relay Control</title>
  </head>

  <body align="center" style="width: 540px; margin: 0 auto; padding: 20px;" bgcolor="#d9e7f2">

    <header style="border: 2px solid white; margin: -2px; background-color: #4685b9;">
      <h2 style="font-family: Helvetica;color: white;">Smart Grow Relay Control</h2>
    </header>

    <div style="border: 2px solid white; margin: -2px; padding-top: 2px; background-color: #8cb6d9;">
      <br>
      <span style="font-family: Helvetica;color: white;">Engine</span><br>
      <br>
      <a href="AutomaticModeOn" target="Iframe1"><input type=button style="width: 198px;" value="Automatic Mode On" onClick="this.parentNode.click()"></a> 
      <a href="AutomaticModeOff" target="Iframe1"><input type=button style="width: 198px;" value="Automatic Mode Off" onClick="this.parentNode.click()"></a><br>
      <iframe name="Iframe1" width="414" height="34" frameBorder="0"></iframe><br>
      <a href="SystemRestart" target="Iframe2"><input type=button style="width: 200px;" value="Restart Engine" onClick="this.parentNode.click()"></a><br>
      <iframe name="Iframe2" width="200" height="34" frameBorder="0"></iframe><br>
    </div>
  
    <div style="height: auto; border: 2px solid white; margin: -2px; background-color: #4685b9;">
      
      <br>
      <span style="font-family: Helvetica;color: white;">Température</span><br>
      <br>
      <iframe width="450" height="260" style="border: 1px solid #cccccc;" src="https://thingspeak.com/channels/580336/widgets/16629"></iframe><br>
      <br>
      <span style="font-family: Helvetica;color: white;">Humidité Relative</span><br>
      <br>
      <iframe width="450" height="260" style="border: 1px solid #cccccc;" src="https://thingspeak.com/channels/580336/widgets/16636"></iframe><br>
      <br>

    </div>

    <div style="height: auto; border: 2px solid white; margin: -2px; background-color: #8cb6d9;">
      
      <br>
      <span style="font-family: Helvetica;color: white;">Brumisateur</span><br>
      <br>
       <a href="Relay1On" target="Iframe3"><input type=button style="width: 198px;" value="Relay 1 On" onClick="this.parentNode.click()"></a>
       <a href="Relay1Off" target="Iframe3"><input type=button style="width: 198px;" value="Relay 1 Off" onClick="this.parentNode.click()"></a><br>
       <iframe name="Iframe3" width="414" height="34" frameBorder="0"></iframe><br>
      <br>
      <span style="font-family: Helvetica;color: white;">Vitesse Extracteur</span><br>
      <br>
       <a href="Relay2On" target="Iframe4"><input type=button style="width: 198px;" value="Relay 2 On" onClick="this.parentNode.click()"></a>
       <a href="Relay2Off" target="Iframe4"><input type=button style="width: 198px;" value="Relay 2 Off" onClick="this.parentNode.click()"></a><br>
       <iframe name="Iframe4" width="414" height="34" frameBorder="0"></iframe><br>
      <br>

    </div>
      
    <footer style="height: auto; border: 2px solid white; margin: -2px; background-color: #4685b9;">
      <h5><a href="https://thingspeak.com/channels/580336" target="_blank" style="font-family: Helvetica;color: white;">ThingSpeak.com</a></h5>
    </footer>
        
  </body>
  
</html>

)=====";

//---------------------------------------------------------------

// WIFI SETTINGS
#define WIFI_SSID "XXXXXXXXXXXXXXXX"
#define WIFI_KEY "XXXXXXXXXXXXXXXX"

// THINGSPEAK SETTINGS
#define THINGSPEAK_HOST "api.thingspeak.com"
#define THINGSPEAK_API_KEY "XXXXXXXXXXXXXXXX"

#define FIELD_TEMPERATURE 1
#define FIELD_HUMIDITY 2
#define FIELD_MOISTURE 3
#define FIELD_LIGHT 4
#define FIELD_RELAY1 5
#define FIELD_RELAY2 6

// TELEGRAM SETTINGS
#define BOT_TOKEN "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXX_XXXXXXXXXXX"
#define CHAT_ID "-XXXXXXXXX"
#define BOT_NAME "XXXXXXXXXXXXXXXX"
#define USERNAME "XXXXXXXXXXXXXXXX"

// PIN SETTINGS
#define PIN_SCL D1
#define PIN_SDA D2
#define PIN_DHT D3
#define PIN_YL100 A0

// PROGRAM SETTINGS
#define TIME_SLEEP 1000
#define CPT_PUBLISH 26

// VAR DECLARATION
HTTPClient http;
ESP8266WebServer server(80);
WiFiClientSecure client;
TelegramBOT bot(BOT_TOKEN, BOT_NAME, USERNAME);

DHT dht(PIN_DHT, DHT22);
YL100 yl(PIN_YL100);
Max44009 max44(0x4A, PIN_SDA, PIN_SCL);

uint16_t cptLoop = 0;
uint16_t FailLoop = 0;

float temperature = 0;
float humidity = 0;
float moisture = 0;
float light = 0;

uint16_t relay_1 = 0;
uint16_t relay_2 = 0;

uint16_t cptTemperature = 0;
uint16_t cptHumidity = 0;
uint16_t cptMoisture = 0;
uint16_t cptLight = 0;

uint16_t AutomaticMode = 0;

int i = 0;

//===============================================================
// This routine is executed when you open its IP in browser
//===============================================================

void handleRoot() {
 Serial.println("Web page requested.");
 server.send(200, "text/html", "<form action=\"/SmartGrow\" method=\"POST\"><p>Smart Grow Relay Control</p><input type=\"text\" name=\"username\" placeholder=\"Username\"></br><input type=\"password\" name=\"password\" placeholder=\"Password\"></br></br><input type=\"submit\" value=\"Login\"></form>");
}

void handleSmartGrow() { // If a POST request is made to URI /SmartGrow
  if ( ! server.hasArg("username") || ! server.hasArg("password") || server.arg("username") == NULL || server.arg("password") == NULL) { // If the POST request doesn't have username and password data
    Serial.println("Invalid request.");
    server.send(400, "text/plain", "400: Invalid Request"); // The request is invalid, so send HTTP status 400
    return;
  }
  if (server.arg("username") == "XXXXXXXXXXXXXXXX" && server.arg("password") == "XXXXXXXXXXXXXXXX") { // If both the username and the password are correct
    Serial.println("Login successful.");
    String s = MAIN_page; //Read HTML contents
    server.send(200, "text/html", s); //Send web page
  }
  else { // Username and password don't match
    Serial.println("Unauthorized user.");
    server.send(401, "text/plain", "401: Unauthorized");
  }
}

void handleRelay1On() { 
 Serial.println("Relay 1 On requested.");
 AutomaticMode = 0;
 relay_1 = 1;
 digitalWrite(D5, 1);
 server.send(200, "text/html", "<center>Relay 1 is ON.</center>"); //Send ADC value only to client ajax request
}

void handleRelay1Off() { 
 Serial.println("Relay 1 Off requested.");
 AutomaticMode = 0;
 relay_1 = 0;
 digitalWrite(D5, 0);
 server.send(200, "text/html", "<center>Relay 1 is OFF.</center>"); //Send ADC value only to client ajax request
}

void handleRelay2On() { 
 Serial.println("Relay 2 On requested.");
 AutomaticMode = 0;
 relay_2 = 1;
 digitalWrite(D6, 1);
 server.send(200, "text/html", "<center>Relay 2 is ON.</center>"); //Send ADC value only to client ajax request
}

void handleRelay2Off() { 
 Serial.println("Relay 2 Off requested.");
 AutomaticMode = 0;
 relay_2 = 0;
 digitalWrite(D6, 0);
 server.send(200, "text/html", "<center>Relay 2 is OFF.</center>"); //Send ADC value only to client ajax request
}

void handleAutomaticModeOn() { 
 Serial.println("Automatic Mode On.");
 AutomaticMode = 1;
 server.send(200, "text/html", "<center>Automatic Mode is ON.</center>"); //Send ADC value only to client ajax request
}

void handleAutomaticModeOff() { 
 Serial.println("Automatic Mode Off.");
 AutomaticMode = 0;
 server.send(200, "text/html", "<center>Automatic Mode is OFF.</center>"); //Send ADC value only to client ajax request
}

void handleSystemRestart() { 
 Serial.println("Restart requested.");
 server.send(200, "text/html", "<center>Restarting...</center>"); //Send ADC value only to client ajax request
 ESP.restart();
}

void handleNotFound(){
Serial.println("Invalid request.");
server.send(404, "text/plain", "404: Not found"); // Send HTTP status 404 (Not Found) when there's no handler for the URI in the request
}


//===============================================================
//                            SETUP
//===============================================================

void setup() {  
  // Initialisation de la sortie Serial pour nous permettre de monitorer notre système
  Serial.begin(9600);
  Serial.println("\nSetup");
  delay(50);

  // Initialisation du WIFI
  WiFi.begin(WIFI_SSID, WIFI_KEY);

  Serial.printf("Connecting to %s with key %s\n", WIFI_SSID, WIFI_KEY);

  uint32_t timer = millis();
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(200);

    // Si il n'arrive pas à se connecter au bout de 20 secondes, le système redémarre (au cas ou un bug serait survenu)
    if (millis() - timer >= 20000)
    {
    Serial.println("Unable to connect, restarting...");
    ESP.restart();
    }
  }

  Serial.println(" WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Initialisation des PIN de sorties pour le contrôle des relais
  pinMode(D5, OUTPUT);
  pinMode(D6, OUTPUT);
  digitalWrite(D5, 0);
  digitalWrite(D6, 0);
  
  // Initialisation pour le DHT22 et le YL100
  dht.begin();
  yl.begin();

  // Initialisation Serveur HTTP
  server.on("/", handleRoot);
  server.on("/SmartGrow", HTTP_POST, handleSmartGrow); // Call the 'handleLogin' function when a POST request is made to URI "/login"
  server.on("/Relay1On", handleRelay1On);
  server.on("/Relay1Off", handleRelay1Off);
  server.on("/Relay2On", handleRelay2On);
  server.on("/Relay2Off", handleRelay2Off);
  server.on("/AutomaticModeOn", handleAutomaticModeOn);
  server.on("/AutomaticModeOff", handleAutomaticModeOff);
  server.on("/SystemRestart", handleSystemRestart);
  server.onNotFound(handleNotFound); // When a client requests an unknown URI (i.e. something other than "/"), call function "handleNotFound"

  server.begin();

  bot.sendMessage(CHAT_ID, "System Initialized.", "");
  
  Serial.println("System Initialized.");

}

//===============================================================
//                             LOOP
//===============================================================

void loop() {
  //Handle client requests
  server.handleClient();
  
  // Incrémentation de 1 du compteur de boucle
  cptLoop++;

  // Lecture des capteurs
  float _temperature = dht.readTemperature();
  if (_temperature >= -40 && _temperature <= 80) {
    temperature += _temperature;
    cptTemperature++;
  }

  float _humidity = dht.readHumidity();
  if (_humidity >= 0 && _humidity <= 200) {
    humidity += _humidity;
    cptHumidity++;
  }

  float _moisture = yl.readSoilMoisture();
  if (_moisture >= 0 && _moisture <= 200) {
    moisture += _moisture;
    cptMoisture++;
  }

  float _light = max44.getLux();
  if (_light >= 0 && _light <= 1000000) {
    light += _light;
    cptLight++;
  }

  // Si le compteur de boucle arrive à CPT_PUBLISH
  if (cptLoop >= CPT_PUBLISH) {
    temperature = temperature / cptTemperature;
    humidity = humidity / cptHumidity;
    moisture = moisture / cptMoisture;
    light = light / cptLight;

    // Affichage à l'écran des valeurs lues
    Serial.println("======");
    Serial.printf("Temperature : %s C°\n", String(temperature).c_str());
    Serial.printf("Humidity : %s %%\n", String(humidity).c_str());
    Serial.printf("Moisture : %s %%\n", String(moisture).c_str());
    Serial.printf("Light : %s lux\n", String(light).c_str());

    // Contrôle automatique de l'état des relais
    if (AutomaticMode == 1) {
      if (humidity <= 41) {
        relay_1 = 1;
      }

      if (humidity >= 49) {
        relay_1 = 0;
      }

      if (temperature <= 25 && humidity <= 60) {
        relay_2 = 0;
      }

      if (humidity >= 62) {
        relay_2 = 1;
      }

      if (temperature >= 26) {
        relay_2 = 1;
      }
    }

    // Création de l'URL
    String url;
    url.reserve(256);
    url = "http://" + String(THINGSPEAK_HOST) + "/update?api_key=" + String(THINGSPEAK_API_KEY);

    // Ici on intègre les champs et leurs valeurs.
    if (cptTemperature > 0) {
      url += "&field" + String(FIELD_TEMPERATURE) + "=" + temperature;
    }
    else {
      Serial.println("Unable to read temperature");
    }
    
    if (cptHumidity > 0) {
      url += "&field" + String(FIELD_HUMIDITY) + "=" + humidity;
    }
    else {
      Serial.println("Unable to read humidity");
    }
    
    if (cptMoisture > 0) {
      url += "&field" + String(FIELD_MOISTURE) + "=" + moisture;
    }
    else {
      Serial.println("Unable to read soil moisture");
    }

    if (cptLight > 0) {
      url += "&field" + String(FIELD_LIGHT) + "=" + light;
    }
    else {
      Serial.println("Unable to read lux");
    }
    
    if (relay_1 == 1) {
      url += "&field" + String(FIELD_RELAY1) + "=" + 1;
    }
    else {
      url += "&field" + String(FIELD_RELAY1) + "=" + 0;
    }

    if (relay_2 == 1) {
      url += "&field" + String(FIELD_RELAY2) + "=" + 1;
    }
    else {
      url += "&field" + String(FIELD_RELAY2) + "=" + 0;
    }
    
    // Si nous ne sommes plus connectés au WiFi
    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("Connection to the SSID lost, trying to reconnect...");

      uint32_t timer = millis();
      while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(200);

        if (millis() - timer >= 20000) {
          Serial.println(" Unable to connect, restarting...");
          ESP.restart();
        }
      } 
    }

    Serial.printf("Fetching %s\n", url.c_str());
  
    // Etablissement de la communication HTTP
    http.begin(url);
    int httpCode = http.GET();
    
    // Si nous n'avons pas réussi à émettre les données dix fois de suite, nous redémarrons le système (au cas ou un bug serait survenu)
    if (httpCode != HTTP_CODE_OK) {
      Serial.printf("[HTTP] GET... failed, code: %d, error: %s\n", httpCode, http.errorToString(httpCode).c_str());
      FailLoop++;
    }
    else {
      Serial.println("Data sent !");
      FailLoop = 0;
    }
    
    if (FailLoop > 9) {
      ESP.restart();
    }
      
    http.end();
  
    // Commutation des relais
    if (relay_1 == 1) {
      digitalWrite(D5, 1);
      Serial.println("Relay 1 is On.");
    }
    else {
      digitalWrite(D5, 0);
      Serial.println("Relay 1 is Off.");
    }

    if (relay_2 == 1) {
      digitalWrite(D6, 1);
      Serial.println("Relay 2 is On.");
    }
    else {
      digitalWrite(D6, 0);
      Serial.println("Relay 2 is Off.");
    }

    // Remise à zéro
    cptLoop = 0;

    temperature = 0;
    humidity = 0;
    moisture = 0;
    light = 0;

    cptTemperature = 0;
    cptHumidity = 0;
    cptMoisture = 0;
    cptLight = 0;
  }
  
  // Temps en millisecondes où le programme ne fait rien
  delay(TIME_SLEEP);
}

 


Au sujet de la calibration des sondes, dans le code à cet endroit (en rouge ici par exemple) on peut ajouter un coefficient ou une valeur d'offset. Cela m'a permis de réaligner les sondes par rapport à mon thermomètre/hygromètre mécanique de référence. ;)

 

  if (cptLoop >= CPT_PUBLISH) {
    temperature = temperature / cptTemperature - 1.6;
    humidity = humidity / cptHumidity / 1.1;
    moisture = moisture / cptMoisture;
    light = light / cptLight;


Voilà, je trouve ce petit système génial. C'est simple à mettre en oeuvre et vraiment efficace. Merci encore Raphiki, je n'aurais jamais pu réaliser cette installation sans ton aide! :supair:

 

Si vous voulez jeter un oeil, c'est ici :

https://thingspeak.com/channels/580336


Bon grow connecté 2.0 à tous!

 

Modifié par Tastybud
  • Like 1
  • Thanks 2
Lien à poster
Partager sur d’autres sites

Bonjour,
 Tout d'abord merci pour ce tut c'est très sympathique ! 
A la vue de celui-ci j'ai décider de me lancer avec un ESP32 ainsi que des sensor moisture V1.2 afin de mouvoir monit plusieurs pots.

Apres pas mal de galère vue mes très faibles connaissance en arduino je suis arriver à faire fonctionner le 1.2 et j'ai créer une library adapter à celui-ci en regroupant un peut tous ce qu'on peut trouver à son sujet.

Révélation

//"Moisure_sensor_V1_2.h"
 

#pragma once

class V1_2
{
private:
    unsigned int pinRead;
    const int scale_min = 0; // valeur min de la plage
  const int scale_max = 100; // valeur max de la plage 
  const int AirValue = 3400; //Valeur RAW à l'air libre
  const int WaterValue = 850; //Valeur RAW dans un verre d'eau
public:
  V1_2(unsigned int _pinRead);
    void begin();
    float readSoilMoisture();
};

 


Les valeurs RAW utiliser sont une moyenne des 3 capteurs dont je dispose.

 

Révélation

//"Moisture_sensor_V1_2.ccp"

 

#include "Moisture_sensor_V1_2.h"
#include <Arduino.h>

V1_2::V1_2(unsigned int _pinRead)
{
  this->pinRead = _pinRead;
}

void V1_2::begin()
{    
  pinMode(this->pinRead, INPUT);
}

float V1_2::readSoilMoisture()
{
  int RAW = analogRead(this->pinRead);
    float moisture = map(RAW,AirValue,WaterValue,scale_min,scale_max);
    
    return moisture;
}

 

 

 

Pour ceux qui souhaiterais faire des essais et récupérer les valeurs RAW ainsi que sa valeur correspondante en %:

 

Révélation

#include "Moisture_sensor_V1_2.h"

#define wait 2000        // durée d'attente entre les mesures - waiting time

#define PIN_POT1 13
#define PIN_POT2 33

V1_2 pot1(PIN_POT1);
V1_2 pot2(PIN_POT2);

void setup() {
  Serial.begin(115200);
}

void loop() 
{
  int POT1 = analogRead(27);   //v1.2
  int POT2 = analogRead(33);   //v1.2
  
  float moisture = pot1.readSoilMoisture();
  float moisture2 = pot2.readSoilMoisture();
  
  Serial.printf("Moisture 1 : %s %\n",String(POT1).c_str());
  Serial.printf("Moisture 1 : %s %%\n",String(moisture).c_str());
  Serial.printf("Moisture 2 : %s %\n",String (POT2).c_str());
  Serial.printf("Moisture 2 : %s %%\n",String(moisture2).c_str());
  delay(wait);
}

 

Pour ceux qui possède un ESP 32 voici mon code avec 2 capteur d’hygrométrie du sol

 

Révélation

#include "DHT22.h"
#include "MAX44009.h"
#include "Moisture_sensor_V1_2.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <UniversalTelegramBot.h>


#define WIFI_SSID "WIFI ID"
#define WIFI_KEY "WIFI KEY"


#define THINGSPEAK_HOST "api.thingspeak.com"
#define THINGSPEAK_API_KEY "YOUR KEY THINGDPEAK"

#define FIELD_TEMPERATURE 1
#define FIELD_HUMIDITY 2
#define FIELD_POT1 3
#define FIELD_POT2 4


#define PIN_DHT 18
#define PIN_POT1 33
#define PIN_POT2 34
//#define PIN_POT3 35


#define TIME_SLEEP 1000
#define CPT_PUBLISH 30

 


HTTPClient http;

DHT dht(PIN_DHT, DHT22);
V1_2 pot1(PIN_POT1);
V1_2 pot2(PIN_POT2);


uint16_t cptLoop = 0;

float temperature = 0;
float humidity = 0;
float moisture = 0;
float moisture2 = 0;

uint16_t cptTemperature = 0;
uint16_t cptHumidity = 0;
uint16_t cptMoisture = 0;
uint16_t cptMoisture2 = 0;


void setup()
{
  Serial.begin(115200);
  Serial.println("\nSetup");
  delay(50);

  // Initialisation du WIFI
  WiFi.begin(WIFI_SSID, WIFI_KEY);

  Serial.printf("Connecting to %s with key %s\n", WIFI_SSID, WIFI_KEY);
  
  uint32_t timer = millis();
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(200);

)
    if (millis() - timer >= 20000)
    {
      Serial.println("Unable to connect, restarting...");
      ESP.restart();
    }
  }
 
  Serial.println(" WiFi connected");
  dht.begin();
}

 


void loop()
{
  // Incrémentation de 1 du compteur de boucle
  cptLoop++;
  
  // Lecture des capteurs
  float _temperature = dht.readTemperature();
  if (_temperature >= -40 && _temperature <= 80)
  {
    temperature += _temperature;
    cptTemperature++;
  }

  float _humidity = dht.readHumidity();
  if (_humidity >= 0 && _humidity <= 200)
  {
    humidity += _humidity;
    cptHumidity++;
  }

  float _moisture = pot1.readSoilMoisture();
  if (_moisture >= 0 && _moisture <= 100)
  {
    moisture += _moisture;
    cptMoisture++;
  }

  float _moisture2 = pot2.readSoilMoisture();
  if (_moisture2 >= 0 && _moisture2 <= 100)
  {
    moisture2 += _moisture2;
    cptMoisture2++;
  }


  if (cptLoop >= CPT_PUBLISH)
  {
    temperature = temperature / cptTemperature;
    humidity = humidity / cptHumidity;
    moisture = moisture / cptMoisture;
    moisture2 = moisture2 / cptMoisture2;
    

    Serial.println("======");
    Serial.printf("Temperature : %s C°\n", String(temperature).c_str());
    Serial.printf("Humidity : %s %%\n", String(humidity).c_str());
    Serial.printf("Moisture : %s %%\n", String(moisture).c_str());
    Serial.printf("Moisture2 : %s %%\n", String(moisture2).c_str());

    // Si nous ne sommes plus connectés au WiFi
    if (WiFi.status() != WL_CONNECTED)
    {
      Serial.println("Connection to the SSID lost, trying to reconnect...");
      
      uint32_t timer = millis();
      while (WiFi.status() != WL_CONNECTED)
      {
        Serial.print(".");
        delay(200);
    
        if (millis() - timer >= 20000)
        {
          Serial.println(" Unable to connect, restarting...");
          ESP.restart();
        }
      }
    }

    // Création de l'URL
    String url;
    url.reserve(256);
    url = "http://"+ String(THINGSPEAK_HOST) +"/update?api_key="+ String(THINGSPEAK_API_KEY);

    // Ici on intègre les champs et leurs valeurs.
    if (cptTemperature > 0)
      url += "&field"+ String(FIELD_TEMPERATURE) +"="+ temperature;
    else
      Serial.println("Unable to read temperature");

    if (cptHumidity > 0)
      url += "&field"+ String(FIELD_HUMIDITY) +"="+ humidity;
    else
      Serial.println("Unable to read humidity");

    if (cptMoisture > 0)
      url += "&field"+ String(FIELD_POT1) +"="+ moisture;
    else
      Serial.println("Unable to read soil moisture");
      
    if (cptMoisture2 > 0)
      url += "&field"+ String(FIELD_POT2) +"="+ moisture2;
    else
      Serial.println("Unable to read soil moisture");
      
        
    Serial.printf("Fetching %s\n", url.c_str());      

    // Etablissement de la communication HTTP
    http.begin(url);
    int httpCode = http.GET();

   


    if(httpCode != HTTP_CODE_OK)
    {
      Serial.printf("[HTTP] GET... failed, code: %d, error: %s\n", httpCode, http.errorToString(httpCode).c_str());
      ESP.restart();
    }
  
    Serial.println("Data sent !");
  
    http.end();

    // Remise à zéro
    cptLoop = 0;
    
    temperature = 0;
    humidity = 0;
    moisture = 0;
    moisture2 = 0;


    cptTemperature = 0;
    cptHumidity = 0;
    cptMoisture = 0;
    cptMoisture2 = 0;
    
  }
  delay(TIME_SLEEP);
}

 

Voila ce qu'il en est de mon avancée de l'adaptation pour un ESP32.
Reste a ce jour un point qui dépasse mon niveau médiocre le capteur MAX44009 ne fonctionne toujours pas j'ai un retour de valeur à 0.00 je n'arrive pas a débugg.
Si quelqu'un a une idée ?

 

Mon channel https://thingspeak.com/channels/657204

 

Modifié par Shint4r0
  • Like 1
Lien à poster
Partager sur d’autres sites

Hello !

 

Chouette tout ça :) Content que ça en inspire plus d'un !

 

@Tastybud

Propre ton petit boîtier :) 

Ton interface est sympa également, l'ajout des graph ThingSpeak rend le truc coolos et ton système automatisé est plutôt bien pensé.

Pour les coupures ouais dans le code original, si il y a eu un soucis d'envoi, l'ESP se reset en cas de bug inopiné. Vu qu'il n'automatise rien à la base, cela ne pose pas de soucis.

Chouette système en tout cas, ça pourrait servir d'ébauche au tuto développement d'un système automatisé même si il y a surement quelques opti à faire au niveau du code :p 

Merci pour ta contrib en tout cas !

 

@Shint4r0 

Bien joué pour l'ajout de l'ESP32. Pour ton soucis lié au capteur MAX44009, sur quels pins est-il connecté ? La correspondance est-elle correcte dans le code ? (PIN_SCL et PIN_SDA)

Sinon as-tu bien penser à ajouter les board supplémentaire dans Arduino IDE pour coder sur l'ESP32 et non l'ESP8266 comme expliqué ici https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md ?

Normalement sans ça tu ne devrais même pas pouvoir flasher l'ESP32 si tu as laissé les informations dans "Type de carte" > "NodeMCU ESP 1.0 ESP12E" 

 

---

 

Concernant le Moisture Sensor SEN0193 (que tu appelles V1.2 Shint4r0, ref indiquée sur le PCB) :

Je viens de le valider le remplacement du YL100 avec le SEN0193 dans le tuto.

Si vous disposez du YL100, une version du code est toujours disponible sur mon dépot (https://github.com/RaphikiCW/smartgrow). Vous devez cliquer sur le bouton "Branch: master" et sélectionner la branche "yl100", puis cliquez sur "Download ZIP".

A notez que la façon de lire le capteur ne change pas de beaucoup, il s'agit de mapper une valeur analogique entre 0 et 1023 => en pourcentage, en faisant en sorte que la valeur lu par le capteur dans l'air = 0% et que la valeur lu dans l'eau = 100%.

Si vous jetez un coup d'oeil au fichier SEN0193.h vous trouverez ces ligne :

 

float valueO2 = 820;
float valueH2o = 350;

 

Ces valeurs de calibration sont définis selon ce que j'ai pu lire sur 2 SEN0193, mais elles peuvent être différentes selon le capteur, ce qui justifierai de potentielle valeur inférieur à 0% ou supérieur à 100%. Si elles le sont, vous pouvez changer ces lignes selon les valeurs de votre capteur.

 

--- 

 

Concernant l'hydro edition j'aurais un peu de temps pour m'y consacrer la semaine prochaine.

Toutefois je doute d'arriver à des résultats concluant concernant le pH et l'EC... Les sondes utilisés sont très cheap et ne sont pas faites pour être constamment plonger dans l'eau, les perte de calibration serait trop fréquente (les testeur perde leur calibration progressivement puis nettement après 2-3 jours). Il en est de même d'ailleurs pour les testeur acheté 20-30e.

Il existe des testeur étant justement conçu pour être constamment dans la solution, mais là on attend des budgets que je ne peux pas me permettre.

Donc du coup ça casse un peu l'idée de monitoring par courbe si on peut pas laisser la sonde dans la solution. Donc je réfléchi à une version avec un écran comme évoqué par @Hydro_Funktion ou le test du pH et de l'EC se ferait de façon promptuelle et non continue, même si on perd un peu l'idée du monitoring.

 

Tcho!

Modifié par Raphiki
  • Like 1
Lien à poster
Partager sur d’autres sites

@Raphiki Merci de ta réponse.

En fait le problème ne vient pas du réglage de la définition pins mais plutôt de ou se brancher

 

Révélation

#ifdef ESP8266
        Wire.begin(dataPin, clockPin);
#else  // other platforms
        Wire.begin();
#endif

Si j'ai bien compris ce bout de code il dit que si je n'utilise pas d'ESP8266 je ne défini pas les PIN SDA ni SCL
en cherchant sur le net un autre modèle de capteur je suis tomber sur une video ou la personne utilise les pins 21 (SDA) et 22 (SDC) je me suis brancher dessus sa fonctionne.

Par-contre la valeur lue 25000 lux tout une pauvre lampe me semble complètement a cote de la plaque. Je suppose qu'il y a une config possible a se niveau.
j'ai récupérer un code de test et lui me sort une valeur bien plus cohérente de 97 lux même si je trouve sa encore un peut trop élever c'est correct en comparaison.

 

Si quelqu'un trouve la modif à faire le voici :

Révélation

#include <Wire.h>
#include "MAX44009.h"

MAX44009 light;
 
void setup() 
{
  Serial.begin(115200);
  Wire.begin();
  
  delay(500);
  
  if(light.begin())
    {
        Serial.println("Could not find a valid MAX44009 sensor, check wiring!");
    while(1);
  }
}
 
void loop() 
{
  Serial.print("Light (lux):    ");
  Serial.println(light.get_lux());
  delay(1000);
}

 

Révélation

#include "MAX44009.h"
#include <math.h>

MAX44009::MAX44009() {}

int MAX44009::begin()
{
  Wire.beginTransmission(MAX_ADDR);
  Wire.write(0x02);
  Wire.write(0x40);
  return Wire.endTransmission();
}


float MAX44009::get_lux(void)
{
  unsigned int data[2];
  
  Wire.beginTransmission(MAX_ADDR);
  Wire.write(0x03);
  Wire.endTransmission();
 
  // Request 2 bytes of data
  Wire.requestFrom(MAX_ADDR, 2);
 
  // Read 2 bytes of data luminance msb, luminance lsb
  if (Wire.available() == 2)
  {
        data[0] = Wire.read();
        data[1] = Wire.read();
  }
 
  // Convert the data to lux
  int exponent = (data[0] & 0xF0) >> 4;
  int mantissa = ((data[0] & 0x0F) << 4) | (data[1] & 0x0F);
  
  //float luminance = pow(2, exponent) * mantissa * 0.045;
  float luminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045);
  
  return luminance; 
}

 

Révélation

#ifndef MAX44009_h
#define MAX44009_h
#include <Arduino.h>
#include <Wire.h>

#define MAX_ADDR 0x4A

class MAX44009 {
    public:
    MAX44009();
    
    int begin();
            
    float get_lux(void);
    
};

#endif

 

 

Modifié par Shint4r0
Lien à poster
Partager sur d’autres sites

Re @Shint4r0

 

25 000 lux si le capteur est directement sous une lampe même faible c'est pas déconnant, c'est plutôt normal.

Si la valeur varie comme il faut selon le niveau de lumière, tu n'as plus de soucis du coup ? En soit le niveau lu n'a pas vraiment d'importance, la valeur n'est pas vraiment exploitable scientifiquement, seul la variation compte.

 

Le réseau I2C doit en effet être définit sur 2 pins : SDA et SCL. Sur une carte Arduino, elles sont définit nativement. Sur ESP8266 et ESP32, on te laisse le choix de définir quelles sont ces pins. En 2 mots, l'I2C est un bus de communication te permettant de relié plusieurs esclaves (capteurs, relay, etc) en les connectant tous en parallèle sur les 2 seules pins SDA (data) et SCL (clock).

Après sur Internet tu peux trouver des librairies à jour contenant du code compatible ESP/Arduino mais c'est pas toujours le cas, auquel cas un peu de bidouille s'impose ;) 

 

A+

Lien à poster
Partager sur d’autres sites

Ok pour sa interessant le fait de les utiliser en paralelle. 

 

Pour la valeur ce serais bien d’avoir quand meme quelque chose de logique et plosible. La DS donne entre 0 et 188000 je me retrouve avec 380k sous les lampes ils serais interessant de pouvoir appliquer un gain a la valeur par exemple pour revenir a quelque chose de convenable. 

 

Prochaine etape c’est l’analyse du seuil a partir duquel arroser, 30% 40% ?

 

je vais recevoir un starter kit de dev pour raspberry pi je pense que sa me permettras de mieu comprendre certaines choses.

 

 

Lien à poster
Partager sur d’autres sites

Salut, 

 

pour sur sa va intéresser beaucoup de monde !

 

voici un firmware (qui existe pour ESP8266) avec interface WEB ou l'on peut tout gérrer sur page HTTP en developpement pour le ESP 32 mais il me plais déjà beaucoup. possibilitée de renvoyer sur thingspeak et 2 autre gestion domotique pour un total de 3 simultané. tres pratique pour moi qui ai 2 emplacement séparer (croissance / flo) donc l'objectif et de centraliser 2 esp32 et de remonter le tout sur un Raspberry pi 3 équiper de jeedom ou autre outil domotique a définir. 

Lien à poster
Partager sur d’autres sites
  • 9 mois après ...

Salut a tous !

 

Tout d'abord merci raphiki pour ce tuto très instructif.
Je tiens a préciser que je suis novice en domotique (autrement je ne me retrouverai surement pas dans cette situation). Tout semble s'être déroulé sans accro, de la création du channel ThingSpeak jusqu'au développement de l'embarqué. Cependant aucune donnée ne s'affiche après le téléversement.
 

Quand je clique sur "Moniteur Série" (outil dont je n'ai pas compris l'utilité d'ailleurs) cela m'inscrit en boucle (en 9600 baud ???) :

 

Révélation

.....................Unable to connect, restarting...
?܆⸮⸮D⸮N
Setup
Connecting to XXXX_E5A0 with key ygbv7tzk94icdb6naa54
...................................



Et en bas de Arduino 1.8.10, pas de message d'erreur semble t-il mais
 

Révélation

Le croquis utilise 292140 octets (27%) de l'espace de stockage de programmes. Le maximum est de 1044464 octets.
Les variables globales utilisent 28432 octets (34%) de mémoire dynamique, ce qui laisse 53488 octets pour les variables locales. Le maximum est de 81920 octets.
esptool.py v2.6
2.6
esptool.py v2.6
Serial port COM6
Connecting....
Chip is ESP8266EX
Features: WiFi
MAC: cc:50:e3:63:b1:be
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 296288 bytes to 212890...

Writing at 0x00000000... (7 %)
Writing at 0x00004000... (15 %)
Writing at 0x00008000... (23 %)
Writing at 0x0000c000... (30 %)
Writing at 0x00010000... (38 %)
Writing at 0x00014000... (46 %)
Writing at 0x00018000... (53 %)
Writing at 0x0001c000... (61 %)
Writing at 0x00020000... (69 %)
Writing at 0x00024000... (76 %)
Writing at 0x00028000... (84 %)
Writing at 0x0002c000... (92 %)
Writing at 0x00030000... (100 %)
Wrote 296288 bytes (212890 compressed) at 0x00000000 in 18.9 seconds (effective 125.5 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

 

 

Si quelqu'un aurait une idée du problème, une étape omis ou quoi que ce soit. Si jamais vous avez besoin de renseignements/données supplémentaires n’hésitez pas non plus.

Je vous remercie par avance. WalkaJazz

 

Modifié par Walka-Jazz
  • Like 1
Lien à poster
Partager sur d’autres sites
  • 4 semaines après ...

Hello Walka !

 

Déso pour la réponse un peu tardive

Eh bien le problème semble simple : "Unable to connect" signifie que ton ESP n'a pas pu se connecter à ton WiFi, la cause peut-être un mauvais SSID, Clef ou une box trop éloigné du module.

Le monitor série est en fait une fenêtre qui affiche ce que t'envoie l'ESP à travers son port série (par USB ici).

 

A+

Modifié par Raphiki
Lien à poster
Partager sur d’autres sites
  • 3 semaines après ...
  • 1 mois après ...

Bonjour A tous, merci pour toutes ces contributions.Et merci @Raphiki pour ce post for inspirant. C'est à mon tours de me lancer.

Mon projet dans un premier temps est de pouvoir monitorer mon placo pour peut être ensuite automatiser un peu.

 

Il s'agit de ma première expérience dans le grow. c'est pour cela que je suis très intéressé pour surveiller et apprendre de mes erreurs.

J'ai lu et relu ce fil et donc je me suis mis directement sur l'ESP32 et la sonde SEN0193.

 

Seulement voilà ça ne se passe pas vraiment comme prévu, impossible de connecter cette sonde.

Je n'ai eu aucun pb avec le DHT22 mais les ports "analogique" ne semble pas aussi simple que cela a connecter.

il semblerait même que certains ne fonctionnent pas quand le WIFI est actif ( pratique).

 

Auriez vous testé un peu? et pourriez vous m'aider?

Merci à vous et bon grow

  • Like 1
Lien à poster
Partager sur d’autres sites
  • 2 semaines après ...

Hello tous, 

j'ai réussi à monter le contrôleur ili marche plutôt bien. A ceci près qu'au bout de quelques heures le DHT22 se coupe.

Je suis a ce moment obligé de débrancher et de rebrancher pour que le DHT22 se re connecte.

Avez vous eu ce bug ? Avez vous une idée de ce qui se passe ? et/ou avez vous une solution ?

Merci d'avance.

 

Lien à poster
Partager sur d’autres sites
  • 1 mois après ...

Salut, 

 

J ai eu le même soucis avec un dht 22. J ai réglé le problème en utilisant le bootloader "Espeasy" la version Mega (2.0) qui permet d avoir une interface sans programmation. Par contre à vérifié s il est compatible avec votre logiciel, j utilise domoticz pour ma part. 

Et vérifier aussi ton câblage qui est important, distance, blindage s il est long, résistance pull-up de 4,7k si tu utilise le dht22 directement (s il n est pas monter sur un circuit imprimé)

Je suis passer depuis sur un capteur Bme280 et je ne reviendrai pas au dht

Bon bricolage

 

Ciao

  • Like 2
Lien à poster
Partager sur d’autres sites
  • 3 semaines après ...

Bonjour , déjà merci pour ce petit tuto.

Je viens aujourd'hui je viens de recevoir le capteur de température et il me manque plus que le capteur de luminosité.

Je viens de faire le codage et voila qu'a la fin quand je fais téléverser a la fin il met met leaving... puis hard resetting via rts pin ....

j'ai essayé plusieurs fois et a chaque fois le même message d'erreur.

@Curly-Bud aurais déjà rencontrer ce genre d'erreur ?

 

PB Résolue erreur de connexion de broches.

 

 

merci d'avance

Modifié par Fraxar
Pb résolue
  • Like 1
Lien à poster
Partager sur d’autres sites
  • 4 semaines après ...

Bonjour à tous,

Je vais recevoir un capteur BlueDot BME280+TSL2591 (Luxmètre) et intégrer un facteur de conversion PPFD.

 

A voir sur mon JDC :

 

 

 

A+

Modifié par Cannoob
  • Like 1
Lien à poster
Partager sur d’autres sites
  • 1 an après ...

bonjour

 

désolé du detterage de topic , mais je suis en train d essayer de faire fonctionner tout cela et j ai toujours été nul nul en programmation. 

j ai une erreur à la compilation et je ne comprend pas vraiment le soucis . 

si quelqu un passe par là ... ca serait top

 

Arduino : 1.8.15 (Windows 10), Carte : "NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, 4MB (FS:2MB OTA:~1019KB), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200"

C:\Users\lXXXX\Documents\Arduino\smartgrow\smartgrow.ino: In function 'void loop()':
smartgrow:181:15: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
  181 |     http.begin(url);
      |     ~~~~~~~~~~^~~~~
exit status 1
call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

 

 


 

Lien à poster
Partager sur d’autres sites
  • 2 semaines après ...

Salut @ibsla

 

Cela ressemble a une mise à jour de la librairie arduino-ESP8266 qui a rendu obsolète certaines fonctions utilisées ici, donc une erreur que tu fais bien de remonté car ça demande une update au niveau du tuto du coup.

 

Tu doit pouvoir remédier au problème en sélectionnant une ancienne version de la librairie esp8266 en cliquant sur Outil > Type de carte > Gestionnaire de cartes > Trouver la librairie "esp8266" et sélectionner par exemple la 2.4.2 (version datant de la période où ce tuto a été rédigé) puis cliquer sur Installer.

 

image.png.34fc1a2e4752d94290beca34a40aea1e.png

 

Dis moi si ça roule, que je fasse une update du tuto en précisant d'utiliser la 2.4.2.

 

A+

Lien à poster
Partager sur d’autres sites