Sensor capacitivo de humedad del suelo.

elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

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

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
You do not have the required permissions to view the files attached to this post.
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

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

Código Arduino:

Code: Select all

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

Code: Select all

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

Code: Select all

#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
Posts: 451
Joined: Mon Jan 15, 2018 6:18 pm

Post

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
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

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
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

Solución fácil para hacer el sensor impermeable:
Sumergir en esmalte sintético. :lol: :lol: :lol:
frontal.jpg
trasera.jpg
You do not have the required permissions to view the files attached to this post.
edm
Posts: 451
Joined: Mon Jan 15, 2018 6:18 pm

Post

¡Bravo tú!
Wziąłem udział w Supla Offline Party 2023 :D
User avatar
QLQ
Posts: 2286
Joined: Sun Sep 03, 2017 9:13 am
Location: Koszalin

Post

elmaya wrote: Sat 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:

Code: Select all

} 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
You do not have the required permissions to view the files attached to this post.
jak coś nie działa to włącz zasilanie.....
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

Actualizado a canal de humedad.

Código Arduino:

Code: Select all

#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

Code: Select all

#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

Code: Select all

#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
You do not have the required permissions to view the files attached to this post.

Return to “Ideas y conceptos”