CONTROLAR O MÓDULO SHELLY 1PM COM ESP32!

Não há como negar, os módulos da marca Shelly são ótimos para quem pretende uma domótica de forma fácil e em conta, mas os verdadeiros fãs de eletrónica gostam sempre de mostrar ideias “out-of-the-box”, explorando não só o básico dos seus produtos, como também os desafios mais exigentes! Neste projeto, vamos controlar o módulo Shelly 1PM com a ESP32, capaz de ligar ou desligar o relé e mostrar o consumo em tempo real no display LCD, bem como a tensão aos terminais da saída do mesmo. Vamos começar!

 

  • Material Necessário

Para este projeto, vamos precisar dos seguintes materiais:

Imagem Produto Comprar
ESP32 (NodeMCU)

Shelly 1PM

Display LCD 20×4 I2C

2 Breadboard’s 830 Pinos

Botão de Pressão

Resistência 1K

Fios de Ligação Macho-Macho

Fios de Ligação Macho-Fêmea

  • Montagem do Circuito

Vamos interligar todos os componentes anteriormente mencionados. Começamos por ligar o LCD: o pino 21 liga-se ao pino SDA e o pino 22 ao pino SCL. Usamos o “Vin” e o “GND” da ESP32 para alimentação. De seguida, configuramos o botão em função pull-up resistor e o sinal é enviado para o pino 19.

 

  • Configurar o módulo Shelly

Abrimos a app “Shelly Cloud” no smartphone e adicionamos o mesmo na nossa rede local. Se já tiver um adicionado, basta anotar o IP do mesmo, utilizado posteriormente no código do programa.

  • Arduino IDE

Por último, resta abrir o Arduino IDE, transferir todas as livrarias necessárias para o projeto, selecionar a correta placa microcontroladora, bem como a sua porta série, e colar o código do projeto.

Biblioteca LiquidCrytal_I2C.h
Biblioteca Arduino_JSON.h

Código

/*Código do Sistema de Controlo de Módulos de Automação Shelly
  Possibilidade de controlar o estado da saída do módulo e a sua tensão, bem como monitorar o consumo do equipamento.
  Modelos testados e aprovados:
  ->Shelly Plus 1PM
  DISCLAMER: Restantes módulos podem não funcionar corretamente.
   www.electrofun.pt/blog/controlar-o-modulo-shelly-1pm-com-esp32
   Electrofun@2022 ---> www.electrofun.pt
*/

//Inclusão de livrarias e add-on's
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
#include <LiquidCrystal_I2C.h>

#define pinoBotao 19 //Conectar o botão de pressão em configuração pull-up resistor ao pino GPIO 19

LiquidCrystal_I2C lcd(0x27, 20, 4);

//A preencher pelo utilizador
const char* SSID_WIFI = "SSID";
const char* PASSWORD_WIFI = "PASSWORD";
const char* updateShellyPath = "http://[IP_DO_SHELLY]/rpc/Switch.GetStatus?id=0";
const char* onShellyPath = "http://[IP_DO_SHELLY]/relay/0?turn=on";
const char* offShellyPath = "http://[IP_DO_SHELLY]/relay/0?turn=off";

//Declaração de Variáveis Necessárias
int potenciaInt, tensaoInt;
unsigned long oldTime = 0;
unsigned long delayLCD = 0;
String leituraShelly, estadoReleString;
bool estadoShellyBool, estadoBotao;

void setup() {
  Serial.begin(115200);
  pinMode(pinoBotao, INPUT);
  WiFi.begin(SSID_WIFI, PASSWORD_WIFI);
  Serial.print("A ligar à rede Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Conexão bem sucedida. IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  lcd.init();
  lcd.backlight();
  lcd.setCursor(2, 0);
  lcd.print("Controlo Modulos");
  lcd.setCursor(7, 1);
  lcd.print("Shelly");
  lcd.setCursor(0, 2);
  lcd.print("Com Medicao Consumo");
  lcd.setCursor(1, 3);
  lcd.print("By Electrofun@2022");
  delay(5000);
  lcd.clear();
}

void loop() {
  atualizarDados();
  estadoBotao = digitalRead(pinoBotao);
  if (estadoBotao == 1) {
    delay(500);
    mudarEstadoShelly();
  }
  atualizarLCD();
}

void atualizarDados() {
  if ((millis() - oldTime) > 1000) {
    if (WiFi.status() == WL_CONNECTED) {
      leituraShelly = httpGETRequest(updateShellyPath);
      JSONVar myObject = JSON.parse(leituraShelly);
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
      JSONVar keys = myObject.keys();
      JSONVar estadoReleJSONValue = myObject[keys[2]];
      JSONVar potenciaJSONValue = myObject[keys[3]];
      JSONVar tensaoJSONValue = myObject[keys[4]];
      estadoReleString = JSON.stringify(estadoReleJSONValue);
      if (estadoReleString == "false") {
        estadoShellyBool = false;
      } else if (estadoReleString == "true") {
        estadoShellyBool = true;
      }
      potenciaInt = int(potenciaJSONValue);
      tensaoInt = int(tensaoJSONValue);
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    oldTime = millis();
  }
}

void mudarEstadoShelly() {
  if (estadoReleString == "false") {
    httpGETRequest(onShellyPath);
  } else if (estadoReleString == "true") {
    httpGETRequest(offShellyPath);
  }
}

void atualizarLCD() {
  if (millis() - delayLCD > 2000 || delayLCD == 0) {
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print("Shelly 1PM");
    lcd.setCursor(0, 1);
    lcd.print("Estado: ");
    if (estadoReleString == "false") {
      lcd.print("OFF");
    } else {
      lcd.print("ON");
    }
    lcd.setCursor(0, 2);
    lcd.print("Tensao: ");
    lcd.print(tensaoInt);
    lcd.print('V');
    lcd.setCursor(0, 3);
    lcd.print("Potencia: ");
    lcd.print(potenciaInt);
    lcd.print('W');
    delayLCD = millis();
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
  http.begin(client, serverName);
  int httpResponseCode = http.GET();
  String payload = "{}";
  if (httpResponseCode > 0) {
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  http.end();
  return payload;
}

Não se esqueçam de ver o nosso vídeo sobre este artigo no nosso canal do YouTube:


Para mais projetos, percorram o nosso blog, onde podem encontrar vários artigos interessantes relacionados com eletrónica, robótica e muito mais! Visitem também o nosso site, onde encontram tudo para eletrónica e robótica!