Relé y sensor inalámbrico con un ESP32

Las Piezas

Puedes construir el termostato usando solo un ESP32 para controlar tanto el sensor de temperatura/humedad como el telé. El diagrama fritzing para este caso es el siguiente:

 

An ESP32 with a DHT sensor and a relay

 

Esp32 relay and dht sensor
Esp32 relay and dht sensor

El sketch

El sketch es un hibrido de los dos sketchs ya vistos. Despues de instalarlo en el microcontrolador ESP32 con ayuda del Arduino IDE, puedes actuar sobre el relé, u obtener la información de la temperatura y humedad con una sola llamada.

Por ejemplo:

  • http://192.168.2.15: devuelve un objeto json con el estado actual del relé, y los valores de humedad y temperatura.
  • http://192.168.2.15/H: activa el relé y devuelve el mismo objeto json que la llamada anterior.
  • http://192.168.2.15/L: desactiva el relé y devuelve el mismo objeto json que la llamada anterior.

Puedes averiguar la ip de tu ESP32 consultando la consola serie del Arduino IDE justo después de subir el sketch.

Importante: este sketch utiliza la librería “DHTStable” de Rob Tillaart, que funciona mejor que la librería estándar. Por favor, descárgala y añadela a tu Arduino IDE antes de compilar el sketch.

/*
   Smart Pi Thermostat by Roque Campos
   Sketch to read temperatures with an ESP32 board and a DHTxx sensor, and to control a Relay connected to the Pin 21
   Complete Project Details https://www.smart-thermostat.eu
*/

#include 
#include 


// Uncomment one of the lines below for whatever DHT sensor type you're using!
#define DHTTYPE 11   // DHT 11
//#define DHTTYPE 22   // DHT 22  (AM2302), AM2321

// Replace with your network credentials
const char* ssid     = "SSID";
const char* password = "Password";
const String nodeName = "nodeName";


//Please don't touch anything below this point unless you know what you are doing.
const String sketchVersion = "2";
const String nodeType = "TH&Relay";
unsigned long lastReceivedRelayCommandMilis;
const unsigned int TIMEOUT_REICEIVED_COMMANDS_MILIS = 1000 * 60 * 2; //Two minutes
String relayError = "";
String thError = "";
WiFiServer server(80);

//The pin for the relay
const int relayPin = 21;

//Onboard led
const int ONBOARD_LED_PIN = 2;

// DHT Sensor
const int DHTPin = 18;


dht DHT;

// Client variables
char linebuf[80];
int charcount = 0;

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



  pinMode(ONBOARD_LED_PIN, OUTPUT);

  //Initialize serial and wait for port to open:
  pinMode(relayPin, OUTPUT);      // set the Relay pin mode

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  setUpWifi();
  lastReceivedRelayCommandMilis = millis();
}

void setUpWifi() {
  //WiFi.config(ip,dns,gateway,subnet);

  // attempt to connect to Wifi network:
  int counter = 0;
  while (WiFi.status() != WL_CONNECTED) {
    WiFi.disconnect();
    WiFi.begin(ssid, password);
    int counter = 0;
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(".");
      counter++;
      if (counter > 10) {
        break;
      }
    }
  }

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

  server.begin();
}

double celsius2Fahrenheit(double celsius)
{
  return celsius * 9 / 5 + 32;
}

void turnRelayOffIfTimeout() {
  unsigned long now = millis();
  long elapsed = now - lastReceivedRelayCommandMilis;
  if (elapsed > TIMEOUT_REICEIVED_COMMANDS_MILIS) {
    digitalWrite(relayPin, LOW);
    relayError = "Thermostat command timeout...";
  }
}

void loop() {

 
   turnRelayOffIfTimeout();
  if (WiFi.status() != WL_CONNECTED) {
    setUpWifi();
  }
  // listen for incoming clients


  WiFiClient client = server.available();
  if (client) {
    digitalWrite(ONBOARD_LED_PIN, HIGH);
    Serial.println("New client");
    memset(linebuf, 0, sizeof(linebuf));
    charcount = 0;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    String currentLine = "";
    while (client.connected()) {

      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        //read char by char HTTP request

        linebuf[charcount] = c;

        if (charcount < sizeof(linebuf) - 1) charcount++;
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply

        if (c == '\n' && currentLineIsBlank) {



          int chk = DHTLIB_OK;
          double humidity = -10000;
          double celsiusTemp = -10000;
          double fahrenheitTemp = -10000;

          if (DHTTYPE == 22) {
            chk = DHT.read22(DHTPin);
          } else {
            chk = DHT.read11(DHTPin);
          }

          if (chk == DHTLIB_OK) {
            thError = "";
            Serial.print("DHT OK,\t");
            celsiusTemp = DHT.temperature;
            fahrenheitTemp = celsius2Fahrenheit(celsiusTemp);
            humidity = DHT.humidity;


          } else {
            switch (chk)
            {
              case DHTLIB_ERROR_CHECKSUM:
                thError = "Checksum error";
                break;
              case DHTLIB_ERROR_TIMEOUT:
                thError = "Timeout error";
                break;

              default:
                thError = "Unknown error";
                break;
            }
            Serial.print(thError);
          }

          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: application/json");
          client.println();
          client.println("{");
          client.println();
          client.println("\"nodeType\":\"" + nodeType + "\",");
          client.println("\"name\":\"" + nodeName + "\",");
          client.println("\"version\":\"" + sketchVersion + "\",");
          client.println("\"relayError\":\"" + relayError + "\",");
          client.println("\"thError\":\"" + thError + "\",");
          client.println("\"mac\":\"" + WiFi.macAddress() + "\",");

          int currentStatus = digitalRead(relayPin);

          String statusAsString = (currentStatus == 1) ? "true" : "false";
          client.print("\"status\":\"" + statusAsString);
          client.println("\",");


          String cc = String(celsiusTemp);
          cc.trim();
          client.print("\"celsius\":\"" + cc);
          client.println("\",");



          String ff = String(fahrenheitTemp);
          ff.trim();
          client.print("\"fahrenheit\":\"" + ff);
          client.println("\",");

          String hh = String(humidity);
          hh.trim();
          client.print("\"humidity\":\"" + hh);
          client.println("\"");

          client.println();
          client.println("}");
          client.println();

          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
          currentLine = "";
          memset(linebuf, 0, sizeof(linebuf));
          charcount = 0;
        } else if (c != '\r') {

          // you've gotten a character on the current line
          currentLineIsBlank = false;
          currentLine += c;      // add it to the end of the currentLine

        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          lastReceivedRelayCommandMilis = millis();
          digitalWrite(relayPin, HIGH);
          relayError = "";
        }
        if (currentLine.endsWith("GET /L")) {
          lastReceivedRelayCommandMilis = millis();
          digitalWrite(relayPin, LOW);
          relayError = "";
        }




      }
    }
    // give the web browser time to receive the data
    delay(250);

    // close the connection:
    client.stop();
    Serial.println("client disconnected");
    digitalWrite(ONBOARD_LED_PIN, LOW);
  }






}