Como controlar as IOs do expansor MCP23017 ligados ao ESP32 pelo home assistant usando protocolo mqtt

Boas a todos. Estou num dilema propositado de querer expandir as portas digitais do ESP32 e conectar na rede via cabo RJ45.

Primeiro instalei o expansor de portas MCP23017 inclusive mais de um (1) (Identificando assim os endereços) e simplesmente funcionou bem com os códigos exemplos da própria biblioteca Adafruit-MCP23017.

Separadamente configurei o shield ENC28J60 para conectar o esp32 à rede usando o cabo. Felismente também consegui por a funcionar.

Por fim quis juntar os códigos para que eu podesse controlar as entradas e saídas (Botões e LEDs) e também pelo home assistant via mqtt. Só conseguí fazer funcionar os botões e LEDs ligados directamente ao ESP32, consigo ligar os LEDs pelos botões assim como pelo home assistant via mqtt.

O problema agora é assionar os LEDs ligados ao expansor de GPIOs. Não accionam por nada. Nem pelo home assistant e nem pelos botões. Os botões conectados aos expansores também não mostram efeito algum as serem pressionados. Era suposto que eu visse pelo monitor serial, da mesma forma como vejo os que estão ligados ao ESP32.

#include <SPI.h>
#include <Wire.h>
#include <Bounce2.h>
#include <EthernetENC.h>
#include <PubSubClient.h>
#include <Adafruit_MCP23X17.h>

// Instanciar objeto mcp
Adafruit_MCP23X17 mcp1;    
Adafruit_MCP23X17 mcp2;


// Definir o endereço MAC e IP para o ENC28J60
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 177);

// //Definir detalhes do MQTT broker
const char* mqtt_server = "192.168.1.29";
const int mqtt_port = 1883;
const char* mqtt_username = "mqtt_user";
const char* mqtt_password = "mqtt_pass";

// Define GPIO pins
const int lampada_varanda = 2;
const int interruptor_varanda = 4;
const int interruptor_sala_de_estar = 0;
const int lampada_sala_de_estar = 0;
int lampada_varandaValue = LOW;
int lampada_sala_de_estarValue = LOW;

EthernetClient ethClient;
PubSubClient client(ethClient);

void callback(char* topic, byte* payload, unsigned int length) {
  // lidar com a mensagem chegou
  String content = "";
  char character;
  for (int num = 0; num < length; num++) {
    character = payload[num];
    content.concat(character);
  }
  Serial.println(topic);
  Serial.println(content); // Mensagens enviadas por ações de botõo são retornadas pelo broker e impressas no monitor serial
  if (content == "1on") {
    lampada_varandaValue = HIGH;
  }

  if (content == "1off") {
    lampada_varandaValue = LOW;
  }

  
  if (content == "2on") {
    lampada_sala_de_estarValue = HIGH;
  }

  if (content == "2off") {
    lampada_sala_de_estarValue = LOW;
  }

    digitalWrite(lampada_varanda, lampada_varandaValue);
    digitalWrite(lampada_sala_de_estar, lampada_sala_de_estarValue);

}
    Bounce bouncer1 = Bounce();
    Bounce bouncer2 = Bounce();
void setup() {
  // Iniciar o Moitor Serial
  Serial.begin(115200);
  Wire.begin();

     // Inicializar as instâncias dos MCP23017
if (!mcp1.begin_I2C(0x20)) {
    Serial.println("Erro ao inicializar o MCP23017 1. Por favor, verifique as conexções.");
    while (1);
  }

  if (!mcp2.begin_I2C(0x21)) {
    Serial.println("Erro ao inicializar o MCP23017 2. Por favor, verifique as conexções.");
    while (1);
  }

  // Setup Ethernet
  Ethernet.begin(mac, ip);

  // Setup MQTT
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  // Setup GPIO
  pinMode(lampada_varanda, OUTPUT);
  pinMode(interruptor_varanda, INPUT_PULLUP);
  digitalWrite(interruptor_varanda, HIGH);
  bouncer1.attach(interruptor_varanda);
  bouncer1.interval(5);

  mcp1.pinMode(interruptor_sala_de_estar, INPUT);
  mcp2.pinMode(lampada_sala_de_estar, OUTPUT);
  digitalWrite(interruptor_sala_de_estar, HIGH);
  bouncer2.attach(interruptor_sala_de_estar);
  bouncer2.interval(5);
}

void loop() {
  // ConnectConectar ao MQTT
  if (!client.connected()) {
    reconnect();
  }

  //Lidando com as mensagens do mqtt broker de novo
  client.loop();

    if (bouncer1.update()) {
    if (bouncer1.read() == HIGH) {
      if (lampada_varandaValue == LOW) {
      lampada_varandaValue = HIGH;
      client.publish("casa/interruptores/varanda", "1on");
      } else {
        lampada_varandaValue = LOW;
        client.publish("casa/interruptores/varanda", "1off");
      }
    }
  }
    if (bouncer2.update()) {
    if (bouncer2.read() == HIGH) {
      if (lampada_sala_de_estarValue == LOW) {
      lampada_sala_de_estarValue = HIGH;
      client.publish("casa/interruptores/sala_estar", "2on");
      } else {
        lampada_sala_de_estarValue = LOW;
        client.publish("casa/interruptores/sala_estar", "2off");
      }
    }
  }

}
void reconnect() {
  // Repetição até se conectar
  while (!client.connected()) {
    Serial.println("Tentando conectar ao servidor MQTT...");

    // Tentativa de conecxão
    if (client.connect("ESP32Client", mqtt_username, mqtt_password)) {
      Serial.println("Conectado");
      // Subcrevendo - se ao tópico (se Necessário)
      client.subscribe("casa/interruptores/#");
    } else {
      Serial.print("Falha ao conectar, rc= ");
      Serial.println(client.state());
      Serial.println("Tentar de novo em 5 segundos");
      // Esperar 5 segundos antes de tentar outra vez
      delay(5000);
    }
  }
}

Se alguém poder dar olhada ao meu código e poder me ajudar a entender onde é que estou falhando. Ë um projecto para automação da minha casa.

Abraços.

Dércio

Na função callback, a variável content e reinicializado a "", logo não tem o conteúdo que pretendes..
Asneiras!

Olhando melhor, não vejo erros óbvios… Já experimentaste usar mesmo esphome com a API nativa? Não sei se suporta essa placa de rede…

Na função callback, a variável content e reinicializado a "", logo não tem o conteúdo que pretendes.. Asneiras!

Funciona assim mesmo em vazio.
O código funciona perfeitamente para os pino do esp32. Já para os dos expansores não funciona nem a pau. O código não dá erro e os expansores estão devidamente conectados pois já experimentei todos códigos exemplos que vem na biblioteca da adafruit, nomeadamente:
[mcp23xxx_blink…]
[mcp23xxx_button…]
[mcp23xxx_combo…]
[ mcp23xxx_interrupt…]

E todos funcionaram como esperado. Mas como quero integrar ao home assistant, estou nesse dilema. Já com o esphome, ainda não tenho muito domínio na codificação.

Desde já obrigado @Sergio_Silva1 pela tua contrubuição.

Eu sublinhei porque eu estava a dizer asneiras!

Verifiquei na tua função que a string vai sendo concatenada!

Não consigo ver em lado nenhum onde escreves o estado high ou low nos MCP… talvez seja por isso?

Interruptor está ligado no pino cero do mcp1 e Lampada está no pino zero do mcp2. segundo a declaração acima.

Na secção acima defini interruptor como entrada e e lampada como saída.
Támbém defini o bouncer ao colocar HIGH do interruptor (ligado ao pino 0 do mcp1) num intervalo de 5ms

E por fim coloquei para se a lampada estiver desligada e o interruptor for ligado, a lampada mude de estado para HIGH e uma mensagem “2on” é publicada no mqtt broker (Instalado no HA). Caso a lampada esteja ligada, ela mude de HIGH para LOW e também publica “2off” no broker. por aí em diante. Pelo menos funciona perfeitamente com a lampada e interruptor da varanda em que os dois estão directamente ligados aos pinos do esp (2 e 4 respectivamente).

Até então estou a um passo meio andado, consegui fazer com que accione a lampada da sala pelo home assistant via mqtt usando o mesmo código. Fiz uma pequena alteração aquo:

e ficou assim:

    digitalWrite(lampada_varanda, lampada_varandaValue);
    mcp2.digitalWrite(lampada_sala_de_estar, lampada_sala_de_estarValue);

O que falta agora é poder acionar pelo interruptor físico, igual como faço com a lampada da varanda que está ligado directo ao ESP32. Obrigado.

Obrigado @Sergio_Silva1 pela tua contribuição. Consegui achar uma solução no forum do arduino.

teria sido mais fácil para ti se tivesses usado o esphome para programar, não estavas dependente de fazer tudo visto que o esphome já tem lá tudo para fazer a integração com o home assistant e com o MCP23017

só estou a falar porque desenvolvi uma board simples para trabalhar a 24V com inputs e outputs, mas infelizmente não achei um sistema fiável para o que pretendia e optei por ir para KNX


Copyright © 2017-2021. Todos os direitos reservados
CPHA.pt - info@cpha.pt


FAQ | Termos de Serviço/Regras | Política de Privacidade