Domotica persianas del hogar

          Se trata de controlar la subida, bajada y parada de persianas eléctricas que funcionan con mando a 433Mhz. El proyecto es emular este mando con un esp8266 y un emisor 433Mhz y poder controlar las persianas vía Web y mejor, con un teléfono por Internet, tanto desde nuestra IP interna como fuera del domicilio si tenemos IP fija o DDNS.
          Lo primero era averiguar las tramas de control de los mandos. Se intentó, con poca fe, con Arduino y la librería rcswitch que suele leer bien mandos de tipo infrarrojos de TV y similares con resultado nulo.


           Lo siguiente fue conectar la salida de un módulo receptor de 433Mhz al osciloscopio donde podía verse perfectamente la trama pero lógicamente con muy difícil lectura de los tiempos de cada cambio lógico. Era el momento de desempolvar un analizador lógico que monté en el 2015 por menos de 5€. Actualmente se vende ya montado por ese precio y con solfware gratuito PulseView.
         Simplemente conectar la salida Data del módulo 433Mhz al canal D0 del analizador y pulsando el mando de la persiana obtendremos una estupenda trama que nos permite medir tiempos y niveles lógicos de cada uno de los comandos Up, Down y Stop..
          En concreto y en esta caso hay un primer pulso de 5,1 Milisegundos + valle de 1,7mSeg y después los unos miden 400microSeg y los ceros 350microSeg. Por supuesto también hay niveles lógicos dobles. Además hay una separación entre tramas de 13mSeg.

          Con estos datos es sencillo recrearlos con un esp8266 y enviarlos a un módulo emisor de 433Mhz.

//Control de dos persianas va web. Joaquín Paredes 2020
//www.jopapa.me
#include <ESP8266WiFi.h>
String tramaComun="110100100100110110110110100110100100100100100100110110110100110100110100100100100100100";
String trama1Up =   "10010011010010010011010010110011";
String trama2Up =   "10011010010010010011010010110011";
String trama1Stop= "10010011010011010011010011011011";
String trama2Stop= "10011010010011010011010011011011";
String trama1Down="10010011010010011011010010010011";
String trama2Down="10011010010010011011010010010011";
int outPin = D2;  //Salida datos
String bit="";
const char* ssid = "Jopapa";
const char* password = "xxxxxxxxxxxxxxxx";

// Configuración de la IP estática.
IPAddress local_IP(192, 168, 1, 105);   //IP fija
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
#define LED4  D4    // LED en terminal 4
String respuesta= "";

WiFiServer server(95);

void setup() {
  Serial.begin(115200);
  pinMode(LED4, OUTPUT);  //Parpadea en cada comando
  WiFi.config(local_IP, gateway, subnet);
  Serial.println();
  Serial.print("Conectando con ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.println("Conectado con WiFi.");
  // Inicio del Servidor web.
  server.begin();
  Serial.println("Servidor web iniciado.");
  pinMode(outPin, OUTPUT);
  digitalWrite(LED4, HIGH);  //Apaga LED esp8266
}

void loop() {
  // Consulta si se ha conectado algún cliente.
  WiFiClient client = server.available();

  if (!client) { return; }          //Espera por un nuevo cliente
  Serial.println("Nuevo cliente.");
  
  // Espera hasta que el cliente envíe datos.
  while(!client.available()){
    delay(1);
  }

  // Lee la información enviada por el cliente.
  String req = client.readStringUntil('\r');
  Serial.println(req);
 
  // Realiza la petición del cliente.
       if (req.indexOf("P1Up") != -1) {
         digitalWrite(LED4, LOW);
         respuesta="Persiana matrimonio subiendo";        
         persiana(trama1Up);        
         digitalWrite(LED4, HIGH);
       }      
       if (req.indexOf("P1Stop") != -1){
         digitalWrite(LED4, LOW); 
         respuesta="Persiana matrimonio parada";         
         persiana(trama1Stop);         
         digitalWrite(LED4, HIGH);
       }
       if (req.indexOf("P1Down") != -1){
        digitalWrite(LED4, LOW); 
        respuesta="Persiana matrimonio bajando";              
        persiana(trama1Down);       
        digitalWrite(LED4, HIGH);
       }
       if (req.indexOf("P2Up") != -1) {
         digitalWrite(LED4, LOW);
         respuesta="Persiana dormitorio subiendo";        
         persiana(trama1Up);        
         digitalWrite(LED4, HIGH);
       }      
       if (req.indexOf("P2Stop") != -1){
         digitalWrite(LED4, LOW); 
         respuesta="Persiana dormitorio parada";         
         persiana(trama1Stop);         
         digitalWrite(LED4, HIGH);
       }
       if (req.indexOf("P2Down") != -1){
        digitalWrite(LED4, LOW); 
        respuesta="Persiana dormitorio bajando";              
        persiana(trama1Down);       
        digitalWrite(LED4, HIGH);
       }      

      

  //////////////////////////////////////////////
  // Página WEB. ////////////////////////////
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("");                  //  Poner Comillas .
  client.println(respuesta);      //  Devuelve respuesta.

  client.flush();
  client.stop();
  Serial.println("Cliente desconectado.");
}


void persiana(String latrama) {     //Función que recibes las tramas
  String tramaT=tramaComun+latrama;
  for(int m=0;m<6;m++){                          //Repite trama 6 veces
    digitalWrite(outPin, HIGH); delay(5);     //Trama de inicio
    digitalWrite(outPin, LOW);  delayMicroseconds(1700);     
    for(int i=0; i<=119; i++){
      bit=tramaT.substring(i,i+1);
      if (bit == "1") {
      digitalWrite(outPin, HIGH);
      delayMicroseconds(350);   
      }else{
        digitalWrite(outPin, LOW);  
        delayMicroseconds(300);
      }
    } 
    delay(13);  //Tiempo entre tramas
    }
}
          En el programa del esp8266 se ven en primer lugar una trama que es común a todos los comandos y después hay otras seis que definen la persiana y su acción particular. Con estos datos se llama a la función persiana() que transmite los datos a través del pin D2 a la entrada data del emisor 433. Este emisor se alimenta de los 5v del propio esp8266 aunque admite perfectamente hasta 12v y tiene una salida de antena para mayor alcance. Las tramas tienen al principio unos y ceros de varios milisegundos que he preferido incluir dentro de la función persianas() y los he quitado de la trama común.

          Ahora podemos abrir nuestro navegador y teclear la IP del montaje, puerto y comando del modo 192.168.1.125:95/P1Up y si todo va bien la persiana 1 subirá. Este método es muy incomodo y la interfaz Web puede mejorarse mucho añadiendo botones para cada comando.

          Yo he preferido hacer una App para el teléfono con App Inventor y he añadido videos de la subida y bajada de las persianas.

          Aunque las persianas no tienen feedback de su posición podemos dejarlas a la altura que queramos con un truco. Grabamos el recorrido completo de cada persiana a controlar y lo incluimos en la aplicación del teléfono. Bajamos la persiana a tope, le damos a subir y arranca el video y damos a stop a la altura deseada ya que el video irá a la misma velocidad que la persiana real. Bueno, también podemos contar segundos pero con el video mola más.


         
          De arriba a abajo: El esp8266 conectado al emisor de 433Mhz, las dos pantallas de programación del App Inventor y video YouTube del sistema. En el App Inventor esta puesta mi IP interna, en caso de acceso desde fuera de casa hay que poner nuestra IP externa o DDNS y configurar puertos en nuestro router.
Menu