ūüďĎ Controlar garagem com monitoriza√ß√£o do estado do port√£o e temperatura ambiente


(Ricardo Silva) #1

Aqui deixo um projecto que te permite com um nodemcu/wemos uma placa de relé dois par de reed switch e um sensor de temperatura, controlares o portão da tua garagem, como monotorizares o portão sabendo o seu estado e a temperatura ambiente dentro da garagem.

O que é necessário para executares este projecto?

Lista de Material:

  • 1x wemos D1 mini ou Nodemcu
  • 1 rel√© wemos ou uma placa de rel√© (ligado ao interruptor do motor que permite abrir - parar - fechar o port√£o)
  • 1 sensor dht22 (Sensor de temperatura e humidade da garagem)
  • 2 pares de reed switch para saber a posi√ß√£o do port√£o (fechado - abrindo - aberto - fechando - parado)

Nota:

N√£o foram deixados nenhuns links devido a que podem deixar de estar a funcionar, mas este material encontras facilmente em lojas online da china, seja Alixpress, Bangood, dealextreme etc,

Abaixo deixo o código para flashares no teu wemos ou Nodemcu com o software arduino IDE:

Não te esqueças de mudar os teus dados:
Nome da tua Rede como a tua password da rede, Ip do servidor do teu broker mqtt tal como o username e password do broker.

    //#include <Timing.h>
    //MQTT
    #include <PubSubClient.h>
    //ESP
    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    #include <ESP8266mDNS.h>
    #include <ESP8266HTTPUpdateServer.h>
    #include <Bounce2.h> //elimina ruido no bot√£o manual https://github.com/thomasfredericks/Bounce-Arduino-Wiring
    #include "RemoteDebug.h"
    #include <DHT.h>
    #include <Adafruit_Sensor.h>

//aqui é o pin do wemos para o relay do meu portão
#define door1 D1
#define sensor_door1_open D2
#define sensor_door1_close D5
#define DHTPIN D3

//constant
//wifi
const char* ssid = "";
const char* password = "";
#define HOST_NAME "garagem"
#define DHTTYPE DHT22

//mqtt
const char* mqtt_server = "";
const char* mqtt_username = "";
const char* mqtt_password = "";
const char* mqtt_id = mqtt_username;
const int mqtt_port = 1883;

//ha
const char* ha_command_door1 = "ha/garagem/door1/set";
const char* ha_state_door1 = "ha/garagem/door1/status";
const char* ha_availability = "ha/garagem/door1/lwt";
const char* ha_sensor_door1 = "ha/garagem/door1/position";
const char* ha_reboot_esp = "ha/garagem/door1/reboot";
const char* ha_temperature = "ha/garagem/temperature/value";
const char* ha_humidity = "ha/garagem/humidity/value";

//aqui vou ter que ter OPEN CLOSE STOP no que vem o mqtt
const char* payload_open = "OPEN";
const char* payload_close = "CLOSE";
const char* payload_stop = "STOP";
const char* payload_available = "ONLINE";
const char* payload_not_available = "OFFLINE";
const char* ota_estado = "OTA ONLINE";
const char* ota_topico = strcat("ota/",mqtt_username);
const char* reboot_esp = "RESTART";

//outros
const int SERIAL_BAUDRATE = 115200;
const int port_webserver = 80;

//class
ESP8266WebServer httpServer(port_webserver);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient espwifiClient;
PubSubClient client(mqtt_server, mqtt_port,espwifiClient);
RemoteDebug Debug;
DHT dht(DHTPIN, DHTTYPE);

//debouncer para o ruido nos bot√Ķes
Bounce debouncerOpen_door1 = Bounce();
Bounce debouncerClose_door1 = Bounce();

//variaveis
String lastStateNotified_door1 = "NONE";
int door1_laststatesensor_open = 5;
int door1_laststatesensor_close = 5;
bool firststart = true;
int timeSinceLastRead = 0;

void callback(char* topic, byte* payload, unsigned int length) {
	if(!firststart)
	{
		payload[length] = '\0';
		String strTopic = String((char*)topic);
		if(strTopic == ha_command_door1)
		{
			String infomqtt = String((char*)payload);
			if(infomqtt.equals(payload_open))
			{
				Debug.println("vai para o metodo opencover()");
				openCover();
			}else if (infomqtt.equals(payload_close))
			{
				Debug.println("vai para o metodo closecover()");
				closeCover();
			}else if (infomqtt.equals(payload_stop))
			{
				Debug.println("vai para o metodo stopCover()");
				stopCover();
			}   
		}else if(strTopic == ha_reboot_esp){
			Debug.println("ESP Restart");
			ESP.restart();
		}
	}else{
	 firststart = false;
	}
} 

bool checkMqttConnection() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    Debug.println("Attempting MQTT connection...");
	//aqui i false ou true é importante
	// true: volta ao estado anterior mas para a garagem não é util porque tenho o estado pelo sensores
	//no caso de persianas pode ser true para continuar o que estava a fazer
    if (client.connect(mqtt_id, mqtt_username, mqtt_password, ha_availability, 0, true, payload_not_available )) {
		Serial.println("connected");
		Debug.println("connected");
		firststart = true;
		client.publish(ota_topico, ota_estado, true);      
		client.publish(ota_topico, (const char*)"connected", true);
		client.publish(ha_availability, payload_available, true);
		client.subscribe(ha_command_door1);			
		client.subscribe(ha_reboot_esp);			
    } else {
		Serial.print("failed, rc=");
		Debug.print("failed, rc=");
		Serial.print(client.state());
		Debug.print(client.state());
		Serial.println(" try again in 5 seconds");
		Debug.println(" try again in 5 seconds");
		delay(5000);
    }
  }
  return true;
}

void setup_wifi() {
  delay(100);
  //debug
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  //ota add isso
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  int restartesp = 0;
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.print("Connecting to WiFi.." + String(restartesp) + " ");
    restartesp++;
    if(restartesp > 9)
    {
      ESP.restart();
    }
  }
  MDNS.begin(HOST_NAME);
  httpUpdater.setup(&httpServer);
  httpServer.begin();
  MDNS.addService("http", "tcp", port_webserver);
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  
  Serial.begin(SERIAL_BAUDRATE);
  setup_wifi(); 
  //modo debug por telnet
  Debug.begin(HOST_NAME);
  Debug.setResetCmdEnabled(true);
  Debug.showTime(true);
  Debug.showProfiler(true); // Profiler
  //client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  //aqui é para o relay da minha porta. O relay simula o interruptor que faz abrir/stop/fechar	
  digitalWrite(door1, LOW);
  pinMode(door1, OUTPUT);  
  //sensores da minha porta
  //para contornar o problema se o esp8266 aceita 5V ou 3.3, vou por o pin 
  //com saida up e passa a 0 com contacto fechado
  pinMode(sensor_door1_open, INPUT_PULLUP);
  pinMode(sensor_door1_close, INPUT_PULLUP);
  //associar ao debouncer
  debouncerOpen_door1.attach(sensor_door1_open);
  debouncerOpen_door1.interval(5);//DELAY
  debouncerClose_door1.attach(sensor_door1_close);
  debouncerClose_door1.interval(5);//DELAY
	  
}

void openCover(){  
	if(!lastStateNotified_door1.equals(payload_open)){
	  digitalWrite(door1,HIGH);
		delay(400);
		digitalWrite(door1,LOW);
		lastStateNotified_door1 = payload_open;
		Serial.println("OPEN");
		Debug.println("OPEN");
	}  
}

void closeCover(){
	if(!lastStateNotified_door1.equals(payload_close)){
	  digitalWrite(door1,HIGH);
		delay(400);
		digitalWrite(door1,LOW);
		lastStateNotified_door1 = payload_close;
		Serial.println("CLOSE");   
		Debug.println("CLOSE");   
  } 
}

void stopCover(){
	if(!lastStateNotified_door1.equals(payload_stop)){
		 digitalWrite(door1,HIGH);
		delay(400);
		digitalWrite(door1,LOW);
		lastStateNotified_door1 = payload_stop;
		client.publish(ha_state_door1,payload_stop,true);
		client.publish(ha_sensor_door1,"Parada",true);
		Serial.println("STOP");
		Debug.println("STOP");
	}  
}

//permite verificar o estado da porta com os sensores
//assim se a porta for aberta com o comando ou pelo interruptor j√° o sabemos
void check_door1_status() {

	//atualizar estado dos sensores
	debouncerOpen_door1.update();
	debouncerClose_door1.update();
	int currentStateOpen = debouncerOpen_door1.read();
	int currentStateClose = debouncerClose_door1.read();
	
	if(door1_laststatesensor_close == 5 && door1_laststatesensor_open == 5){
		
		door1_laststatesensor_close = currentStateClose;		
		door1_laststatesensor_open = currentStateOpen;	
		Debug.println("Primeiro if para o estado dos sensores");
		
	}else if(currentStateClose != door1_laststatesensor_close && currentStateOpen == door1_laststatesensor_open){
		
		if(currentStateClose == 1 && door1_laststatesensor_close == 0){
			publish_door1_status("Abrindo");
			Serial.println("Abrindo");
			Debug.println("Abrindo");
		}else {
			publish_door1_status("Fechado");
			Serial.println("Fechado");
			Debug.println("Fechado");
		}
		door1_laststatesensor_close = currentStateClose;		
		
	}else if (currentStateClose == door1_laststatesensor_close && currentStateOpen != door1_laststatesensor_open){
		
		if(currentStateOpen == 1 && door1_laststatesensor_open == 0){
			publish_door1_status("Fechando");
			Serial.println("Fechando");
			Debug.println("Fechando");
		}else {
		  publish_door1_status("Aberto");
			Serial.println("Aberto");
			Debug.println("Aberto");
		}
		door1_laststatesensor_open = currentStateOpen;		
		
	}else if (currentStateClose != door1_laststatesensor_close && currentStateOpen != door1_laststatesensor_open){
		
		door1_laststatesensor_close = currentStateClose;
		door1_laststatesensor_open = currentStateOpen;
		publish_door1_status("error");
		Serial.println("Problema nos sensores");
		Debug.println("Problema nos sensores");
	
	}
}

void publish_door1_status(String message)
{
	if(message == "Fechado")	{
		lastStateNotified_door1 = payload_close;
		client.publish(ha_state_door1,payload_close,true);
		client.publish(ha_sensor_door1, "Fechado", true);
	}else if(message == "Aberto"){
		lastStateNotified_door1 = payload_open;
		client.publish(ha_state_door1,payload_open,true);
		client.publish(ha_sensor_door1, "Aberto", true);
	}else if(message == "error"){
		client.publish(ha_sensor_door1, "Problema nos sensores", true);		
	}else if(message == "Fechando"){
		client.publish(ha_sensor_door1,"Fechando",true);
	}else if(message == "Abrindo"){
		client.publish(ha_sensor_door1,"Abrindo",true);
	}
}

void loop() {
  
  if (WiFi.status() == WL_CONNECTED) 
  {
    if (checkMqttConnection())
		{
			httpServer.handleClient();
			client.loop(); 
			check_door1_status();
			Debug.handle();
			//sensor DHT
			// Report every 2 seconds.
			if(timeSinceLastRead > 30000) 
			{
				// Reading temperature or humidity takes about 250 milliseconds!
				// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
				float h = dht.readHumidity();
				// Read temperature as Celsius (the default)
				float t = dht.readTemperature();
				// Check if any reads failed and exit early (to try again).
				if (isnan(h) || isnan(t)) {
					Serial.println("Failed to read from DHT sensor!");
					Debug.println("Failed to read from DHT sensor!");
					timeSinceLastRead = 0;
					return;
				}		
				
				const int VAL_MAX = 16;
				char val[VAL_MAX];
				timeSinceLastRead = 0;
				client.publish(ha_humidity, dtostrf(h, 1, 2, val));
				client.publish(ha_temperature, dtostrf(t, 1, 2, val));
				Debug.printf("Temperature: %s\n", dtostrf(t, 1, 2, val));
				Debug.printf("Humidade: %s\n", dtostrf(h, 1, 2, val));
			}
			delay(100);
			timeSinceLastRead += 100;
    }
  }else{
		Debug.println("ESP Restart");
		ESP.restart();
  }	
}

Com esse codigo tem o estado do port√£o: fechado - abrindo - aberto - fechando - parado + temperatura e humidade + debug do wemos (telnet porta 23)

Do lado do home Assistant no ficheiro configuration.yaml colocas:
cover:

- platform: mqtt
  name: "Garagem"
  command_topic: "ha/garagem/door1/set"
  state_topic: "ha/garagem/door1/status"
  availability_topic: "ha/garagem/door1/lwt"
  qos: 0
  retain: true
  payload_open: "OPEN"
  payload_close: "CLOSE"
  payload_stop: "STOP"
  payload_available: "ONLINE"
  payload_not_available: "OFFLINE"
  state_open: "OPEN"
  state_closed: "CLOSE"
  optimistic: false

sensor:

- platform: mqtt
  state_topic: 'ha/garagem/door1/position'
  name: 'garagem_estado_minhaporta'
  qos: 0
  retain: true

customize:

sensor.garagem_estado_minhaporta:
  friendly_name: Estado
  show_last_changed: true   
  templates:
    icon_color: >
      if (state === 'Fechando' || state === 'Abrindo') return 'yellow'; 
      else if (state === 'Problema nos sensores') return 'red';
      else if (state === 'Parada') return 'orange';
      return 'rgb(54, 95, 140)';
    icon: >
      if (state === 'Fechando') return 'mdi:garage'; 
      else if (state === 'Abrindo') return 'mdi:garage-open';
      else if (state === 'Aberto') return 'mdi:garage-open';
      else if (state === 'Fechado') return 'mdi:garage';
      else if (state === 'Problema nos sensores') return 'mdi:garage-alert';
      else if (state === 'Parada') return 'mdi:garage-alert';

Video:



Automação Portão
Controlar garagem com monitorizacao do estado do portao e temperatura ambiente
(system) #2

Para comentares este tópico clica aqui:


(Rodolfo) #3

Garagem monitorizar