Vídeo deste Projeto no nosso canal do YouTube:
Se num dos últimos artigos deste blog aprendemos a controlar o Shelly 1PM com a ESP32 controlar o Shelly 1PM com a ESP32, ficava pendente o controlo de mais alguns módulos da marca. Neste artigo, vamos, através da nossa placa ESP32, alterar o estado das nossas persianas de casa, podendo fechá-las ou abri-las com um simples clique!

- Material Necessário
Para este projeto, vamos precisar dos seguintes materiais:
| Imagem | Produto | Comprar |
|---|---|---|
![]() |
ESP32 (NodeMCU) | |
![]() |
Shelly 2.5 | |
![]() |
Display LCD 20×4 I2C | |
![]() |
2 Breadboard’s 830 Pinos | |
![]() |
3 Botões de Pressão | |
![]() |
3 Resistências 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 os 3 botões de pressão em configuração pull-up resistor com as respetivas resistências, e os impulsos ligam-se às portas 2, 5 e 19, dos botões de fechar, parar e abrir a persiana, respetivamente.
No que toca ao módulo Shelly, alimentamos o mesmo com o fio fase e neutro, de onde este último derivamos para o neutro do motor de persiana. Ligamos um fio de controlo do motor ao terminal “01” do Shelly e o outro ao terminal “02”.

- 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
Controlo de Persiana
Modelos testados e aprovados:
->Shelly 2.5 (Roller Mode)
DISCLAMER: Restantes módulos podem não funcionar corretamente.
www.electrofun.pt/blog/controlar-persianas-com-o-modulo-shelly-2-5-e-esp32-roller-mode
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 pinoBotaoFechar 2 //Conectar o botão de pressão em configuração pull-up resistor ao pino GPIO 2
#define pinoBotaoParar 5 //Conectar o botão de pressão em configuração pull-up resistor ao pino GPIO 5
#define pinoBotaoAbrir 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";
char* updateShelly25RollerPath = "http://[IP_DO_SHELLY]/roller/0";
char* openShelly25RollerPath = "http://[IP_DO_SHELLY]/roller/0?go=open";
char* closeShelly25RollerPath = "http://[IP_DO_SHELLY]/roller/0?go=close";
char* stopShelly25RollerPath = "http://[IP_DO_SHELLY]/roller/0?go=stop";
char* setRollerModeShelly25RollerPath = "http://[IP_DO_SHELLY]/settings/0?mode=roller";
//Declaração de Variáveis Necessárias
String estadoPersianaString, lastDirPersianaString, leituraShelly;
unsigned long delayLCD = 0;
long oldTime = 0;
void setup() {
Serial.begin(115200);
pinMode(pinoBotaoFechar, INPUT);
pinMode(pinoBotaoParar, INPUT);
pinMode(pinoBotaoAbrir, 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();
httpGETRequest(setRollerModeShelly25RollerPath);
lcd.init();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Controlo Modulo");
lcd.setCursor(5, 1);
lcd.print("Shelly 2.5");
lcd.setCursor(5, 2);
lcd.print("Modo Roller");
lcd.setCursor(1, 3);
lcd.print("By Electrofun@2022");
delay(5000);
lcd.clear();
}
void loop() {
atualizarDados();
atualizarLCD();
mudarEstadoPersiana();
}
void atualizarDados() {
if ((millis() - oldTime) > 1000 || oldTime == 0) {
if (WiFi.status() == WL_CONNECTED) {
leituraShelly = httpGETRequest(updateShelly25RollerPath);
JSONVar myObject = JSON.parse(leituraShelly);
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
JSONVar keys = myObject.keys();
JSONVar estadoPersianaJSONValue = myObject[keys[0]];
JSONVar lastDirPersianaJSONValue = myObject[keys[7]];
estadoPersianaString = JSON.stringify(estadoPersianaJSONValue);
estadoPersianaString = estadoPersianaString.substring(1, 5);
lastDirPersianaString = JSON.stringify(lastDirPersianaJSONValue);
lastDirPersianaString = lastDirPersianaString.substring(1, 5);
Serial.println(estadoPersianaString);
Serial.println(lastDirPersianaString);
}
else {
Serial.println("WiFi Disconnected");
}
oldTime = millis();
}
}
void atualizarLCD() {
if (millis() - delayLCD > 1000 || delayLCD == 0) {
lcd.clear();
lcd.setCursor(7, 0);
lcd.print("STATUS");
lcd.setCursor(2, 2);
lcd.print("Estado Persiana:");
if (estadoPersianaString == "stop" && lastDirPersianaString == "clos") {
lcd.setCursor(6, 3);
lcd.print("Fechada");
} else if (estadoPersianaString == "stop" && lastDirPersianaString == "open") {
lcd.setCursor(7, 3);
lcd.print("Aberta");;
} else if (estadoPersianaString == "open") {
lcd.setCursor(6, 3);
lcd.print("A Abrir");;
} else if (estadoPersianaString == "clos") {
lcd.setCursor(6, 3);
lcd.print("A Fechar");;
}
delayLCD = millis();
}
}
void mudarEstadoPersiana() {
if (digitalRead(pinoBotaoFechar) == 1) { //Fechar
delay(500);
Serial.println("Fechar");
httpGETRequest(closeShelly25RollerPath);
} else if (digitalRead(pinoBotaoParar) == 1) { //Parar
Serial.println("Parar");
delay(500);
httpGETRequest(stopShelly25RollerPath);
} else if (digitalRead(pinoBotaoAbrir) == 1) { //Abrir
Serial.println("Abrir");
delay(500);
httpGETRequest(openShelly25RollerPath);
}
}
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!









