Automação sem IP fixo! Hoje
mostro como, com meu APP Fernando K, disponível para IOS e Android, você acessa
o ESP de duas maneiras: utilizando o socket local e também pela nuvem, via Firebase.
O mais legal deste projeto é que, além de fácil, ele é rápido, com delay muito
reduzido.
Objetivo
Apresentar o aplicativo
Fernando K e suas ferramentas:
·
Conexões:
Socket
(Local)
Firebase
·
Componentes:
Botões
Sliders
Modelo ESP32 utilizado
Nas figuras abaixo temos os modelos
mais comuns de ESP32 atualmente.
O mesmo projeto foi testado
para estes 3 modelos.
Recursos usados
·
ESPWROOM-32 DevKit de 30 pinos
·
Servo Motor
·
Fios
·
Cabo USB para o ESP32
·
Celular Com aplicativo Fernando K
Link para download do Aplicativo
Tela inicial
Menu Options
·
Connection
·
Add Components
·
Screen Components Length
·
Enable/Disable DragButton
·
Save
·
About
·
Getting Buttons
·
Create Buttons
·
Save Buttons
Adicionar nova Conexão
1. Clique
no Botão Menu
2. Clique
em Connection
3. Clique
no botão “+”
Tipos de conexões:
1. Conexão
por Socket.
2. Conexão
por Firebase.
Conexão por Socket
Name: Informe o nome para
identificar sua conexão
Host: Informar o Host da
conexão
Port: Informar a Porta da
conexão
Add: Adiciona uma nova conexão
O valor do Host e da Porta tem
que ser o mesmo valores identificados no ESP
Conexão por Firebase
Para ter uma conexão com o
Firebase, primeiramente é necessário criar uma conta, depois basta criar um
banco de dados dentro do Firebase para obter a “databaseURL” utilizado para
conectar ao aplicativo. Esses passos serão mostrados nos slides posteriores.
Criar banco de dados no Firebase
Primeiro acesse o site do
Firebase. Clique aqui para
acessá-lo.
Clique no botão escrito
“Primeiros Passos”.
Para criar um banco de dados
no Firebase é necessário ter uma conta do Google.
Faça o Login na sua conta e
clique no botão “Seguinte”.
Clique em “Adicionar Projeto”.
Insira um nome para seu
projeto. Aceite os termos e clique em “Criar projeto”.
Após criar, clique em
“</>” ao lado dos ícones do iOS e do Android.
Copie e salve o conteúdo do
“databaseURL” que será utilizado para fazer a conexão entre o aplicativo e o
banco.
Clique em “Database”no lado
esquerdo da tela.
Clique em “Criar banco de
dados”.
Clique em “Criar banco de
dados” na seção Realtime Database.
Selecione a opção “Iniciar no
modo de teste” e depois clique em “Ativar”.
Pronto! O banco de dados está
criado e em funcionamento.
Conectar
Para conectar, clique na
conexão.
Comunicação Aplicativo – ESP
Após estar conectado, é
possível se comunicar com o ESP
independente se a conexão for por Firebase ou Socket.
O Padrão de comunicação
programado no ESP é o nome do comando, seguido por um valor (é possível alterar
o padrão mudando o código do ESP).
Exemplos:
·
LED On
·
LED Off
·
Servo 0
·
Servo 180
A comunicação pode ser feita
através de 3 maneiras:
1. Terminal
2. Botão
3. Slider
Comunicação via Terminal
Digite um *comando no campo de
texto e clique no botão OK.
*Os comandos devem estar
devidamente programados no código fonte do ESP32.
Comunicação clique Botão
O botão é um componente que
facilita a comunicação com o ESP32, pois os comandos são previamente
programados no botão e enviados quando ocorrer um clique.
O botão pode conter mais de um
comando, como um script. Os comandos são separados pela quebra de linha e
enviados em ordem.
Adicionar novo Botão
1. Clique
no Botão Menu
2. Clique
em Add Components
Title: Informe o nome para
identificar o botão
Code: *Informar o script.
Button Color: Cor Botão
Text Color: Cor do nome do
Botão
Add: Adiciona o botão
*O Code pode ser um comando ou
uma lista de comandos (Script).
Após clicar em Add um novo
botão será criado conforme a figura 2.
*A lista de comandos
reservados (como o Wait) está disponível no manual do usuário do aplicativo.
Basta clicar no botão para
executar o script colocado no Code.
Comunicação Slider
O slider é um componente que
facilita a comunicação com o ESP32 quando o valor a ser enviado está dentro de
um intervalo numérico.
Assim, basta arrastar o slider
até o valor desejado e será enviado um comando com o nome do slider seguido do
valor.
Exemplo: Se o nome do slider
for Servo e estiver no valor 180. O comando enviado para o ESP será “Servo
180”.
Adicionar novo Slider
1. Clique
no Botão Menu
2. Clique
em Add Components
3. Clique
em Slider
Title: Informe o nome para
identificar o Slider
Min Value: Valor Mínimo.
Max Value: Valor Máximo.
Slider Color: Cor do Slider.
Maker Slider Color: Cor do
Marcador
Add: Adiciona o slider.
Após clicar em Add um novo
slider será criado conforme a figura 2.
*O nome do Slider será
mandando junto com o valor atual para o ESP como um comando quando sofrer
alteração.
Montagem
Pinout 30 pinos
Pinout 38 pinos
Montagem
Instalação das Bibliotecas
Instalação da Biblioteca Firebase
É necessário instalar a
biblioteca do Firebase para o ESP32. Entre no link clicando aqui.
Clique em “Clone or Download”
e depois “Download ZIP” para baixar o ZIP.
Na IDE do Arduino vá em
Sketch->Incluir Biblioteca->Adicionar biblioteca .ZIP. Navegue até a
pasta que baixou a biblioteca e adicione ela.
Instalação da Biblioteca ArduinoJSON
Na IDE do Arduino vá em
Sketch->Incluir Biblioteca->Gerenciar bibliotecas
Pesquise a biblioteca
ArduinoJSON, selecione a primeira feita por Benoit Blanchon, selecione a versão
5.13.3 e clique em Instalar.
Código
Declarações e variáveis
#include <Arduino.h> //Lib Arduino #include <WiFi.h> // Lib WiFi #include <Wire.h> // Necessário apenas para o Arduino 1.6.5 e posterior #include <SPI.h> // Lib de comunicação SPI #include <vector> // Lib com as funções de vetor (vector) #include <IOXhop_FirebaseESP32.h> //Lib Firebase #define FIREBASE_HOST "https://databaseURL.firebaseio.com" //databaseURL fornecido pelo Firebase para conexão #define FIREBASE_AUTH "" #include "esp_task_wdt.h" const char* ssid = "NomeWiFi"; // Coloque o nome da sua rede wifi aqui const char* password = "SenhaWiFi"; // Coloque a sua senha wifi aqui const IPAddress IP = IPAddress(192,168,3,141); // IP fixo que o ESP utilizará const IPAddress GATEWAY = IPAddress(192,168,3,1); // Gateway const IPAddress SUBNET = IPAddress(255,255,255,0); // Máscara // Google Public DNS represents two IP addresses for IPv4 – 8.8.8.8 and 8.8.4.4 const IPAddress PRIMARY_DNS(8, 8, 8, 8); const IPAddress SECONDARY_DNS(8, 8, 4, 4); const int port = 80; // Porta // Objeto WiFi Server, o ESP será o servidor WiFiServer server(port); // Vetor com os clientes que se conectarão no ESP std::vectorclients; // Task que insere novos clientes (recém conectados) no vector void taskNewClients(void *); // Task que recebe executa comandos dos clientes void handleClients(void *); int LED_BUILTIN = 2; const int freq = 50; const int canal = 0; const int resolucao = 12; const int pinoAtuacao = 13; int ciclo = 200;
Setup
void setup() { // Iniciamos a serial com 115200 de velocidade Serial.begin(115200); pinMode (LED_BUILTIN, OUTPUT); pinMode(pinoAtuacao, OUTPUT); ledcSetup(canal, freq, resolucao); ledcAttachPin(pinoAtuacao, canal); //Iniciamos o valor do servo com 150, que se equivale a 0. ledcWrite(canal, 150); // Iniciamos o servidor (WiFi Server) serverBegin(); // Criamos 3 tasks (mais detalhes no escopo da função) createTasks(); //Inicia a conexão com o Firebase0 Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); //Muda o valor do Servo no firebase para 0. Firebase.setInt("Servo", 0); //Se está o comando é On, ligar o LED. //Callback quando tem alguma alteração no firebase Firebase.stream("/", [](FirebaseStream stream) { //Entra quando o evento que vem do callback é de alteração "put" if (stream.getEvent() == "put") { //Verifica se o nome é o mesmo do Servo. O nome tem que ser igual com o nome no Firebase e no Aplicativo. if (stream.getPath() == "/Servo") { //Muda o valor do Servo de acordo com oque foi recebido e é feito o mapeamento do valor. ledcWrite(canal, map(stream.getDataInt(),0,180,150,450)); } else{ String cmd; cmd=stream.getPath(); cmd.toUpperCase(); Serial.println("Recebido: ["+stream.getPath()+"]"); if(cmd == "/LED"){ cmd= stream.getDataString(); cmd.toUpperCase(); Serial.println("Recebido2: ["+cmd+"]"); if(cmd=="ON"){ digitalWrite(LED_BUILTIN, HIGH); } else{ if(cmd=="OFF"){ digitalWrite(LED_BUILTIN, LOW); } } } } } }); }
Loop
void loop() { // Exibimos o total de clientes conectados showClients(); delay(5000); }
ServerBegin
// Conectamos no WiFi e iniciamos o servidor void serverBegin() { // Iniciamos o WiFi WiFi.begin(ssid, password); Serial.println("Connecting to WiFi"); // Enquanto não estiver conectado exibimos um ponto while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(1000); } // Exibimos na serial Serial.println("OK"); //Configuramos o WiFi com o IP definido anteriormente if (!WiFi.config(IP, GATEWAY, SUBNET, PRIMARY_DNS, SECONDARY_DNS)) { Serial.println("STA Failed to configure"); while(1); } // Printamos o IP (debug) Serial.println(WiFi.localIP()); // Iniciamos o servidor server.begin(port); delay(1000); }
Create Tasks
// Criamos as 2 Tasks void createTasks() { //Criamos a task que insere os novos clientes no vector xTaskCreatePinnedToCore(taskNewClients, "taskNewClients", 10000, NULL, 2, NULL, 1); //Criamos a task que recebe e executa os comandos dos clients conectados xTaskCreatePinnedToCore(handleClients, "handleClients", 10000, NULL, 2, NULL, 1); }
Task 2: Core 0 - taskNewClients
// Task que insere novos clientes conectados no vector void taskNewClients(void *p) { // Objeto WiFiClient que receberá o novo cliente conectado WiFiClient newClient; // Tempo esperado no delay da task (1 ms) TickType_t taskDelay = 1 / portTICK_PERIOD_MS; while(true) { // Se existir um novo client atribuimos para a variável newClient = server.available(); // Se o client for diferente de nulo if(newClient) { // Inserimos no vector clients.push_back(newClient); // Exibimos na serial indicando novo client e a quantidade atual de clients Serial.println("New client! size:"+String(clients.size())); } // Aguardamos 1ms vTaskDelay(taskDelay); } }
Task 3: Core 0 – handleClients
// Função que verifica se um cliente enviou um comando void handleClients(void *p) { // String que receberá o comando String cmd; // Tempo aguardado pela task (1 ms) TickType_t taskDelay = 1 / portTICK_PERIOD_MS; // Loop infinito while(true) { // Atualizamos o vector deixando somente os clientes conectados refreshConnections(); // Percorremos o vector for(int i=0; i<clients.size(); i++) { // Se existir dados a serem lidos if(clients[i].available()) { // Recebemos a String até o '\n' cmd = clients[i].readStringUntil('\n'); // Executamos um comando, enviando por parametro a String cmd, e o client que nos enviou o comando executeCommand(cmd, clients[i]); } // Delay de 1 ms esp_task_wdt_reset(); } // Delay de 1 ms vTaskDelay(taskDelay); } }
refreshConnections (função chamada pela task handleClients)
// Função que verifica se um ou mais clients se desconectaram do server e, se sim, estes clients serão retirados do vector void refreshConnections() { // Flag que indica se pelo menos um client ser desconectou bool flag = false; // Objeto que receberá apenas os clients conectados std::vector<WiFiClient> newVector; // Percorremos o vector for(int i=0; i<clients.size(); i++) { // Verificamos se o client está desconectado if(!clients[i].connected()) { // Exibimos na serial que um cliente se desconectou e a posição em que ele está no vector (debug) Serial.println("Client disconnected! ["+String(i)+"]"); // Desconectamos o client clients[i].stop(); // Setamos a flag como true indicando que o vector foi alterado flag = true; } else newVector.push_back(clients[i]); // Se o client está conectado, adicionamos no newVector } // Se pelo menos um client se desconectou, atribuimos ao vector "clients" os clients de "newVector" if(flag) clients = newVector; }
executeCommand (função chamada pela task handleClients)
// Função que executa um comando de acordo com a String "cmd" void executeCommand(String cmd, WiFiClient client) { // String que guarda a resposta que será enviada para o client String response = ""; // Se a String estiver vazia, abortamos a função if (cmd.equals("")) return; // Exibimos o comando recebido na serial e no Serial.println("Recebido: ["+cmd+"]"); // Deixamos a string toda em maiúsculo cmd.toUpperCase(); //Verifica se o comando é destinado ao Servo if(cmd.indexOf("SERVO")==0) { //Recebe o grau de acordo com o valor após o espaço " " int grau = atoi((cmd.substring(cmd.indexOf(" ")+1).c_str())); //Mapeia o valor recebido para o valor do Servo ciclo = map(grau,0,180,150,450); ledcWrite(canal, ciclo); response = "ok"; } else{ if(cmd.indexOf("LED ON")==0){ digitalWrite(LED_BUILTIN, HIGH); response = "ok"; } else{ if(cmd.indexOf("LED OFF")==0){ digitalWrite(LED_BUILTIN, LOW); response = "ok"; } else{ response = "Invalid Command"; } } } // Enviamos para o client passado por parâmetro e exibimos sucesso ou falha na serial if(client.print(response)>0) Serial.println("Resposta enviada"); else Serial.println("Erro ao enviar resposta"); }
17 Comentários
Bom dia. Essa biblioteca do firebase funciona com Arduino uno R3, no caso eu teria que modifica-lo para usar o módulo ethernet?
ResponderExcluirOlá, você pode entrar no blog http://forum.fernandok.com e colocar sua dúvida lá!
ExcluirAbs
Boa tarde! O app funciona com placas NodeMCU ESP8266?
ResponderExcluirOlá, você pode entrar no blog http://forum.fernandok.com e colocar sua dúvida lá!
ExcluirAbs
Olá Fernando, o app não está salvando as configurações, saiu do app, tem que configurar tudo, ip, firebase, botão e etc. Grato.
ResponderExcluirCorrigido!
ExcluirNão está disponível na App Store da Apple
ResponderExcluirBoa noite,
ResponderExcluirFiz tudo conforme explicado, porém não esta me dando nenhum retorno dos valores modificados.
Bom dia, está funcionando corretamente por scocket, pelo firebase funciona na inicialização apos alguns minutos para de funcionar e so volta apos reset.
ResponderExcluirOlá tem o código fonte do app? Ou algum tutorial para eu desenvolver o meu.
ResponderExcluirNAO CONSIGO NEM SEQUER CONECTAR AO IP...
ResponderExcluiralguem poderia me dar uma ajuda?
Olá,
ResponderExcluirConectei um ESP-12 com Firebase com sucesso.
Não consegui fazer isso com Arduino Mega2560 + Ethernet 5100.
Vi que antes do Firebase ser adquirido pelo Google era possível fazer isso, tem scketches na web.
É possível hoje a conexão Arduino Mega2560 + Ethernet 5100 com Firebase? Tem biblioteca que suporte essa conexão?
ASF
Bom dia. Fiz uma aplicação pelo firebase e esp32 e aproximadamente 10 minutos após ligado, ele trava o duro que tem o watchdog, mas mesmo após alguns Reboot ele volta a travar.
ResponderExcluirOlá FK, eu tentei fazer com o ESP12, não consegui, comprei o (ESP32 Wroon devkit v1) e nao estou conseguindo gravar, aparece a msg de que nao foi possivel compilar o ESP32...qual modelo de placa devo escolher na ide do arduino?!
ResponderExcluirboa noite
ResponderExcluirnão estou conseguindo encontrar o link da biblioteca firebase
poderia enviar por favor
Como foi feito esse app? Fiz no app inventor porém quando envio teste para o firebase ele recebe com \" diferente da forma que o firebase da aula recebe os dados. Assim o ESP 32 não reconhece o comando
ResponderExcluirFernando,
ResponderExcluirVocê tem o fonte do app flutter ?
Pelo menos algumas telas ?