Sensor capacitivo de humedad del suelo.

Responder
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Para quien esté interesado en probar el sensor capacitivo de humedad del suelo
Utilizamos un canal de temperatura y humedad.
La temperatura muestra la lectura del sensor analógico "Esto no es necesario pero no hay canal independiente para humedad así que lo usamos" muestra un valor alrededor de 700 en seco (0%) y de alrededor de 250 estando dentro de un vaso de agua (100%).
La humedad muestra la humedad del suelo entre 0% y 100%.
¡Necesita calibración para una lectura correcta!

Csm_bb.png
Csm_bb.png (107.38 KiB) Visto 4466 veces

Led = D4 "Led incorporado en wemos / nodemcu"
Parpadeo rápido "0.5s" = no conectado / conectando.
Parpadeo lento "1.5s" = WiFiConfig.
Apagado = conectado Ok.

Pulsador = D3:

Presione durante al menos 5 segundos para WiFiConfig. (Nombre de WiFiAP "CSM_Probe")

3 clics para calibrar y almacenar el valor del sensor a humedad mínima 0% "expuesto al aire"
El led parpadea 3 veces.

2 clics para calibrar y almacenar el valor del sensor para la humedad máxima del 100% "sumergido en agua"
El led parpadea 2 veces.

CSM_DOUT_16Mbit.rar
(669.27 KiB) Descargado 321 veces
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

En vista de la gran aceptación del proyecto añado código y librerías. :lol: :lol: :lol: :lol:

Código Arduino:

Código: Seleccionar todo

#include "LittleFS.h" // LittleFS is declared 
#include <WiFiManager.h>
#include <ArduinoJson.h> //--------- V6 ------ 
#include <EEPROM.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266TrueRandom.h>
#include <Button3.h>
#include <Ticker.h> 
#include <SuplaDevice.h>  
#include <supla/sensor/CSM.h>
#include <supla/network/esp_wifi.h>
Supla::ESPWifi wifi("", "");  //------ Do not change----wifimanager takes care------

extern "C"
{
#include "user_interface.h"
}

//#define D0 16  //no internal pullup resistor
//#define D1  5
//#define D2  4
//#define D3  0  //must not be pulled low during power on/reset, toggles value during boot
//#define D4  2  //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15  //must not be pulled high during power on/reset

#define status_led 2   // D4
#define wificonfig_pin 0  // D3  WiFiconfig 

char Supla_server[81]=("Unknown server address");
char Email[81]=("Unknown email address");                        
char Supla_name[51];
char Supla_status[51];
int C_W_state = HIGH; 
int last_C_W_state = HIGH;
unsigned long time_last_C_W_change = 0; 
long C_W_delay = 5000;                      // config delay 5 seconds        
bool shouldSaveConfig = false;
bool initialConfig = false; 
char GUID[SUPLA_GUID_SIZE];
char AUTHKEY[SUPLA_AUTHKEY_SIZE];
byte uuidNumber[16];
int s;
bool starting = true; 
bool Tik = true;
Button3 buttonA = Button3(wificonfig_pin);
ESP8266WebServer httpServer(81);
ESP8266HTTPUpdateServer httpUpdater;
WiFiManager wifiManager;
Ticker ticker;

Supla::Sensor::CSM *CSM1 = nullptr;

void tick() {
  int state = digitalRead(status_led);  
  digitalWrite(status_led, !state);     
}
void saveConfigCallback () {          
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
 ticker.attach(1.5, tick);
   WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 81,"required");
   WiFiManagerParameter custom_Email("email", "Email", Email, 81,"required");
   WiFiManagerParameter custom_Supla_name("name", "Supla Device Name", Supla_name, 51,"required");
   WiFiManagerParameter custom_html_id21("<div><h4> - Supla State -   ");
   WiFiManagerParameter custom_html_id22( Supla_status);
   WiFiManagerParameter custom_html_id23( "</h4></div>");

   wifiManager.setBreakAfterConfig(true);
   wifiManager.setSaveConfigCallback(saveConfigCallback);
  
   wifiManager.addParameter(&custom_Supla_server);
   wifiManager.addParameter(&custom_Email);
   wifiManager.addParameter(&custom_Supla_name);
   wifiManager.addParameter(&custom_html_id21);
   wifiManager.addParameter(&custom_html_id22);
   wifiManager.addParameter(&custom_html_id23);

   wifiManager.setCustomHeadElement("<style>html{ background-color: #01DF3A;}</style><div class='s'><svg version='1.1' id='l' x='0' y='0' viewBox='0 0 200 200' xml:space='preserve'><path d='M59.3,2.5c18.1,0.6,31.8,8,40.2,23.5c3.1,5.7,4.3,11.9,4.1,18.3c-0.1,3.6-0.7,7.1-1.9,10.6c-0.2,0.7-0.1,1.1,0.6,1.5c12.8,7.7,25.5,15.4,38.3,23c2.9,1.7,5.8,3.4,8.7,5.3c1,0.6,1.6,0.6,2.5-0.1c4.5-3.6,9.8-5.3,15.7-5.4c12.5-0.1,22.9,7.9,25.2,19c1.9,9.2-2.9,19.2-11.8,23.9c-8.4,4.5-16.9,4.5-25.5,0.2c-0.7-0.3-1-0.2-1.5,0.3c-4.8,4.9-9.7,9.8-14.5,14.6c-5.3,5.3-10.6,10.7-15.9,16c-1.8,1.8-3.6,3.7-5.4,5.4c-0.7,0.6-0.6,1,0,1.6c3.6,3.4,5.8,7.5,6.2,12.2c0.7,7.7-2.2,14-8.8,18.5c-12.3,8.6-30.3,3.5-35-10.4c-2.8-8.4,0.6-17.7,8.6-22.8c0.9-0.6,1.1-1,0.8-2c-2-6.2-4.4-12.4-6.6-18.6c-6.3-17.6-12.7-35.1-19-52.7c-0.2-0.7-0.5-1-1.4-0.9c-12.5,0.7-23.6-2.6-33-10.4c-8-6.6-12.9-15-14.2-25c-1.5-11.5,1.7-21.9,9.6-30.7C32.5,8.9,42.2,4.2,53.7,2.7c0.7-0.1,1.5-0.2,2.2-0.2C57,2.4,58.2,2.5,59.3,2.5z M76.5,81c0,0.1,0.1,0.3,0.1,0.6c1.6,6.3,3.2,12.6,4.7,18.9c4.5,17.7,8.9,35.5,13.3,53.2c0.2,0.9,0.6,1.1,1.6,0.9c5.4-1.2,10.7-0.8,15.7,1.6c0.8,0.4,1.2,0.3,1.7-0.4c11.2-12.9,22.5-25.7,33.4-38.7c0.5-0.6,0.4-1,0-1.6c-5.6-7.9-6.1-16.1-1.3-24.5c0.5-0.8,0.3-1.1-0.5-1.6c-9.1-4.7-18.1-9.3-27.2-14c-6.8-3.5-13.5-7-20.3-10.5c-0.7-0.4-1.1-0.3-1.6,0.4c-1.3,1.8-2.7,3.5-4.3,5.1c-4.2,4.2-9.1,7.4-14.7,9.7C76.9,80.3,76.4,80.3,76.5,81z M89,42.6c0.1-2.5-0.4-5.4-1.5-8.1C83,23.1,74.2,16.9,61.7,15.8c-10-0.9-18.6,2.4-25.3,9.7c-8.4,9-9.3,22.4-2.2,32.4c6.8,9.6,19.1,14.2,31.4,11.9C79.2,67.1,89,55.9,89,42.6z M102.1,188.6c0.6,0.1,1.5-0.1,2.4-0.2c9.5-1.4,15.3-10.9,11.6-19.2c-2.6-5.9-9.4-9.6-16.8-8.6c-8.3,1.2-14.1,8.9-12.4,16.6C88.2,183.9,94.4,188.6,102.1,188.6z M167.7,88.5c-1,0-2.1,0.1-3.1,0.3c-9,1.7-14.2,10.6-10.8,18.6c2.9,6.8,11.4,10.3,19,7.8c7.1-2.3,11.1-9.1,9.6-15.9C180.9,93,174.8,88.5,167.7,88.5z'/></svg>");
   wifiManager.setMinimumSignalQuality(8);
   //wifiManager.setShowStaticFields(true); // force show static ip fields
   //wifiManager.setShowDnsFields(true);    // force show dns field always
   wifiManager.setConfigPortalTimeout(180);

   if (!wifiManager.startConfigPortal("CSM_Probe")) { Serial.println("Not connected to WiFi but continuing anyway.");} else { Serial.println("connected...yeey :)");}                
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Email, custom_Email.getValue());
    strcpy(Supla_name, custom_Supla_name.getValue()); 
    if(strcmp(Supla_server, "get_new_guid_and_authkey") == 0){
      Serial.println("new guid & authkey.");
      EEPROM.write(300, 0);
      EEPROM.commit();
      ESP.reset(); 
    }
    WiFi.softAPdisconnect(true);   //  close AP
    ticker.detach();
    digitalWrite(status_led, HIGH);    
}
void status_func(int status, const char *msg) {    //    ------------------------ Status --------------------------
  if (s != status){
    s = status; 
      if (s != 10){
        strcpy(Supla_status, msg); 
  }  }            
}
void guid_authkey(void) {
  if (EEPROM.read(300) != 60){
    int eep_gui = 301;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString += "0123456789abcdef"[topDigit];
      uuidString += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid = uuidString.length();
    for (int i = 0; i < length_uuid; ++i) {
      EEPROM.put(eep_gui + i, uuidString[i]);
    }

    int eep_aut = 341;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString2 = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString2 += "0123456789abcdef"[topDigit];
      uuidString2 += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid2 = uuidString2.length();
    for (int i = 0; i < length_uuid2; ++i) {
      EEPROM.put(eep_aut + i, uuidString2[i]);
    }
    EEPROM.write(300, 60);
    EEPROM.commit();
  }
  read_guid();
  read_authkey();
  Serial.print("GUID : ");Serial.println(read_guid()); 
  Serial.print("AUTHKEY : ");Serial.println(read_authkey()); 
}

String read_guid(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 301;
  int end_guid = eep_star + SUPLA_GUID_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_guid + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_guid = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      GUID[ii] = strtoul( _guid, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}
String read_authkey(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 341;
  int end_authkey = eep_star + SUPLA_AUTHKEY_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_authkey + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_authkey = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      AUTHKEY[ii] = strtoul( _authkey, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}

void setup() {

   wifi_set_sleep_type(NONE_SLEEP_T); 
    
  Serial.begin(115200);  
  pinMode(wificonfig_pin, INPUT_PULLUP);
  pinMode(status_led,OUTPUT); 
  ticker.attach(0.5, tick);
  
  EEPROM.begin(1024);
  if (EEPROM.read(300) != 60){initialConfig = true;} 
  guid_authkey();

  if (WiFi.SSID()==""){ initialConfig = true;} 

  buttonA.setClickHandler(click);
  buttonA.setDoubleClickHandler(doubleClick);
  buttonA.setTripleClickHandler(tripleClick);

  if (LittleFS.begin()) {  // ------------------------- wificonfig read -----------------
    Serial.println("mounted file system");
    if (LittleFS.exists("/config.json")) {
      Serial.println("reading config file");
       File configFile = LittleFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
         size_t size = configFile.size();
         std::unique_ptr<char[]> buf(new char[size]);
         configFile.readBytes(buf.get(), size);
        DynamicJsonDocument json(1024);
        DeserializationError deserializeError = deserializeJson(json, buf.get());
        serializeJsonPretty(json, Serial);
        if (!deserializeError) {Serial.println("\nparsed json");         
          if (json.containsKey("Supla_server")) strcpy(Supla_server, json["Supla_server"]);
          if (json.containsKey("Email")) strcpy(Email, json["Email"]);
          if (json.containsKey("Supla_name")) strcpy(Supla_name, json["Supla_name"]);       
        } else {
          Serial.println("failed to load json config");
           initialConfig = true;
        }
        configFile.close(); 
      }
    }
   } else {
    Serial.println("failed to mount FS");
  }
   wifi_station_set_hostname(Supla_name);
   
  WiFi.mode(WIFI_STA); // Force to station mode because if device was switched off while in access point mode it will start up next time in access point mode.

  SuplaDevice.setStatusFuncImpl(&status_func);
  SuplaDevice.setName(Supla_name);
  wifi.enableSSL(false); 
   
  CSM1 = new Supla::Sensor::CSM(A0,100); // pin, EEPROM offset

     SuplaDevice.begin(GUID,Supla_server,Email,AUTHKEY);
        
}

void loop() {
   if (initialConfig == true){ondemandwifiCallback();}

   int C_W_read = digitalRead(wificonfig_pin);{  
   if (C_W_read != last_C_W_state) {            
     time_last_C_W_change = millis();
   }
   if ((millis() - time_last_C_W_change) > C_W_delay) {     
     if (C_W_read != C_W_state) {     
       C_W_state = C_W_read;       
       if (C_W_state == LOW) {
        ondemandwifiCallback () ;
       }
     }
    }
   last_C_W_state = C_W_read;            
 }
  
  if (shouldSaveConfig == true) { // ------------------------ wificonfig save --------------
    Serial.println(" config...");  
    DynamicJsonDocument json(1024);
    json["Supla_server"] = Supla_server;
    json["Email"] = Email;
    json["Supla_name"] = Supla_name;
    File configFile = LittleFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }
    serializeJsonPretty(json, Serial);
    serializeJson(json, configFile);
    configFile.close();
    Serial.println("Config written successfully");
    shouldSaveConfig = false;
    initialConfig = false;
    ticker.detach();
    digitalWrite(status_led, HIGH);  
    WiFi.mode(WIFI_STA);   
    delay(5000);
    ESP.restart();     
  }
  
   buttonA.loop();     
   SuplaDevice.iterate();
   delay(25);

   if (WiFi.status() == WL_CONNECTED){
    if (starting){
      httpUpdater.setup(&httpServer, "/update", "admin", "pass");
      httpServer.begin(); 
      starting = false;         
     }
    httpServer.handleClient();
   }else if (Tik == false){
    ticker.attach(0.5, tick);
    Tik = true;
   }

  if (s == 17){
    if ((Tik == true) && (WiFi.status() == WL_CONNECTED)){
      ticker.detach();
      digitalWrite(status_led, HIGH); 
      Tik = false;
      }     
  }
}

void click(Button3& btn) {

}
void doubleClick(Button3& btn) {
  CSM1->storeMax();
  ticker.detach();
  Tik = false;
  digitalWrite(status_led, HIGH); 
  delay(200);
  digitalWrite(status_led, LOW); 
  delay(200);
  digitalWrite(status_led, HIGH); 
  delay(200);
  digitalWrite(status_led, LOW); 
  delay(200);
  digitalWrite(status_led, HIGH); 
}
void tripleClick(Button3& btn) {
  CSM1->storeMin();
  ticker.detach();
  Tik = false;
  digitalWrite(status_led, HIGH); 
  delay(200);
  digitalWrite(status_led, LOW); 
  delay(200);
  digitalWrite(status_led, HIGH); 
  delay(200);
  digitalWrite(status_led, LOW); 
  delay(200);
  digitalWrite(status_led, HIGH); 
  delay(200);
  digitalWrite(status_led, LOW); 
  delay(200);
  digitalWrite(status_led, HIGH);  
}
void longClick(Button3& btn) {

}

Librería sensor capacitivo humedad suelo: CSM.h
Copiar a: “Arduino\libraries\SuplaDevice\src\supla\sensor”

Código: Seleccionar todo

#ifndef _csm_h
#define _csm_h

#include "therm_hygro_meter.h"

namespace Supla {
namespace Sensor {
class CSM: public ThermHygroMeter {
  public:
    CSM(int pin, int eepAdresse) {
      _pin = pin;
      eep_ofset = eepAdresse;
      lastValidTemp = TEMPERATURE_NOT_AVAILABLE;	
    }

    double getTemp() {

      int value = analogRead(_pin);
	  if ((value < lastValidTemp - 5 ) || (value > lastValidTemp + 5 )){
        lastValidTemp = value;	  	
	  }
      return lastValidTemp;
    }

    double getHumi() {

      int _value = analogRead(_pin);
      int value = map(_value, max_value, min_value, 100,0);

      return value;
    }


    void onInit() {
      EEPROM.get(eep_ofset,min_value);
      if ((min_value < 100) || (min_value >1023)) min_value = 1023;
      supla_log(LOG_DEBUG, "load min CSM value %d", min_value);
      EEPROM.get(eep_ofset + 5,max_value);
      if ((max_value < 0) || (max_value >1023)) max_value = 0;
	  if (max_value >= min_value) max_value = 0;
      supla_log(LOG_DEBUG, "load max CSM value %d", max_value);
      channel.setNewValue(getTemp(), getHumi());
    }

  void storeMin() {
      min_value = analogRead(_pin);
      supla_log(LOG_DEBUG, "save min CSM value %d", min_value);
      EEPROM.put(eep_ofset, min_value);
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
      EEPROM.commit();
#endif
  }
  void storeMax() {
      max_value = analogRead(_pin);
      supla_log(LOG_DEBUG, "save max CSM value %d", max_value);
      EEPROM.put(eep_ofset + 5, max_value);
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
      EEPROM.commit();
#endif
  }  

    protected:
      int8_t _pin;
      int eep_ofset;
      int min_value;
      int max_value;
      int lastValidTemp;
};
};  // namespace Sensor
};  // namespace Supla

#endif

Ejemplo básico:

Código: Seleccionar todo

#include <EEPROM.h>
#include <SuplaDevice.h>
#include <supla/sensor/CSM.h>


// ESP8266 based board:
 #include <supla/network/esp_wifi.h>
 Supla::ESPWifi wifi("your_wifi_ssid", "your_wifi_password");

Supla::Sensor::CSM *CSM1 = nullptr;

 
void setup() {

  Serial.begin(115200);
  EEPROM.begin(1024);
  
  // Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
  char GUID[SUPLA_GUID_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

  // Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

  /*
    this uses a temperature and humidity channel
    temperature shows analog sensor reading
    humidity shows humidity between 0% and 100%
    needs calibration for a correct reading! "storeMin()" + "storeMax()"
   */
    
  CSM1 = new Supla::Sensor::CSM(A0,100); // A0 = analog pin where the sensor is connected -- 100 = eeprom offset where to save "offset + 10"

  /*
   * SuplaDevice Initialization.
   * Server address is available at https://cloud.supla.org 
   * If you do not have an account, you can create it at https://cloud.supla.org/account/create
   * SUPLA and SUPLA CLOUD are free of charge
   * 
   */

  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    "svr1.supla.org",  // SUPLA server address
                    "email@address",   // Email address used to login to Supla Cloud
                    AUTHKEY);          // Authorization key
    
}

void loop() {
  SuplaDevice.iterate();

  delay(25); // For ESP8266 to have time for WiFi, improve stability.

// call to calibrate and store the sensor value for minimum humidity 0% "exposed to air"
  //CSM1->storeMin();

// call to calibrate and store the sensor value for maximum humidity 100% "in a glass of water"    
  //CSM1->storeMax(); 
 

  
}
edm
Mensajes: 439
Registrado: Lun Ene 15, 2018 6:18 pm

Puedo solicitar un enlace, por ejemplo, aliexpress al sensor de humedad del suelo apropiado, que coincida con este proyecto.
Wziąłem udział w Supla Offline Party 2023 :D
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Después de detectar un error que podía llevar a un bucle de reinicio si por accidente se memorizaban los mismos valores para mínimo y máximo he corregido CSM.h y el firmware compilado. :oops:
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Solución fácil para hacer el sensor impermeable:
Sumergir en esmalte sintético. :lol: :lol: :lol:
frontal.jpg
frontal.jpg (40.02 KiB) Visto 4361 veces
trasera.jpg
trasera.jpg (49.25 KiB) Visto 4361 veces
edm
Mensajes: 439
Registrado: Lun Ene 15, 2018 6:18 pm

¡Bravo tú!
Wziąłem udział w Supla Offline Party 2023 :D
Avatar de Usuario
QLQ
Mensajes: 2276
Registrado: Dom Sep 03, 2017 9:13 am
Ubicación: Koszalin

elmaya escribió: Sab Nov 14, 2020 9:12 am Para quien esté interesado en probar el sensor capacitivo de humedad del suelo
Utilizamos un canal de temperatura y humedad.
La temperatura muestra la lectura del sensor analógico "Esto no es necesario pero no hay canal independiente para humedad así que lo usamos" muestra un valor alrededor de 700 en seco (0%) y de alrededor de 250 estando dentro de un vaso de agua (100%).
La humedad muestra la humedad del suelo entre 0% y 100%.
¡Necesita calibración para una lectura correcta!
Hay un canal separado en Supla, que se usa solo para mostrar la humedad:

en la antigua biblioteca SD:

Código: Seleccionar todo

} else if ( channel->Type == SUPLA_CHANNELTYPE_HUMIDITYSENSOR && Params.cb.get_humidity != NULL ){
        pin->last_val_dbl1 = Params.cb.get_humidity(channel_number, pin->last_val_dbl1);
        channelSetDoubleValue(channel_number, pin->last_val_dbl1);

....
bool SuplaDeviceClass::addHumiditySensor(void) {
    
    int c = addChannel(0, 0, false, false);
    if ( c == -1 ) return false; 
	
    Params.reg_dev.channels[c].Type = SUPLA_CHANNELTYPE_HUMIDITYSENSOR;
    channel_pin[c].last_val_dbl1 = -1;
    channelSetDoubleValue(c, channel_pin[c].last_val_dbl1);
    
}
...void SuplaDeviceClass::setHumidityCallback(_cb_arduino_get_double get_humidity) {
    Params.cb.get_humidity = get_humidity;
}
Tengo estos sensores y estaré encantado de probarlos.
Screenshot_20210328-184414_SUPLA .jpg
Screenshot_20210328-184414_SUPLA .jpg (29.95 KiB) Visto 3867 veces
jak coś nie działa to włącz zasilanie.....
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Actualizado a canal de humedad.

Código Arduino:

Código: Seleccionar todo

#define supla_lib_config_h_  // silences debug messages
#include "LittleFS.h" // LittleFS is declared 
#include <WiFiManager.h>
#include <ArduinoJson.h> //--------- V6 ------ 
#include <EEPROM.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266TrueRandom.h>
#include <Button3.h>
#include <SuplaDevice.h> 
#include <supla/sensor/hygro_meter.h>
  #include <supla/network/esp_wifi.h>
  Supla::ESPWifi wifi("ssid", "pass");

extern "C"
{
#include "user_interface.h"
}

//#define D0 16  //no internal pullup resistor
//#define D1  5
//#define D2  4
//#define D3  0  //must not be pulled low during power on/reset, toggles value during boot
//#define D4  2  //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15  //must not be pulled high during power on/reset

#define status_led 2   // D4
#define wificonfig_pin 0  // D3  WiFiconfig 

char Supla_server[81]=("Unknown server address");
char Email[81]=("Unknown email address");                        
char Supla_name[51];
char Supla_status[51];
char Router_SSID[32];
char Router_Pass[64]; 
int C_W_state = HIGH; 
int last_C_W_state = HIGH;
unsigned long time_last_C_W_change = 0; 
long C_W_delay = 10000;                      // config delay 10 seconds        
bool shouldSaveConfig = false;
bool initialConfig = false; 
char GUID[SUPLA_GUID_SIZE];
char AUTHKEY[SUPLA_AUTHKEY_SIZE];
byte uuidNumber[16];
int s;
bool starting = true; 
Button3 buttonA = Button3(wificonfig_pin);
ESP8266WebServer httpServer(81);
ESP8266HTTPUpdateServer httpUpdater;
WiFiManager wifiManager;

class CSM: public Supla::Sensor::HygroMeter {
  public:
    CSM(int pin, int eepAdresse) {
    _pin = pin;
    eep_ofset = eepAdresse;
    }

    double getHumi() {
      int _value = analogRead(_pin);
      int value = map(_value, max_value, min_value, 100,0);
      value = constrain(value, 0, 100);
      return value; 
    }

    void onInit() {
      EEPROM.get(eep_ofset,min_value);
      if ((min_value < 0) || (min_value >1023)) min_value = 1023;
      supla_log(LOG_DEBUG, "load min CSM value %d", min_value);
      EEPROM.get(eep_ofset + 5,max_value);
      if ((max_value < 0) || (max_value >1023)) max_value = 0;
      supla_log(LOG_DEBUG, "load max CSM value %d", max_value);
      channel.setNewValue(TEMPERATURE_NOT_AVAILABLE, getHumi());
    }

  void storeMin() {
    min_value = analogRead(_pin);
    supla_log(LOG_DEBUG, "save min CSM value %d", min_value);
    EEPROM.put(eep_ofset, min_value);
    EEPROM.commit();
  }
  void storeMax() {
    max_value = analogRead(_pin);
    supla_log(LOG_DEBUG, "save max CSM value %d", max_value);
    EEPROM.put(eep_ofset + 5, max_value);
    EEPROM.commit();
  }  

    protected:
      int8_t _pin;
      int eep_ofset;
      int min_value;
      int max_value;

};

CSM *CSM1 = nullptr;

void saveConfigCallback () {          
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
 digitalWrite(status_led, LOW);
   WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 81,"required");
   WiFiManagerParameter custom_Email("email", "Email", Email, 81,"required");
   WiFiManagerParameter custom_Supla_name("name", "Supla Device Name", Supla_name, 51,"required");
   WiFiManagerParameter custom_Supla_status("status", "Supla Last State", Supla_status, 51,"readonly");

   wifiManager.setBreakAfterConfig(true);
   wifiManager.setSaveConfigCallback(saveConfigCallback);
  
   wifiManager.addParameter(&custom_Supla_server);
   wifiManager.addParameter(&custom_Email);
   wifiManager.addParameter(&custom_Supla_name);
   wifiManager.addParameter(&custom_Supla_status);

   wifiManager.setCustomHeadElement("<style>html{ background-color: #01DF3A;}</style><div class='s'><svg version='1.1' id='l' x='0' y='0' viewBox='0 0 200 200' xml:space='preserve'><path d='M59.3,2.5c18.1,0.6,31.8,8,40.2,23.5c3.1,5.7,4.3,11.9,4.1,18.3c-0.1,3.6-0.7,7.1-1.9,10.6c-0.2,0.7-0.1,1.1,0.6,1.5c12.8,7.7,25.5,15.4,38.3,23c2.9,1.7,5.8,3.4,8.7,5.3c1,0.6,1.6,0.6,2.5-0.1c4.5-3.6,9.8-5.3,15.7-5.4c12.5-0.1,22.9,7.9,25.2,19c1.9,9.2-2.9,19.2-11.8,23.9c-8.4,4.5-16.9,4.5-25.5,0.2c-0.7-0.3-1-0.2-1.5,0.3c-4.8,4.9-9.7,9.8-14.5,14.6c-5.3,5.3-10.6,10.7-15.9,16c-1.8,1.8-3.6,3.7-5.4,5.4c-0.7,0.6-0.6,1,0,1.6c3.6,3.4,5.8,7.5,6.2,12.2c0.7,7.7-2.2,14-8.8,18.5c-12.3,8.6-30.3,3.5-35-10.4c-2.8-8.4,0.6-17.7,8.6-22.8c0.9-0.6,1.1-1,0.8-2c-2-6.2-4.4-12.4-6.6-18.6c-6.3-17.6-12.7-35.1-19-52.7c-0.2-0.7-0.5-1-1.4-0.9c-12.5,0.7-23.6-2.6-33-10.4c-8-6.6-12.9-15-14.2-25c-1.5-11.5,1.7-21.9,9.6-30.7C32.5,8.9,42.2,4.2,53.7,2.7c0.7-0.1,1.5-0.2,2.2-0.2C57,2.4,58.2,2.5,59.3,2.5z M76.5,81c0,0.1,0.1,0.3,0.1,0.6c1.6,6.3,3.2,12.6,4.7,18.9c4.5,17.7,8.9,35.5,13.3,53.2c0.2,0.9,0.6,1.1,1.6,0.9c5.4-1.2,10.7-0.8,15.7,1.6c0.8,0.4,1.2,0.3,1.7-0.4c11.2-12.9,22.5-25.7,33.4-38.7c0.5-0.6,0.4-1,0-1.6c-5.6-7.9-6.1-16.1-1.3-24.5c0.5-0.8,0.3-1.1-0.5-1.6c-9.1-4.7-18.1-9.3-27.2-14c-6.8-3.5-13.5-7-20.3-10.5c-0.7-0.4-1.1-0.3-1.6,0.4c-1.3,1.8-2.7,3.5-4.3,5.1c-4.2,4.2-9.1,7.4-14.7,9.7C76.9,80.3,76.4,80.3,76.5,81z M89,42.6c0.1-2.5-0.4-5.4-1.5-8.1C83,23.1,74.2,16.9,61.7,15.8c-10-0.9-18.6,2.4-25.3,9.7c-8.4,9-9.3,22.4-2.2,32.4c6.8,9.6,19.1,14.2,31.4,11.9C79.2,67.1,89,55.9,89,42.6z M102.1,188.6c0.6,0.1,1.5-0.1,2.4-0.2c9.5-1.4,15.3-10.9,11.6-19.2c-2.6-5.9-9.4-9.6-16.8-8.6c-8.3,1.2-14.1,8.9-12.4,16.6C88.2,183.9,94.4,188.6,102.1,188.6z M167.7,88.5c-1,0-2.1,0.1-3.1,0.3c-9,1.7-14.2,10.6-10.8,18.6c2.9,6.8,11.4,10.3,19,7.8c7.1-2.3,11.1-9.1,9.6-15.9C180.9,93,174.8,88.5,167.7,88.5z'/></svg>");
   wifiManager.setMinimumSignalQuality(8);
   //wifiManager.setShowStaticFields(true); // force show static ip fields
   //wifiManager.setShowDnsFields(true);    // force show dns field always
   wifiManager.setConfigPortalTimeout(180);

   if (!wifiManager.startConfigPortal("CSM_Probe")) { Serial.println("Not connected to WiFi but continuing anyway.");} else { Serial.println("connected...yeey :)");}                
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Email, custom_Email.getValue());
    strcpy(Supla_name, custom_Supla_name.getValue());
    wifiManager.getWiFiSSID().toCharArray(Router_SSID, 33);
    wifiManager.getWiFiPass().toCharArray(Router_Pass, 65); 
    if(strcmp(Supla_server, "get_new_guid_and_authkey") == 0){
      Serial.println("new guid & authkey.");
      EEPROM.write(300, 0);
      EEPROM.commit();
      ESP.reset(); 
    }
    WiFi.softAPdisconnect(true);   //  close AP
}
void status_func(int status, const char *msg) {    //    ------------------------ Status --------------------------
  if (s != status){
    s = status; 
      if (s != 10){
        strcpy(Supla_status, msg); 
  }  }            
}
void guid_authkey(void) {
  if (EEPROM.read(300) != 60){
    int eep_gui = 301;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString += "0123456789abcdef"[topDigit];
      uuidString += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid = uuidString.length();
    for (int i = 0; i < length_uuid; ++i) {
      EEPROM.put(eep_gui + i, uuidString[i]);
    }

    int eep_aut = 341;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString2 = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString2 += "0123456789abcdef"[topDigit];
      uuidString2 += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid2 = uuidString2.length();
    for (int i = 0; i < length_uuid2; ++i) {
      EEPROM.put(eep_aut + i, uuidString2[i]);
    }
    EEPROM.write(300, 60);
    EEPROM.commit();
  }
  read_guid();
  read_authkey();
  Serial.print("GUID : ");Serial.println(read_guid()); 
  Serial.print("AUTHKEY : ");Serial.println(read_authkey()); 
}

String read_guid(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 301;
  int end_guid = eep_star + SUPLA_GUID_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_guid + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_guid = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      GUID[ii] = strtoul( _guid, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}
String read_authkey(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 341;
  int end_authkey = eep_star + SUPLA_AUTHKEY_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_authkey + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_authkey = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      AUTHKEY[ii] = strtoul( _authkey, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}

void setup() {

   wifi_set_sleep_type(NONE_SLEEP_T); 
    
  Serial.begin(115200);  
  pinMode(wificonfig_pin, INPUT_PULLUP);
  pinMode(status_led,OUTPUT); 
  digitalWrite(status_led, HIGH);  
  
  EEPROM.begin(1024);
  if (EEPROM.read(300) != 60){initialConfig = true;} 
  guid_authkey();

  if (WiFi.SSID()==""){ initialConfig = true;} 

  buttonA.setClickHandler(click);
  buttonA.setDoubleClickHandler(doubleClick);
  buttonA.setTripleClickHandler(tripleClick);

  if (LittleFS.begin()) {  // ------------------------- wificonfig read -----------------
    Serial.println("mounted file system");
    if (LittleFS.exists("/config.json")) {
      Serial.println("reading config file");
       File configFile = LittleFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
         size_t size = configFile.size();
         std::unique_ptr<char[]> buf(new char[size]);
         configFile.readBytes(buf.get(), size);
        DynamicJsonDocument json(1024);
        DeserializationError deserializeError = deserializeJson(json, buf.get());
        serializeJsonPretty(json, Serial);
        if (!deserializeError) {Serial.println("\nparsed json");         
          if (json.containsKey("Supla_server")) strcpy(Supla_server, json["Supla_server"]);
          if (json.containsKey("Email")) strcpy(Email, json["Email"]);
          if (json.containsKey("Supla_name")) strcpy(Supla_name, json["Supla_name"]);
          if (json.containsKey("Router_SSID")) strcpy(Router_SSID, json["Router_SSID"]);
          if (json.containsKey("Router_Pass")) strcpy(Router_Pass, json["Router_Pass"]);       
        } else {
          Serial.println("failed to load json config");
           initialConfig = true;
        }
        configFile.close(); 
      }
    }
   } else {
    Serial.println("failed to mount FS");
  }
   wifi_station_set_hostname(Supla_name);
   
  WiFi.mode(WIFI_STA); 

  SuplaDevice.setStatusFuncImpl(&status_func);
  wifi.setSsid(Router_SSID);
  wifi.setPassword(Router_Pass);
  SuplaDevice.setName(Supla_name);
  wifi.enableSSL(false);  
  CSM1 = new CSM(A0,100);

     SuplaDevice.begin(GUID,Supla_server,Email,AUTHKEY);
        
}

void loop() {
   if (initialConfig == true){ondemandwifiCallback();}

   int C_W_read = digitalRead(wificonfig_pin);{  
   if (C_W_read != last_C_W_state) {            
     time_last_C_W_change = millis();
   }
   if ((millis() - time_last_C_W_change) > C_W_delay) {     
     if (C_W_read != C_W_state) {     
       C_W_state = C_W_read;       
       if (C_W_state == LOW) {
        ondemandwifiCallback () ;
       }
     }
    }
   last_C_W_state = C_W_read;            
 }
  
  if (shouldSaveConfig == true) { // ------------------------ wificonfig save --------------
    Serial.println(" config...");  
    DynamicJsonDocument json(1024);
    json["Supla_server"] = Supla_server;
    json["Email"] = Email;
    json["Supla_name"] = Supla_name;
    json["Router_SSID"] = Router_SSID;
    json["Router_Pass"] = Router_Pass;
    File configFile = LittleFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }
        serializeJsonPretty(json, Serial);
        serializeJson(json, configFile);
    configFile.close();
    Serial.println("Config written successfully");
    shouldSaveConfig = false;
    initialConfig = false; 
    WiFi.mode(WIFI_STA);   
    delay(5000);
    ESP.restart();     
  }
  
   buttonA.loop();     
   SuplaDevice.iterate();
   delay(25);

   if (WiFi.status() == WL_CONNECTED){
    if (starting){
      httpUpdater.setup(&httpServer, "/update", "admin", "pass");
      httpServer.begin(); 
      starting = false;         
     }
    httpServer.handleClient();
   }
}

void click(Button3& btn) {

}
void doubleClick(Button3& btn) {
  CSM1->storeMax();
  digitalWrite(status_led, HIGH); 
  delay(100);
  digitalWrite(status_led, LOW); 
  delay(100);
  digitalWrite(status_led, HIGH); 
  delay(100);
  digitalWrite(status_led, LOW); 
  delay(50);
  digitalWrite(status_led, HIGH); 
}
void tripleClick(Button3& btn) {
  CSM1->storeMin();
  digitalWrite(status_led, HIGH); 
  delay(100);
  digitalWrite(status_led, LOW); 
  delay(100);
  digitalWrite(status_led, HIGH); 
  delay(100);
  digitalWrite(status_led, LOW); 
  delay(100);
  digitalWrite(status_led, HIGH); 
  delay(100);
  digitalWrite(status_led, LOW); 
  delay(50);
  digitalWrite(status_led, HIGH);  
}
void longClick(Button3& btn) {

}

Para agregar el canal de humedad es necesario añadir “hygro_meter.h” y “hygro_meter.cpp” al la librería Supla en: “libraries\supla-arduino-master\src\supla\sensor”.

hygro_meter.h

Código: Seleccionar todo

#ifndef _hygro_meter_h
#define _hygro_meter_h

#include "thermometer.h"

#define HUMIDITY_NOT_AVAILABLE -1

namespace Supla {
namespace Sensor {
class HygroMeter : public Thermometer {
 public:
  HygroMeter();
  virtual double getHumi();
  void iterateAlways();

};

};  // namespace Sensor
};  // namespace Supla

#endif
higro_meter.cpp

Código: Seleccionar todo

#include "hygro_meter.h"

Supla::Sensor::HygroMeter::HygroMeter() {
  channel.setType(SUPLA_CHANNELTYPE_HUMIDITYSENSOR);
  channel.setDefault(SUPLA_CHANNELFNC_HUMIDITY);
}

double Supla::Sensor::HygroMeter::getHumi() {
  return HUMIDITY_NOT_AVAILABLE;
}

void Supla::Sensor::HygroMeter::iterateAlways() {
  if (millis() - lastReadTime > 10000) {
    lastReadTime = millis();
    channel.setNewValue(TEMPERATURE_NOT_AVAILABLE, getHumi());
  }
}

Adjunto archivo .bin, .ino y todas las librerías necesarias.

CapSoilMoisture_Humidity_B.rar
(1.02 MiB) Descargado 377 veces
Responder

Volver a “Ideas y conceptos”