Lendo dados do Google planilhas com ESP - Banco de dados

Lendo dados do Google planilhas com ESP - Banco de dados

No tutorial Banco de dados com Google planilhas com ESP, aprendemos a enviar dados para o Google Planilhas. Entretanto, para fazer justo ao nome "banco de dados", também precisamos recuperar dados da planilha para manipula-los ou até criar comandos de controle pela planilha, que permitirá, por exemplo, ativar atuadores ou ler dados que colocamos na planilha. Dessa forma, neste tutorial iremos aprender como ler os dados do Google Planilhas através de um ESP.

[toc]

Configurações iniciais - Requisitando dados do Google planilhas

O processo necessário para adquirir dados da planilha é quase o mesmo em relação ao método de envio (GET), entretanto para fazer isso, precisamos obter uma chave secreta. Esta chave faz o papel de "senha", para que ninguém consiga ler seus dados sem ela.

Atenção: Há maneiras mais seguras, como restringir o acesso da chave ou usar autenticador. Será mostrado o método mais simples.

Passo 1-) Entre na plataforma de gerenciamento de API's da Google: https://console.developers.google.com/apis , crie um novo projeto e de um nome qualquer.

Este projeto será apenas para "guardar" sua chave com a respectiva API, neste caso, Google planilhas.

Figura 1 - Criando um projeto de API.

 

Passo 2-) Vá em "Credenciais" e crie uma "Chave de API"

Figura 2 - Criando a Chave de API.

 

Figura 3 - Chave de API.

 

Feche a janela e a partir de agora, já temos nossa chave necessária para requisição de dados (e futuramente, altera-los).

 

Passo 3-) Volte para a página inicial do Google APIs, clique em "Biblioteca", selecione "Google Sheets API" e "Ativar"

Figura 4 - Ativando a API.

 

 

 

Terminamos de criar nossa chave e ativa-la, agora podemos manipular qualquer planilha que tenhamos salvo no Google Drive!


Mãos a obra - Lendo o Google planilhas

Componentes necessários

Código do projeto

Atenção: é necessário que você use os dados da sua planilha e faça uma alteração na mesma, explicaremos logo abaixo.

#include <ESP8266WiFi.h>

WiFiClientSecure cl;//Cria um cliente seguro (para ter acesso ao HTTPS)
String textFix = "GET /v4/spreadsheets/12IYuWdV0aJa8mQPhsR5C6AVEwZufyC05wufTrTJsSg/values/";
String key = "?key=IzaSyDmot3XwHfsNhqeuKdINMYxpyFK4cY";//Chave de API
//Essas Strings serao auxiliares, para nao precisar ficar re-escrevendo toda hora


void setup()
{
    Serial.begin(115200);//Inicia a comunicacao serial
    WiFi.mode(WIFI_STA);//Habilita o modo estaçao
    WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na sua rede
    delay(3000);//Espera um tempo para se conectar no WiFi

}

void loop()
{

    if (cl.connect("sheets.googleapis.com", 443) == true)//Tenta se conectar ao servidor do Google APIs na porta 443 (HTTPS)
    {
        String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
        
        toSend += "C2:C4";//Os valores que queremos ler da planilha. Para uma única célula, use algo como "A2"; para ler varios, use algo como "A1:C4".
        toSend += key;//Adicionamos a chave na String
        toSend += " HTTP/1.1";//Completamos o metodo GET para nosso formulario.

        cl.println(toSend);//Enviamos o GET ao servidor-
        cl.println("Host: sheets.googleapis.com");//-
        cl.println();//-
			

        Serial.println("Dado recebido:\n");//Mostra no Serial Monitor todo o pacote recebido.-
        Serial.print(cl.readString());//-
        cl.stop();//Encerramos a conexao com o servidor.
    }
    else
    {
        Serial.println("Erro ao se conectar");
    }
	

    delay(5000);

}

Ajustando o código para sua planilha

Antes de testar, precisamos alterar os dados do código para os seus dados e também compartilhar o link da sua planilha. Sem isso não irá funcionar!

Lembrando: altere apenas os dados destacados, o restante é necessário para funcionamento correto.

Passo 1-) Vá no começo do código e altere a chave (destacada) por sua chave.

Figura 5 - Alterando a Chave de API.

 

Passo 2-) Ainda nesta parte, altere o ID com o da planilha que você deseja obter os dados. Para isso vá em seu Google Drive, entre na planilha e pegue o ID:

Neste caso, vamos pegar a própria planilha criada na primeira parte do material.

configurando o google planilhas - banco de dados

Figura 6 - Alterando o ID da planilha.

 

Se você testar o código, verá que não temos permissão para acessar o banco de dados no Google planilhas. Isso acontece pois nossa "Chave de API" precisa estar com o link público (Qualquer pessoa com o link pode visualizar). Você pode contornar isso usando os Autenticadores ou adicionando Emails confiáveis ao sistema. Usaremos o mais simples para didática e fácil entendimento. Veja a saída do Serial monitor:

Figura 7 - Serial Monitor: Erro de permissão ao acessar o banco de dados no Google Planilhas

 

Passo 3-) Para deixar o link público, vá na sua planilha e siga os passos:

  • 1-) Clique em "Compartilhar" no canto superior direito.
  • 2-) Clique em "Avançado".

 

  • 3-) Clique em "Alterar...".

 

  • 4-) Clique em "Ativado: qualquer pessoa com link" e salve.

Colocando para funcionar

Agora podemos testar e já estará funcionando!

lendo as células do google planilhas - banco de dados com ESP
Figura 8 - Serial Monitor: Resposta de um grupo de células do nosso banco de dados no Google Planilhas

 

Veja que o pedido foi de um grupo de células, neste caso, C2:C4. Isso significa que iremos receber os dados das células C2,C3 e C4 em ordem da respectiva chamada.


Entendendo a fundo

Software

- String auxiliar (textFix)

String textFix = "GET /v4/spreadsheets/12IYuWdV0aJa8mQPhsR5C6AVEwZufyC05wufTrTJsSg/values/";

Basicamente é onde colocamos o ID da nossa planilha, você deve alterar para o ID de sua planilha!

- String auxiliar (key)

String key = "?key=IzaSyDmot3XwHfsNhqeuKdINMYxpyFK4cY";//Chave de API

Esta outra String, é onde atribuímos nossa Chave de API, você deve alterar para sua Chave de API.

- Obtenção dos dados

toSend += "C2:C4";

Aqui fica a grande jogada, onde conseguimos pegar células individuais, ou grupos de células. Vamos a um breve resumo.

Nossa planilha:

Banco de dados no Google Planilhas
Nosso banco de dados no Google Planilhas

 

Célula individual: Imagine que você precisa do valor da célula C2("Vida").

toSend += "C2";

 

Grupo de células: Imagine que você precisa do valor de um grupo de células, neste caso C2, C3 e C4 ("Vida", "De", "Silicio").

toSend += "C2:C4";

 

Podemos ver a resposta do Google ao pedido C2:C4 no Serial Monitor:

Lendo o banco de dados no Google planilhas
Lendo o banco de dados no Google planilhas

 

Você pode estar se perguntando: "Como vou usar essa String cheia de 'lixo' ?"

Este será o desafio de vocês! Futuramente criaremos um tutorial sobre manipulação de Strings. Mas aqui vai uma dica, procure sobre estes comandos em programação:

Com elas, você é capaz de pegar partes e caracteres específicos da String e ainda criar protocolos de mensagens para uma comunicação efetiva.


Desafio

Tente pegar apenas o valor que você queria da planilha. Você irá usar os dois comandos citados acima para "limpar" a String recebida pelo Google e assim tornando-a útil para o uso no microcontrolador.

Fechamento

Agora que você consegue obter valores da planilha, pode usar dados da planilha para algum processamento interno ou criar comandos de controle através da planilha! As possibilidades são muitas e depende de você. Boa sorte.

Referências

  • https://developers.google.com/sheets/guides/concepts
  • https://developers.google.com/sheets/guides/values

Banco de dados com Google planilhas com ESP32 / ESP8266

Banco de dados com Google planilhas - ESP

O Google planilhas é um "Excel online", que te permite criar tabelas e coisas do tipo, online, sem a necessidade de instalar no seu computador. Podemos compartilhar essa tabela para outras pessoas visualizarem ou edita-las. Nesse tutorial aprenderemos como usar o Google Planilhas para criar um banco de dados online, gratuito e simples, visto que não precisamos ter um servidor dedicado à hospedar o serviço. Esta primeira parte será ensinado apenas a enviar os dados usando um ESP.

[toc]

Banco de dados

Banco de dados é um conjunto de dados, normalmente relacionados entre si, como por exemplo: dados de clientes, LOG de temperaturas e coisas similares. Normalmente são dados organizados por colunas e linhas (matriz/tabela) para fácil entendimento por nós.

Poderíamos usar MySQL ou Firebase, que nos permite criar banco de dados de forma eficiente e confiável, entretanto,  é preciso ter um servidor apenas para hospedar seu banco de dados sempre disponível.

Você pode ler mais sobre Banco de dados e o uso do MySQL no tutorial: Arduino e MySQL – Registrando temperatura em um banco de dados usando o Shield Ethernet W5100

O Google planilhas oferece uma solução simples e gratuita para o armazenamento dos dados coletados. Podemos criar essas tabelas em conjunto do Google Forms, para enviar os dados dos nossos sensores, clientes e etc., sem a necessidade de um computador ou servidor pago hospedando o banco de dados, já que a Google se encarrega totalmente do serviço.

Obtendo os recursos necessários

Para usar esse incrível recurso precisaremos de uma conta no Google, e com ela criaremos dois arquivos, um de Planilha e outro Form.

Iremos através do formulário, enviar dados para a planilha (os dados do formulário irão para a planilha).

Passo 1-) Vá ao seu Google Drive e crie uma Planilha.

Passo 2-) Altere o nome da sua planilha para ser de fácil identificação nos próximos passos.

Figura 3 - Alterando o nome da planilha.
Figura 3 - Alterando o nome da planilha.

Passo 3-) Volte no Drive e crie um formulário.

Passo 4-) Altere o titulo do seu formulário para o desejado, e configure as perguntas.

Na planilha, os títulos das perguntas serão as colunas, e as respostas serão as linhas. Usaremos a opção "Resposta curta", que permite adicionar números e textos pequenos.

Passo 5-) Vá em "Respostas", vamos atribuir o formulário à planilha criada anteriormente. Clique nas "três bolinhas", e "Selecionar destino da resposta".

Passo 6-) Selecione a planilha desejada e estará pronto para receber nossos dados.

Agora, nosso formulário esta pronto para receber os dados e automaticamente transmitir para a planilha.

Para testar o formulário, clique no "Olho" ao canto superior direito, para abrir o link do formulário.

Figura 7 - Abrindo o link do formulário.
Figura 7 - Abrindo o link do formulário.

Após digitar o numero e clicar em "Enviar", será mostrado o aviso que a resposta foi registrada.

Figura 8 - Resposta enviada.
Figura 8 - Resposta enviada.

Agora, volte à sua Planilha, e veja que os resultados já estão aparecendo!

A coluna "Carimbo de data/hora" é preenchida automaticamente pelo sistema do Google, poupando imenso trabalho e requisitos do nosso sistema, dispensando até mesmo RTCs. A outra coluna "Numero" é o titulo da nossa pergunta, e a linha é a resposta que inseri.

Figura 9 - Resposta do formulário na planilha.
Figura 9 - Resposta do formulário na planilha.

Agora que aprendemos a utilizar o formulário em conjunto com a planilha, precisamos apenas integrar no Microcontrolador.


Mãos à obra

Componentes necessários

Conheça um pouco mais sobre ESP:

Código do projeto

Atenção: Não copie e cole o código inteiro, precisamos fazer algumas alterações no link utilizado. Será explicado logo abaixo em "Entendendo a fundo".

Caso esteja usando o ESP32, altere as bibliotecas removendo a ESP8266WiFi.h e incluindo as bibliotecas WiFi.h e WiFiClientSecure.h

Alguns usuário relatam erro com as versões mais novas do core esp8266 (quando você instala pelo menu (ferramentas > placa > gerenciar placas). A solução é instalar e usar a versão 2.4.0

// Código Banco de dados com Google planilhas com ESP - Vida de Silício

#include <ESP8266WiFi.h> 
// Alterar a linha anterior por #include <WiFi.h> se estiver usando ESP32
// #include <WiFiClientSecure.h> // Incluir esta biblioteca se estiver usando ESP32

WiFiClientSecure client;//Cria um cliente seguro (para ter acesso ao HTTPS)
String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";
//Essa String sera uma auxiliar contendo o link utilizado pelo GET, para nao precisar ficar re-escrevendo toda hora


void setup()
{
    Serial.begin(115200);//Inicia a comunicacao serial
    WiFi.mode(WIFI_STA);//Habilita o modo estaçao
    WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na rede
    
    delay(2000);//Espera um tempo para se conectar no WiFi

}


void loop()
{
    if (client.connect("docs.google.com", 443) == 1)//Tenta se conectar ao servidor do Google docs na porta 443 (HTTPS)
    {
        String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
        toSend += random(0, 501);//Adicionamos um valor aleatorio
        toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

        client.println(toSend);//Enviamos o GET ao servidor-
        client.println("Host: docs.google.com");//-
        client.println();//-
        client.stop();//Encerramos a conexao com o servidor
        Serial.println("Dados enviados.");//Mostra no monitor que foi enviado
    }
    else
    {
        Serial.println("Erro ao se conectar");//Se nao for possivel conectar no servidor, ira avisar no monitor.
    }

    delay(5000);
}

Colocando para funcionar

Após a editar o código com as suas informações, tudo irá funcionar corretamente. Veja como ficou o nosso, enviando valores aleatórios para nossa planilha a cada ~5 Segundos.


Entendendo a fundo

Precisamos fazer algumas alterações para o funcionamento do sistema com sua planilha. Sem isso, você irá enviar dados para nossa planilha de teste! (hehe)

Passo 1-)  Abra seu formulário (Figura 7).

Passo 2-) Copie todo o link entre "docs.google.com" e "/viewform". Salve isso em algum lugar, já iremos utilizar.

O nosso ficou "/forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ".

Passo 3-)  Clique com o direito no "Input Text Box" e "inspecionar elemento".

Passo 4-) Agora, iremos pegar o nome desse Input Text Box.

O nosso é "entry.717212213".

Agora, devemos alterar esses dois valores no código, pois são os valores da sua planilha, e no código demonstrado de exemplo, foi utilizado nossos dados.

Obs: Altere apenas as partes destacadas, o restante é necessário para o correto funcionamento.

Atualização por contribuição do leitor Anselmo:

Caso tenha dificuldade em encontrar os entry, bastar seguir os seguintes passos:

    1. Clique no formulário com o botão direito do mouse e selecione "Exibir código fonte da pagina" (Ctrl+U);
    2. Agora pesquise pelo nome do campo inserido no formulário usando a ferramenta de pesquisa do navegador (Ctrl+F);
    3. No final do código vai encontra algo parecido com:  FB_PUBLIC_LOAD_DATA_ = [null,[null,[[490158642,"nome do campo",null,0,[[12345678,null,0,null,[[1,9,[""];
    4. O entry vai ser o numero após o colchete “12345678”,
    5. Inclua "entry." antes do número, fincando “entry.12345678”;
    6. Se você tiver outros campos, os outros entry do formulário vão estar na sequencia.

Exemplo: Campo do formulário: Teste var 1

    • Procure por “Teste var” (Ctrl+F);
    • No final do código vai encontra algo parecido com: "teste var 1",null,0,[[278629525,null,0,null,[[1,9,[""]
    • Copie o número após o colchete “278629525”
    • basta agora incluir "entry." antes do número , ficando “entry.278629525”

 

Passo 5-) Vá no começo do código e altere esta parte destacada, pelo que você copiou no item 2.

Esta parte é o "ID/KEY" do seu formulário, cada formulário tem o seu.

Passo 6-) Nessa mesma parte do código, altere essa outra parte destacada, pelo valor copiado no item 4.

Se você tiver mais de uma entrada para dados, a String ficaria por exemplo:

"GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=123&entry.312212717=1234"

Os dados em negrito são os dados que você adicionaria, sendo de sensores, temperatura e etc.

Se você quiser testar com nossa planilha, sinta-se livre. Entretanto, é permitido apenas a visualização. Link da nossa planilha.

Software

- String auxiliar

String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";

Essa String textFix é uma auxiliar para nao precisar ficar reescrevendo toda hora, desde que essa parte é FIXA. O único valor que iremos alterar é após o  igual "=", que será o valor enviado à planilha.

- Função WiFiClient::connect()

if (client.connect("docs.google.com", 443) == 1)

Precisamos antes de enviar o método GET, se conectar no servidor. Essa função se conecta à URL (IP), na porta desejada.

- Corpo restante do GET

String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
toSend += random(0, 501);//Adicionamos um valor aleatorio
toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

client.println(toSend);//Enviamos o GET ao servidor-
client.println("Host: docs.google.com");//-
client.println();//-
client.stop();//Encerramos a conexao com o servidor
Serial.println("Dados enviados.");//Mostra no monitor que foi enviado

Após a conexão com o servidor, adicionamos um valor aleatório na String final à ser enviada, e também terminamos o restante do necessário a ser enviado.


Desafio

Foi demonstrado apenas o envio de uma variável para a planilha, entretanto em qualquer projeto pode ser necessário o envio de diversas. Faça as alterações necessárias, adicionando os novos "Input Text Box" e tente enviar varias variáveis para sua planilha!

Fechamento

Em diversos projetos precisamos enviar dados ou guarda-los para analise, e um banco de dados como SQL pode ser desnecessário, uma vez que precisamos de um servidor para hospedar o banco de dados; com este método é possível facilmente criar seu banco de dados online, compartilhar com amigos e etc.

Na parte 1 foi mostrado apenas o procedimento para envio dos dados, entretanto, podemos precisar pegar valores da tabela para uso. Já a parte 2, você aprenderá como ler os valores da planilha para manipulação de dados ou até criar comandos de controle para o MCU: Lendo dados do Google planilhas com ESP – Banco de dados

Referências

  • https://developers.google.com/sheets/api/guides/values

Comunicação Wireless TCP com ESP (Parte 2)

Comunicação Wireless TCP com ESP

Daremos inicio a segunda parte do nosso material sobre comunicações Wireless. No tutorial anterior, foi abordado sobre o protocolo UDP, que não é orientado à conexão. Desta vez, vamos aprender sobre o protocolo TCP, este por sua vez, é orientado à conexão, que nos garante a entrega de mensagens, ordenação do recebimento/envio, etc. O código aqui apresentado irá funcionar tanto para ESP8266 quanto para o ESP32, já que a diferença é mínima e funciona da mesma forma.

 

[toc]

Protocolo TCP

TCP (Transmission Control Protocol) é um protocolo para transmissão de dados voltado à conexão, ou seja, permite que as maquinas se comuniquem e gerenciem o estado atual da conexão com seus clientes e servidores. Uma característica importante do TCP é seu gerenciamento do status da rede e os dados, com isto, podemos saber se o dado enviado foi realmente entregue ao destinatário, também garante a entrega ordenada das informações sem que haja colisões e perdas inperceptíveis. Muitas aplicações usam o TCP para efetuar suas comunicações, sendo amplamente usado em todo tipo de situação, ao contrario do UDP que por não ser orientado à conexão, pode gerar erros em nossos sistemas.


Mãos à obra

Componentes necessários

Obs: Você pode usar qualquer aplicativo ou programa para transmitir os pacotes TCP. Nós usaremos o primeiro encontrado na Play Store para ser fácil de vocês encontrarem caso queiram usar também. Link do TCP Client na Play Store

Código do projeto

#ifdef ESP8266//Se estiver usando ESP8266, automáticamente irá adicionar as bibliotecas do ESP8266.
#include <ESP8266WiFi.h>
#include <WiFiServer.h>
#elif defined ESP32//Se estiver usando ESP32, fara a mesma operaçao.
#include <WiFi.h>
#endif

WiFiServer sv(555);//Cria o objeto servidor na porta 555
WiFiClient cl;//Cria o objeto cliente.


void setup()
{
    Serial.begin(115200);//Habilita a comm serial.

    WiFi.mode(WIFI_AP);//Define o WiFi como Acess_Point.
    WiFi.softAP("NodeMCU", "");//Cria a rede de Acess_Point.

    sv.begin();//Inicia o servidor TCP na porta declarada no começo.
}

void loop()
{
    tcp();//Funçao que gerencia os pacotes e clientes TCP.
}

void tcp()
{
    if (cl.connected())//Detecta se há clientes conectados no servidor.
    {
        if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos.
        {
            String req = "";
            while (cl.available() > 0)//Armazena cada Byte (letra/char) na String para formar a mensagem recebida.
            {
                char z = cl.read();
                req += z;
            }

            //Mostra a mensagem recebida do cliente no Serial Monitor.
            Serial.print("\nUm cliente enviou uma mensagem");
            Serial.print("\n...IP do cliente: ");
            Serial.print(cl.remoteIP());
            Serial.print("\n...IP do servidor: ");
            Serial.print(WiFi.softAPIP());
            Serial.print("\n...Mensagem do cliente: " + req + "\n");

	    //Envia uma resposta para o cliente
            cl.print("\nO servidor recebeu sua mensagem");
            cl.print("\n...Seu IP: ");
            cl.print(cl.remoteIP());
            cl.print("\n...IP do Servidor: ");
            cl.print(WiFi.softAPIP());
            cl.print("\n...Sua mensagem: " + req + "\n");
			
        }
    }
    else//Se nao houver cliente conectado,
    {
        cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.
        delay(1);
    }
}

Colando para funcionar

Devo lembrar que o IP padrão do ESP em modo Acess_Point é 192.168.4.1

1-) Precisamos nos conectar na rede WiFi criada pelo micro controlador.

2-) Logo, iremos adicionar o servidor com seu IP e PORTA no aplicativo. Lembre-se que você pode usar qualquer aplicativo ou programa de computador para isso.

 

3-) Após incluir os dados do servidor no aplicativo, podemos conectar-se e enviar os dados.

 

 

Obs: Também há dados disponíveis no Serial monitor, que o micro controlador escreveu, olhe como ficou.


Entendendo a fundo

Software

-Função WiFiClient::connected()

if (cl.connected())//Detecta se há clientes conectados no servidor.
{

}

Esta função retorna se há cliente conectado em nosso servidor. Também irá retornar que há clientes até que todos dados sejam lidos do buffer, se não, continuará aparecendo clientes conectados até que todos dados sejam lidos.

-Função WiFiClient::available()

if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos.
{

}

Esta função, retorna a quantidade de bytes disponiveis para a leitura no buffer do cliente. Pode ser usada para detectar se há dados, e também para efetuar a leitura byte a byte do buffer, afim de montar a String final.

-Função WiFiClient::print()

cl.print();

Usada para enviar a String para o cliente. Há várias maneiras de mandar uma informação para o cliente, desde write(), printf() até print() e println().

-Função WiFiServer::available()

cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.

Esta função, obtem um cliente que esta conectado ao servidor e tem dados disponiveis para a leitura. Pode ser entendida a grosso modo que diz ao cliente que há um servidor disponivel para enviar dados.


Desafio

O desafio desta vez, é tentar conectar multiplos clientes ao mesmo tempo em seu servidor. Este código não permite isto, então faça alterações e estude sobre as bibliotecas usadas para permitir multiplas conexões!

Fechamento

Neste tutorial, você aprendeu a efetuar uma troca simples de mensagens entre o Cliente (nosso celular) e o Servidor (ESP), pode ser usada de mesma forma para comunicação entre dois micro controladores. Na parte 3 deste material, aplicaremos as aulas passadas em um aplicativo em Android ou PC para se comunicar com nosso ESP8266/32. Não se esqueça de comentar sobre duvidas, elogios e criticas! Também aceitamos sugestões sobre a terceira parte deste material.

 


conhecendo ESP32

Conhecendo o ESP32

Conhecendo o ESP32

Vamos conhecer mais a respeito do incrível "irmão mais novo" do nosso querido ESP8266, o ESP32. Este novo microcontrolador da Espressif é uma melhoria do seu antecessor, com mais poder de processamento (Triple core), memória e novos recursos, incluindo Bluetooth e sensores de touch capacitivo. Veja abaixo uma lista de características do ESP32.

Figura 1 - NodeMCU 32-S
Figura 1 - NodeMCU 32-S

Características do ESP-WROOM32

  • Processador principal: LX6 32-bit Dual-core, operando 2-240 MHz.
  • Processador secundário: ULP (Ultra Low Power coprocessor) 8MHz e consome 150uA.
  • FLASH: 4MB.
  • RAM: 520kB.
  • GPIO: 34, com 3.3V e 12mA.
  • ADC: 18, com resolução de 12-bit.
  • DAC: 2, com resolução 8-bit.
  • WiFi: 2,4 GHz, 802.11 b/g/n.
  • Bluetooth: Bluetooth Low Energy v4.2 (BLE).
  • Acelerador via hardware para encriptações, hash e afins. (AES, RSA, SHA e ECC).
  • True Random Number Generator (TRGN).
  • 4 Timers de 64-bit.
  • 4 Watchdogs.
  • 10 Sensores de Touch Capacitivo.
  • 1  Sensor de temperatura interno.
  • 1 Sensor de efeito Hall.

O ULP é um processador de baixo consumo que pode ser usado até em Deep Sleep, e com isso, conseguimos acordar o micro controlador das mais diversas formas, como por exemplo dados na Serial, informação de algum sensor ou os próprios sensores de toque capacitivo. Vários erros que aconteciam com o ESP8266 foram corrigidos e/ou melhorados, por exemplo, as tarefas de background, interrupções, yield() e watchdogs. Ainda é cedo para dizer (no momento) se foram corrigidos totalmente ou apenas melhorados para que gerem menos inconvenientes.

Podemos programa-lo de diversas formas, inclusive na Arduino IDE. Porem, a inclusão das funções do ESP32 ainda está atrasada em relação a esp-IDF, há varias funções que ainda não foram portadas para o Core do Arduino, a principal até o momento, é o Bluetooth, que ainda não é possível usufruir corretamente. Se você precisa usar o Bluetooth ou alguma função que ainda não foi incluída à Arduino IDE, sugerimos que use a esp-IDF.

Chega de papo e vamos programar esta belezinha, o nosso novo brinquedo. Iremos usar a Arduino IDE por já estarmos familiarizado com os comandos e funções.


Instalando o ESP32 na Arduino IDE

Instalando o Python no seu computador

Talvez seja necessário a instalação do Python em sua maquina caso ainda não tenha instalado. Se você já programou o ESP8266, provavelmente já tem o Python instalado e não precisara instalar novamente.

- Baixando o instalador do Python

Entre em   ( https://www.python.org/downloads/ )   e Baixe o Python 2.7.XX

- Instalando o Python

Abra o instalador e siga até a terceira tela. Na terceira tela ative a opção "Add Python.exe to Path" clicando em "Will be installed on local hard drive" e termine a instalação.

 

Instalando o Driver (Core) do ESP32 na IDE Arduino

1 - Baixe o ZIP do ESP32, disponível no site do GitHub. ( https://github.com/espressif/arduino-esp32 )

 

2- Extraia os arquivos dentro da pasta Arduino/hardware/espressif/esp32/ , que se encontra em seu HD. Ficara igual o nosso:

 

3- Vá em esp32/tools e execute o arquivo GET.exe . Irá começar o download de novos arquivos e isso pode demorar um pouco. Ao fim, a janela se fechara automaticamente.

 

4- Abra a Arduino IDE, e veja se as placas do ESP32 estão disponíveis para seleção.

 

5- Plugue seu ESP32 no computador e espere a instalação automática do driver CP2102. Alguns usuários relatam que não foi possível a instalação automática, sendo necessário a instalação manualmente do driver CP2102. Após a instalação do driver, selecione a porta COM respectiva do seu ESP32, se estiver em duvida qual seja, desconecte o ESP32 do computador e veja quais portas estão ativas, agora conecte novamente e veja a porta que apareceu.


Mãos à obra

Componentes necessários

Programando

Iremos fazer o primeiro upload para nossa placa com o clássico Blink. O Blink é um código para piscar LEDs de forma bem simples. Na placa NodeMCU há um LED OnBoard que iremos piscar, então não é preciso usar um LED externo. Caso você queira usar um LED externo, não se esqueça de alterar os pinos no código.

Código do projeto

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED onboard como saída.
}

void loop()
{
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Faz o LED piscar (inverte o estado).
    delay(250);//espera 250mS para inverter o estado do LED.
}

Colocando para funcionar

Após o upload do código, nosso micro controlador começara a piscar, veja o nosso:

ESP32


Entendendo a fundo

Software

- Função Setup

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED onboard como saída.
}

A função de Setup do Arduino é feita da mesma forma, ao ligar/resetar o micro controlador, esta função é executada uma unica vez, por isso o nome "setup", referenciando uma função que configure nosso micro controlador. Normalmente as configurações iniciais, como por exemplo definição de pino (Input/Output) só é necessária ser feita uma vez, logo, adicionamos ela ao setup. Diferentemente do Loop, que é aonde nosso código é executado infinitamente.

- Função pinMode

pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED onboard como saída.

A função pinMode(pino, estado) é usada para definir qual o estado de um pino do micro controlador, no caso, iremos controlar um LED, então foi declarado OUTPUT, para que possamos alterar o nivel lógico do pino (LOW ou HIGH).

- Função digitalWrite

digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Faz o LED piscar (inverte o estado).

A função digitalWrite(pino, estado) é usada para "escrever" um valor no pino do micro controlador. Você pode usar LOW e HIGH, para acender ou apagar um LED, ligar ou desligar motores e etc. Também foi usado a função digitalRead(pino) que faz a leitura do atual estado do pino, e após pegar este valor, nós invertemos com a exclamação " ! ", que se encontra antes da função digitalRead(). Fazendo isto, nós sempre iremos alternar o estado do LED, ou seja, se esta ligado, desligamos; e se esta desligado, ligamos.

- Função Delay

delay(250);//espera 250mS para inverter o estado do LED.

A função delay(mS) é usada para adicionar um tempo entre as tarefas. Se ela não for usada, o LED irá piscar muito rapidamente, impossibilitando a visualização. Logo, usamos 250mS para que possamos ver o LED piscando lentamente.


Fechamento

Então chegamos ao fim de mais um tutorial, aprendemos a instalar e dar o primeiro upload neste incrivel micro controlador. Nos proximos tutoriais, iremos ensinar sobre como dividir tarefas entre os 2 processadores, permitindo assim, que você rode 2 códigos ao mesmo tempo.

Você também pode optar por instalar a ESP-IDF, um ambiente completo de desenvolvimento pro ESP32 que suporta todas configurações e features do microcontrolador: https://portal.vidadesilicio.com.br/instalando-esp-idf-no-windows-esp32/

Se houver dúvidas ou sugestões, fique à vontade para comentar!


O que é Watchdog e como usar do ESP8266?

O que é Watchdog e como usar do ESP8266?

Vamos aprender o que é e como usar o Watchdog do ESP8266. O ESP conta com dois Watchdog's, um implementado via software, e outro via hardware (interno), aprenderemos uma utilidade básica para esta incrível ferramenta no mundo dos micro controladores!

Este tutorial exige um conhecimento no mínimo intermediário/avançado sobre programação e hardware!

 

Watchdog

 

[toc]

 

Sobre o Watchdog

Watchdog (traduzindo para cão de guarda) é um dispositivo interno ou externo, separado do clock e processador principal. Sendo assim, caso o micro controlador ou software venha a travar, por ser independente do resto, irá reiniciar o sistema.

O Watchdog é basicamente um "Contador" fora do sistema principal. Quando ele é ativado, é necessário reseta-lo dentro do tempo pré-estabelecido, caso contrario, o Watchdog irá reiniciar completamente o micro controlador ou software em que for implementado.

Imagine que você colocou seu prato de comida no microondas e digitou 15 Segundos para apenas aquecer a comida, e por algum motivo, o microondas trave enquanto o aquecimento esta ligado. Sua comida poderia super-aquecer ou coisa pior. Este travamento poderia ser resolvido com o uso do Watchdog, já que com o sistema travado, não ocorreria o Feed do Watchdog, e assim ocasionaria o reinicio do sistema, preservando sua comida.

Os usos desta ferramenta são gigantescos, já que todo sistema pode travar e gerar terríveis danos. Um motor ligado a um sistema travado, pode gerar perdas em fábricas ou até matar alguém. Watchdog é de suma importância em diversos projetos!

Entretanto, até o Watchdog pode falhar. Nunca confie em um único sistema de segurança, se for preciso, adicione mais formas! O tutorial é apenas uma apresentação da ferramenta, não nos responsabilizamos por nada.

O ESP8266, conta com dois Watchdog's, um via software e outro via hardware. É possível desabilitar o SW WDT (Software Watchdog), mas até o momento não há formas de desabilitar o HW WDT (Hardware Watchdog).

Software Watchdog tem duração de ~3,2 Segundos. Se não for alimentado durante este tempo, irá reiniciar o software do ESP e manterá os estados dos pinos.

Hardware Watchdog tem duração de ~8 Segundos. Se não for alimentado durante este tempo, irá reiniciar completamente o ESP, inclusive mudando os estados dos pinos para o padrão do boot.

 

 

Mais sobre Watchdog's do ESP8266, clique AQUI.


Mãos à obra

Componentes utilizados

Montando o projeto

Para este exemplo, acenderemos o LED_BUILTIN do NodeMCU, este LED OnBoard, está conectado ao pino D4 do NodeMCU.

Led Nodemcu ESP8266

Código do projeto

O código e explicação serão separada por partes, mostrando ambos Watchdog's resetando o ESP, e também como corrigir este problema.

Será duas partes por Watchdog, uma que faz o Watchdog reiniciar o MCU, e outro que faz a alimentação correta e não reiniciando o MCU.

Para entender o que foi repassado com os código, leia a explicação do software logo abaixo!

 

Software Watchdog (Parte 1, sem alimentar):

void setup()
{
   pinMode(D4, OUTPUT);//Define o LED Onboard como saida.
   digitalWrite(D4, 1);//Apaga o LED.
   delay(2000);//Espera 2 segundos para visualizarmos que o ESP foi iniciado.

   for (long x = 0; x < 20; x++)//Ira piscar o LED 10x com intervalo de 250mS.
   {
      digitalWrite(D4, !digitalRead(D4));//Inverte o estado do LED.
      delayMicroseconds(250000);//Espera 250mS
   }

//Após piscar 10x sem erros, irá entrar no loop e o LED começara a piscar
// rapidamente indicando que não ocorreu erros.

//Este código não efetua o FEED do SW WDT dentro do FOR, e ocasionara no 
// reset do ESP, então nunca irá piscar rapidamente, desde que não irá para o loop.
}

void loop()
{
   digitalWrite(D4, !digitalRead(D4));
   delay(50);
}

 

Software Watchdog (Parte 2, alimentando corretamente):

void setup()
{
   pinMode(D4, OUTPUT);//Define o LED Onboard como saida.
   digitalWrite(D4, 1);//Apaga o LED.
   delay(2000);//Espera 2 segundos para visualizarmos que o ESP foi iniciado.

   for (long x = 0; x < 20; x++)//Irá piscar o LED 10x com intervalo de 250mS
   {
      digitalWrite(D4, !digitalRead(D4));//Inverte o estado do LED.
      delayMicroseconds(250000);//Espera 250mS
      yield();//Efetua o feed do SW WDT.
   }

//Após piscar 10x sem erros, irá entrar no loop e o LED começara a piscar
// rapidamente indicando que não ocorreu erros.

//Este código efetua o feed do SW WDT, então logo após as 10 piscadas,
// começara a piscar rapidamente pois entrou no loop.
}

void loop()
{
   digitalWrite(D4, !digitalRead(D4));
   delay(50);
}

 

Hardware Watchdog (parte 1, sem alimentar):

void setup()
{
   pinMode(D4, OUTPUT);//Define o LED Onboard como saida.
   digitalWrite(D4, 1);//Apaga o LED.
   delay(2000);//Espera 2 segundos para visualizarmos que o ESP foi iniciado.
   ESP.wdtDisable();//Desabilita o SW WDT.

   for (long x = 0; x < 20; x++)//Irá piscar o LED 10x com intervalo de 1 Segundo
   {
      digitalWrite(D4, !digitalRead(D4));//Inverte o estado do LED.
      delay(1000);//Espera 1 Segundo.
      yield();
   }


//Após piscar 10x sem erros, irá entrar no loop e o LED começara a piscar
// rapidamente indicando que não ocorreu erros.

//Este código não efetua o FEED do HW WDT dentro do FOR, e ocasionara no
// reset do ESP, então nunca irá piscar rapidamente, desde que não irá para o loop.
}

void loop()
{
   digitalWrite(D4, !digitalRead(D4));
   delay(50);
   ESP.wdtFeed();//Alimenta o HW WDT.
}

 

Hardware Watchdog (parte 2, alimentando corretamente):

void setup()
{
   pinMode(D4, OUTPUT);//Define o LED Onboard como saida.
   digitalWrite(D4, 1);//Apaga o LED.
   delay(2000);//Espera 2 segundos para visualizarmos que o ESP foi iniciado.
   ESP.wdtDisable();//Desabilita o SW WDT. 

   for (long x = 0; x < 20; x++)//Irá piscar o LED 10x com intervalo de 1 Segundo
   {
      digitalWrite(D4, !digitalRead(D4));//Inverte o estado do LED.
      delay(1000);//Espera 1 Segundo.
      yield();
      ESP.wdtFeed();//Alimenta o Watchdog.
   }


//Após piscar 10x sem erros, irá entrar no loop e o LED começara a piscar
// rapidamente indicando que não ocorreu erros.

//Este código efetua o feed do HW WDT, então logo após as 10 piscadas,
// começara a piscar rapidamente pois entrou no loop.
}

void loop()
{
   digitalWrite(D4, !digitalRead(D4));
   delay(50);
   ESP.wdtFeed();//Alimenta o Watchdog.
}

 

Entendendo a fundo

Software

O Feed do Software Watchdog no ESP, é feito em diversas formas, e normalmente não é necessário preciso implementar as funções de Feed. Os 4 principais métodos para efetuar o feed do Software Watchdog no ESP são:

 

delay();

Usando o clássico delay(), automaticamente é feito o Feed do SW WDT, então não é preciso se preocupar. Lembre-se que a função delayMicroseconds() não efetua o feed do SW WDT. Também é possível usar delay(0) para efetuar o feed do SW WDT.

 


yield();

Esta função faz diversos processamentos de background no ESP, inclusive o Feed do SW WDT. Esta função é praticamente o coração do ESP.

 


ESP.wdtFeed();

Esta outra função também alimenta o SW WDT.

 


Término do Loop principal.

Ao termino do loop principal, é feito automaticamente a chamada do yield(), que ocasiona no gerenciamento das tarefas de background do ESP.

 


A ideia do código usado para mostrar no funcionamento do SW WDT, é que pisque o LED lentamente 10x no inicio do código para mostrar que o ESP foi ligado/reiniciado. Logo em seguida após passar pelo setup(), já dentro do loop(), é feito com que o LED pisque mais rapidamente, para permitir a visualização de que o código prosseguiu sem resetar.

Pensado nisto, ao testarmos o código do Software Watchdog (parte 1), percebemos que isto não ocorre, pois como foi dito anteriormente, o SW WDT, tem um tempo de ~3,2 Segundos, e dentro do laço FOR foi usado o delayMicroseconds(250000) que não faz o feed do SW WDT. Logo percebemos que o LED irá piscar 6x totalizando ~3 Segundos, e não 10. Isto ocorre pois não efetuamos o feed do SW WDT antes de acabar o tempo estabelecido, ocasionando o Reset do ESP. Podemos confirmar isto olhando o Serial Monitor, que mostra o Reset do ESP.

 

 

Agora avançando ao Software Watchdog (parte 2), você perceberá que o ESP não é reiniciado, isto pois dentro do laço FOR, colocamos um dos métodos para efetuar o feed do SW WDT, neste caso, o yield(). É possível ver que após o ESP piscar lentamente 10x, ele entra no loop() e começa a piscar rapidamente, mostrando que o código continua fluindo.

Resumo: Até aqui foi mostrado como é feito o feed do software Watchdog. É possível desabilita-lo caso seja necessário, chamando a função ESP.wdtDisable(). Agora vamos ao Hardware Watchdog!

 

Hardware Watchdog

Este HW WDT, não pode ser desabilitado, e tem o tempo de ~8 Segundos para efetuar o Reset ao micro controlador. O feed do HW WDT, é feito unicamente pela função ESP.wdtFeed(). Os outros métodos citados acima não fazem o feed o HW WDT!

A ideia deste código, é a mesma que a anterior. Adicionar um laço FOR para o LED piscar 10x, e após acabar, irá entrar no loop() piscando rapidamente o LED, indicando que não houve Reset.

Testando o código Hardware Watchdog (parte 1), percebe-se que o LED piscou ~4x e após isto, o ESP é resetado por causa que não efetuamos o feed corretamente com a função necessária. Veja que mesmo utilizando dois métodos do SW WDT, (delay e yield), o ESP irá reiniciar. Já que o ESP reseta, não é possível ver o LED piscar rapidamente após entrar no loop().

 

 

Já com o código do Hardware Watchdog (parte 2), podemos ver que o LED pisca 10x lentamente e após isto, começa a piscar rapidamente, indicando que o código não travou no laço FOR. Você deve efetuar o feed do HW WDT pela função própria, não se esqueça!

 

Colocando para funcionar

Mostraremos o funcionamento na prática do SW WDT ligado à um solenoide pequeno. Não é necessário o código, apenas entender que:

Botão da esquerda: Liga ou Desliga o solenoide.

Botão da direita: Gera um travamento no sistema por um loop infinito (While).

 

Ao inicio do código, o solenoide é ativado 2x, indicando o inicio do programa. Podemos perceber que o controle do solenoide funciona perfeitamente, invertendo seu estado atual. Mas após gerar um evento que trava o ESP, o botão de controle do solenoide para de funcionar, isto acontece pois o ESP travou!

Mas logo após ~3 Segundos, o ESP é reiniciado automaticamente pelo Software Watchdog e os controle voltam a funcionar.


Fechamento

Aprender a utilizar esta ferramenta de extrema importância em projetos é quase indispensável se você pretende "seguir carreira" nesse mundo. Um sistema travado por gerar danos grandes nas mais diversas áreas e situações, sempre tome cuidado com a garantia de funcionamento do seu projeto! Dúvidas? Sugestões? Críticas? Comente abaixo!


Protocolo de tempo NTP com ESP

Protocolo de tempo NTP com ESP

É comum que em projetos de automação e robótica seja necessário saber a hora correta, para marcar a hora em que uma ação ocorreu ou até para ativar sensores em certo horário. Vamos aprender a adicionar um RTC (Real Time Clock - Relógio de tempo Real) ao ESP sem precisar de um hardware externo, como por exemplo um DS1307 ou do DS3231. Para isso, usaremos o NTP que só precisa de uma conexão com a internet o que é facilmente resolvido quando o assunto é projetos com ESP e IoT.

 

Sobre o NTP

Do Wikipédia:

O NTP é um protocolo para sincronização dos relógios dos computadores baseado no protocolo UDP sob a porta 123, para sincronização do relógio de um conjunto de computadores em redes de dados com latência variável. O NTP permite manter o relógio de um computador com a hora sempre certa e com grande exatidão.

O NTP serve tanto para atualizar e também manter os horários e datas sincronizadas entre dispositivos. Não há muitas explicações sobre isto, porém caso queira aprender mais sobre o NTP, clique AQUI ou AQUI.

 

 

Digamos que você tem uma rede de sensores, e precisa que eles liguem as 20h da noite, as melhores alternativas para isto, são um RTC externo/interno ou até o NTP caso haja conexão com a internet. Para o exemplo deste tutorial, acenderemos o LED Onboard de acordo com o horário que iremos definir. Com o NTP, também é possível arrumar a data e hora de um RTC externo que esteja errado!

Download da biblioteca NTPClient

Neste GIF, é mostrado o funcionamento do exemplo deste tutorial, no qual o LED foi acionado as 19:23:30.

ESP8266
FIG 1 - Projeto do tutorial - ESP8266

Mãos à obra

Componentes necessários

Montando o projeto

Nesse projeto usaremos apenas a placa NodeMCU. Usaremos o LED que já vem na placa ligado ao Pino D4 para fazer nossa experiência. Também funciona com ESP32.

Código do projeto

Não se esqueça de alterar as credenciais do WiFi e usar o fuso horário correto. Também altere para o horário que desejar, como o tutorial foi feito as 19:23, usamos este valor.

#include <NTPClient.h>//Biblioteca do NTP.
#include <WiFiUDP.h>//Biblioteca do UDP.
#include <ESP8266WiFi.h>//Biblioteca do WiFi.

WiFiUDP udp;//Cria um objeto "UDP".
NTPClient ntp(udp, "a.st1.ntp.br", -3 * 3600, 60000);//Cria um objeto "NTP" com as configurações.

#define led D4//Define o LED ao pino D4.

String hora;//Váriavel que armazenara o horario do NTP.

void setup()
{
   Serial.begin(9600);//Inicia a comunicação serial.

   pinMode(led, OUTPUT);//Define o pino como saida.
   digitalWrite(led, 1);//Apaga o LED.

   WiFi.mode(WIFI_STA);
   WiFi.begin("SUA REDE", "SUA SENHA");//Conecta ao WiFi.
   delay(2000);//Espera a conexão.

   ntp.begin();//Inicia o NTP.
   ntp.forceUpdate();//Força o Update.
}

void loop()
{
   hora = ntp.getFormattedTime();//Armazena na váriavel HORA, o horario atual.
   Serial.println(hora);//Printa a hora já formatada no monitor.

   if (hora == "19:23:30")//Se a hora atual for igual à que definimos, irá acender o led.
   {
      digitalWrite(led, 0);//Acende
   }

   delay(1000);//Espera 1 segundo.
}

Entendendo a fundo

Software

-Declarando o objeto

NTPClient ntp(udp, "a.st1.ntp.br", -3 * 3600, 60000);//Cria um objeto "NTP" com as configurações.

Aqui é criado o objeto NTP com os seguintes parâmetros:

  1. Objeto UDP.
  2. Servidor do NTP, Acesse ESTE link para ver os servidores brasileiros disponíveis.
  3. Fuso horário multiplicado por segundos, apenas altere o fuso horário se for necessário.
  4. intervalo de updates para atualização da hora, é necessário para manter a hora correta. O padrão é 1 Minuto.

 

-Função NTPClient::begin() e forceUpdate()

ntp.begin();//Inicia o NTP.

ntp.forceUpdate();//Força o Update.

Iniciamos o NTP e também forçamos o update para certificar de que a hora esteja certa.

-Salvando a hora atual

hora = ntp.getFormattedTime();//Armazena na váriavel HORA, o horario atual.

Esta função ntp.getFormattedTime() retorna uma string com a hora atual, contendo HH:MM:SS. Salvamos isto na nossa String hora

Também é possível pegar os dados separados ou até o dia. Veja as funções da biblioteca!

-Acionando o LED com a hora

if (hora == "19:23:30")//Se a hora atual for igual à que definimos, irá acender o led.
{
   digitalWrite(led, 0);//Acende
}

Caso a variável que contem a hora atual seja igual à definida, neste caso é 19:23:30, acenderá o LED.


Desafio

O desafio desta vez, é manter o LED aceso entre intervalos de tempo, por exemplo das 13h até as 16h. Para isto, pode-se usar a boa e velha lógica booleana ou a função constrain() do arduino. Boa sorte!

Considerações finais

A implementação deste simples protocolo pode ser de grande ajuda e utilidade em seus projetos que tenham conexão com a Internet. Dúvidas? Sugestões? Críticas? Comente abaixo!


Sleep Modes - Economizando energia- ESP8266

Economizando energia

Atire a primeira pedra quem nunca pensou em fazer algo portátil com o ESP8266. Vamos aprender sobre os diversos modos de Sleep presente no ESP8266, desde o Modem Sleep até o Deep Sleep.

 

Por que Sleep em micro controladores?

Deixar o MCU ligado durante algum tempo ocioso, consome muita bateria desnecessariamente e torna inviável projetos portáteis, já que precisaríamos trocar constantemente a bateria ou pilha. Para isto, existem os Sleep modes, que adormecem certas funções do MCU, permitindo o uso em projetos portáteis.

Modem Sleep

Somente o rádio WiFi/Wireless do MCU é desligado, todo o resto do sistema continua ligado normalmente. É útil quando o envio de informações se faz em intervalos de tempos e que é preciso o funcionamento do sistema em geral, como por exemplo acender LEDs, fazer comunicações e etc. O rádio não fica completamente desligado, de acordo com os datasheet's, o ESP faz um gerenciamento entre os Beacons (DTIM) do seu roteador e desliga entre os intervalos definidos.

Consumo: ~15mA.

 

LightSleep

Rádio WiFi/Wireless e Clock interno são desligados. CPU fica pendente. Com este modo, é possível acordar o CPU com um sinal enviado (HIGH/LOW) para um pino definido no software, continuando seu código normalmente. Como o anterior, este modo também possui o "Automatic sleep", que faz o MCU dormir entre os intervalos do DTIM.

Consumo: ~400 μA.

 

Deep Sleep

Rádio WiFi/Wireless, CPU e CLOCK ficam desligados, Apenas o RTC continua ON. Este modo é o melhor na questão de consumo já que praticamente todo o MCU fica desligado. É útil quando precisamos por exemplo enviar dados de um sensor a cada 5 minutos para um banco de dados ou gravar na EEPROM para futuramente ser enviado caso não haja conexão com a internet.

Consumo: ~20μA.

 

Datasheet sobre os sleeps.

 

Como o foco deste material será a autonomia, será ensinado como é o funcionamento do Deep Sleep, já que tem o menor consumo e é facilmente configurado através do código. Caso você ainda não tenha conhecimento sobre os BOT's do Telegram, veja ESTE tutorial.

Faremos um sensor de luminosidade portátil, que irá detectar o nível de luz no local e enviar por um BOT no Telegram a mensagem para o nosso chat a cada 1 minuto. Entre os intervalos, entrará em Deep Sleep para poupar a bateria.

Este projeto poderá ser feito por qualquer ESP8266, porém é necessário que o GPIO16 (D0) esteja conectado ao RESET. O ESP8266 01 não conta com este pino fisicamente, entretanto, é possível liga-lo ao RESET da seguinte forma:

 

 

Mãos à obra

Componentes necessários

Para este projeto, usaremos novamente o NodeMCU, e também mostraremos o consumo dele durante o Deep-sleep.

 

Montando o projeto

Faça as ligações necessárias para se ler um LDR, conectado ao pino A0. Para o Deep Sleep acordar o MCU após o tempo definido, precisamos ligar o pino D0 ao RST.

 

Código do projeto

Não se esqueça de colocar as informações sobre seu WiFi, ID e TOKEN do Telegram. Ensinamos como pegar o ID no tutorial do Telegram, de uma olhada!

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

#define BOTtoken "1659677:AberDacEJadpENQS_mUTIvLfGQ5f6dQe"//Define o token do BOT.

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

String ldr;

void setup()
{
   WiFi.mode(WIFI_STA);//Define o ESP como Station.
   WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na rede.

   while (WiFi.status() != WL_CONNECTED)//Espera a conexão se estabelecer.
   {
      delay(1);
   }

   ldr += analogRead(A0);//Le o LDR.

   bot.sendSimpleMessage("SEU ID", ldr, "");//Envia o valor do LDR para o chat.

   ESP.deepSleep(1 * 60000000);//Dorme por 1 Minuto (Deep-Sleep em Micro segundos).
}

void loop()
{

}


Entendendo a fundo

Hardware

Para o Deep sleep funcionar corretamente, é preciso fazer a ligação do pino D0 (GPIO16) ao pino de RESET. Quando o RTC estoura o tempo (Overflow), é gerado um pulso LOW ao pino do RESET, fazendo com que o mesmo seja resetado e recomece o código do começo! Por este motivo, o código foi escrito no setup(), já que não foi necessário nenhuma ação dentro do loop(), mas isto não impede de escrever dentro do loop().

Sempre que o o ESP for resetado, ele iniciara o código do começo!

Software

-Função ESP.deepSleep()

ESP.deepSleep(1 * 60000000);//Dorme por 1 Minuto (Deep-Sleep em Micro segundos).

Este comando coloca o MCU em Deep-sleep por 1 Minuto. O valor à ser colocado na função é em Micro Segundos!

Após você usar este comando, o MCU irá dormir até que o tempo se acabe. Quando o tempo definido estourar (Acabar), o RTC irá gerar um pulso LOW ao pino RST, fazendo com que o MCU seja reiniciado completamente. Após o reset, o código irá se iniciar do começo normalmente e só entrara em Sleep novamente, quando chegar a respectiva linha do comando para dormir.

 

Fechamento

Faremos alguns cálculos de autonomia com Sleep.

Após testar este projeto, você pode medir o consumo da corrente no MCU utilizando um multímetro ou algo similar. Usarei um Osciloscópio para medir a tensão em cima de um resistor de 1 Ω, isso significa que os valores lidos da tensão pelo osciloscópio, serão a mesma que a corrente.

 

Para entender o gráfico do osciloscópio de uma maneira simples, primeiro veja que a escala vertical esta com 20mV por divisão, isto significa que a cada divisão vertical, corresponde a 20mV!

Fig 1 - Escala vertical em 20mV.


 

Fig 2 - Explicação do gráfico.


 

Fig 3 - Corrente em modo STA.


 

Como podemos ver, a corrente (FIG 3), está aproximadamente em 80mA quando o ESP8266 esta com o RF ligado. Usando Modem Sleep para desligar o RF, este consumo já iria para ~15mA!

Para medir a corrente quando o ESP8266 entra em Deep Sleep, foi necessário a redução da escala vertical, indo para 5mV (FIG 4) por divisão!, a leitura do gráfico é a mesma que o anterior (FIG 5).

Fig 4 - Escala vertical em 5mV.


Fig 5 - Corrente em Deep sleep.


 

Agora você deve estar se perguntando porque o consumo esta tão alto comparado ao datasheet (20μA). Isto se deve ao fato de que esta placa NodeMCU conta com diversos componentes, como por exemplo regulador de tensão e o conversor FTDI. Estes componentes "roubam" uma preciosa energia quando é ativado o Deep Sleep. Por este motivo, você não deve usar o NodeMCU para projetos portáteis, já que o consumo é muito maior. Para isto, use o ESP8266 01, 12, ou qualquer outro que não venha em uma placa (Kit de Desenvolvimento). Ainda sim, usando o ESP 01, há o LED vermelho que indica se o MCU esta ligado, o consumo não será 20μA enquanto não remover este LED!

 

Usamos ESTA ferramenta para fazer os cálculos, você também pode fazer o calculo de autonomia do seu projeto com ela!

  • Bateria 18650: 3,7V e 4000mAh.
  • NodeMCU: Duração do código = 2 Segundos por 80mA.
  • NodeMCU: Tempo de Sleep = 1 Minuto por 3mA.

 

Chegamos a conclusão que sem Sleep, o NodeMCU ficaria 40 horas ligado até que a bateria se acabe. Já com o Deep sleep, isso é aumentado para 583 horas (24 dias)!!!

Para comparar o Deep Sleep do teste com o "verdadeiro" Deep sleep de um ESP8266 (20μA), também foi feito o cálculo e chegamos a incríveis 1230 horas, o equivalente a 51 dias!

 

Dúvidas? Sugestões? Críticas? Comente abaixo!


Comunicação Wireless UDP com ESP (Parte 1)

Comunicação Wireless UDP com ESP

Neste material, iremos aprender a fazer uma comunicação Wireless UDP entre dois ESP8266 para transmissão de informações. O grande diferencial do ESP é sua comunicação Wireless com suporte a WiFi, então nada mais justo que aprender a usar isto. Lembrando que este código também funciona para o ESP32.

 

[toc]

Protocolo UDP

O protocolo UDP, da camada de transporte, nos permite de forma rápida e descomplicada, o envio de informações através da rede. A simplicidade de usar o UDP é compensada ao fato de não ser uma comunicação orientada à conexão, como por exemplo o TCP, logo, não há garantia que os pacotes sejam recebidos de forma ordenada ou se quer sejam recebidos. Usa-lo para aplicações simples é recomendado, já que não são dados críticos; a perda de pacotes (improvável, porém possa acontecer) não é tão prejudicial ao sistema. Iremos transmitir de um Cliente para um Host.

Esta comunicação simples pode ser feita para transmitir dados até um banco de dados em um computador ou informações para outros Micro controladores. As aplicações são as mais diversas e variadas possíveis, novamente, o limite é sua imaginação.

Lembre-se, serão dois ESP8266, um cliente e outro host. Os dois códigos estarão logo abaixo!

Veja como é rápido o processo de envio e recebimento dos dados. O cliente pisca quando envia o pacote e o host  pisca após receber o pacote, é tão rápido que os dois parecem piscar juntos:

 


Mãos à obra

Componentes necessários

 

Hardware

Acenderemos o LED_BUILTIN do NodeMCU para indicar a transmissão de dados. Este LED OnBoard, está conectado ao pino D4 do NodeMCU.

Código do projeto

Cliente

#include <ESP8266WiFi.h>//Biblioteca do WiFi.
#include <WiFiUdp.h>//Biblioteca do UDP.

WiFiUDP udp;//Cria um objeto da classe UDP.
long x;//Variavel para ser enviada.

void setup()
{
   pinMode(D4, OUTPUT);//Habilita o LED onboard como saida.
   digitalWrite(D4, 1);//Desliga o LED.

   WiFi.mode(WIFI_STA);//Define o ESP8266 como Station.
}

void loop()
{
   connect();//Sub-rotina para conectar-se ao host.

   send();//Sub-rotina para enviar os dados ao host.

   delay(500);//Aguarda meio segundo.
}

void connect()//Sub-rotina para verificar a conexao com o host.
{
   if (WiFi.status() != WL_CONNECTED)//Caso nao esteja conectado ao host, ira se conectar.
   {
      WiFi.begin("NodeMCU", "");//Conecta à rede do host.
      delay(2000);//Espera ate que a conexao seja feita.
   }
}

void send()//Sub-rotina para enviar dados ao host.
{
   if (WiFi.status() == WL_CONNECTED)//Só ira enviar dados se estiver conectado.
   {
      x = random(0, 1000);//Gera um numero aleatorio entre 0 e 1000.
      udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA.
      udp.println(x);//Adiciona-se o valor ao pacote.
      udp.endPacket();//Finaliza o pacote e envia.

      digitalWrite(D4, 0);//-
      delay(5);//-
      digitalWrite(D4, 1);//Pisca o led rapidamente apos enviar.
   }
   else//Caso nao esteja com uma conexao estabelicida ao host, piscara lentamente.
   {
      digitalWrite(D4, 0);
      delay(250);
      digitalWrite(D4, 1);
   }
}

 

Host

#include <ESP8266WiFi.h>//Biblioteca do WiFi.
#include <WiFiUdp.h>//Biblioteca do UDP.

WiFiUDP udp;//Cria um objeto da classe UDP.

String req;//String que armazena os dados recebidos pela rede.

void setup()
{
   pinMode(D4, OUTPUT);//Habilita o LED onboard como saida.
   digitalWrite(D4, 1);//Desliga o LED.

   Serial.begin(115200);//Habilita a comunicaçao serial para a string recebida ser lida no Serial monitor.

   WiFi.mode(WIFI_AP);//Define o ESP8266 como Acess Point.
   WiFi.softAP("NodeMCU", "");//Cria um WiFi de nome "NodeMCU" e sem senha.
   delay(2000);//Aguarda 2 segundos para completar a criaçao do wifi.

   udp.begin(555);//Inicializa a recepçao de dados UDP na porta 555
}

void loop()
{
   listen();//Sub-rotina para verificar a existencia de pacotes UDP.
}

void listen()//Sub-rotina que verifica se há pacotes UDP's para serem lidos.
{
   if (udp.parsePacket() > 0)//Se houver pacotes para serem lidos
   {
       req = "";//Reseta a string para receber uma nova informaçao
       while (udp.available() > 0)//Enquanto houver dados para serem lidos
       {
           char z = udp.read();//Adiciona o byte lido em uma char
           req += z;//Adiciona o char à string
       }

       //Após todos os dados serem lidos, a String estara pronta.

       Serial.println(req);//Printa a string recebida no Serial monitor.

       digitalWrite(D4, 0);//-
       delay(5);//-
       digitalWrite(D4, 1);//Pisca o LED rapidamente apos receber a string.
    }
}

 

Entendendo a fundo

Software

Recomendamos que vocês a leiam esta referência sobre WiFi, praticamente todos comandos disponíveis estão explicados AQUI.

Cliente

 

-Enviando dados para o destino

udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA.
udp.println(x);//Adiciona-se o valor ao pacote.
udp.endPacket();//Finaliza o pacote e envia.

Nesta parte, usamos 3 funções do UDP, entre elas estão:

-Função WiFiUDP::beginPacket()

udp.beginPacket("192.168.4.1", 555);

Estamos enviando o pacote para o IP "192.168.4.1" que é o IP padrão do host no ESP8266, na porta 555.

 

-Função WiFiUDP::println()

udp.println(x);

Adicionamos o valor da variável X ao pacote.

 

-Função WiFiUDP::endPacket()

udp.endPacket();

Por ultimo, fechamos o pacote para finalmente ser enviado ao destino.

 

Para melhor entendimento, veja esta figura:

 

  • Vermelho = beginPacket();
  • Verde = print();
  • Azul = endPacket();

 


Host

 

-Função WiFiUDP::parsePacket()

udp.parsePacket();

Esta função faz a verificação de novos dados no buffer. Se houver dados novos para serem lidos, a função irá retornar um numero maior que zero.


Desafio

O desafio agora é você fazer uma mensagem de retorno para quem enviou uma mensagem ao host, por exemplo, quando o cliente 1 enviar dados ao host, o host responda "OK". Também faça um Print do IP de quem foi recebido o dado. Na referencia do WiFi (citado acima), há os comandos necessários!

 

Finalizando

Com a possibilidade de comunicação entre dispositivos pelo WiFi ou Wireless Ponto-a-Ponto, podemos fazer projetos muito legais e redes de dispositivos para se comunicarem. Não se esqueça de ver a parte 2 do material, sobre TCP! Dúvidas? Sugestões? Críticas? Comente abaixo!


Memória não Volátil EEPROM do ESP8266 - NodeMCU

Memória não Volátil EEPROM do ESP8266

EEPROM é um tipo de memória não volátil presente na maioria dos sistemas e micro controladores, já que quase sempre é preciso guardar dados para que sejam lidos mesmo após a uma queda de energia por exemplo. Nesse tutorial você aprenderá a usar essa memória não volátil do ESP8266 usando o NodeMCU

O principal propósito da EEPROM, é guardar as informações (em Bytes) para que possamos ler a qualquer momento, e caso o sistema venha a reiniciar ou algo do tipo, as informações se manterão intactas

 

Memória não Volátil EEPROM do ESP8266

[toc]

Sobre a EEPROM

EEPROM, é uma memória não volátil, mas tem um limite relativamente pequeno de gravações (no ESP8266). Isto faz com que devemos tomar cuidado para por exemplo, não colocar as funções de gravação em loop's. Normalmente é utilizada para armazenar dados sobre a inicialização do sistema ou algo relacionado que não seja necessário ser alterado com muita frequência.

O ESP8266 não tem EEPROM dedicada, porém, há uma emulação em um segmento da FLASH de 4B até 4096KB. Cada Byte da EEPROM no ESP8266, tem um limite de 10mil gravações e "infinitas" leituras. Sabendo disto, tome cuidado para não extrapolar nas gravações; a leitura é permitida quantas vezes forem necessárias.

 

Alguns exemplos práticos para a EEPROM:

  • Manter a maior temperatura alcançada de um sensor.
  • Guardar variáveis que o usuário inserir após o inicio padrão do sistema também é comumente usado, por exemplo, alocar as novas credenciais do WiFi após o cliente comprar o produto novo.
  • Salvar o último dia em que um motor parou de funcionar para gerar relatórios.

As aplicações da EEPROM são as mais diversas e variadas. Pode estar presente na maioria dos projetos já que é facilmente manipulável.


Mãos à obra - Utilizando a EEPROM do NodeMCU

Componentes utilizados

Software

#include <EEPROM.h>


void setup()
{
   Serial.begin(9600);//Inicia a comunicação Serial.
   Serial.println();//-
   Serial.println();//-Apenas para "limpar" a tela.

   EEPROM.begin(4);//Inicia a EEPROM com tamanho de 4 Bytes (minimo).
   Serial.println(EEPROM.read(0));//Mostra no Monitor oque há antes de efetuar a gravação

   if (EEPROM.read(0) != 18)//Se não existir o numero escolhido (18), irá gravar. Isto é necessário para evitar regravações desnecessárias.
   {
      EEPROM.write(0, 18);//Escreve no endereço "0", o valor "18".
      EEPROM.commit();//Salva o dado na EEPROM.
      Serial.println(EEPROM.read(0));//Mostra o valor no endereço 0 novamente.
   }
   else//Se já existir o valor, irá avisar.
   {
      Serial.println("Dado ja cadastrado");
   }

   EEPROM.end();//Fecha a EEPROM.
}

void loop()
{

}

Entendendo a fundo

Software

-Função EEPROM::begin()

EEPROM.begin(4);

Necessária sempre que for ler ou escrever na EEPROM. O parâmetro é o tamanho de inicialização, que precisa estar entre 4 até 4096. Neste caso, foi iniciado o mínimo possível, 4 Bytes.

 

-Função EEPROM::read()

EEPROM.read(0);

Faz a leitura do endereço desejado, retornando um valor UINT8 (0 até 255). No caso do exemplo do tutorial, usamos o primeiro endereço da EEPROM, que é "0". Você pode escolher qualquer endereço desde que esteja entre o parâmetro usado no begin().

 

-Função EEPROM::write()

EEPROM.write(0, 18);

Escreve no endereço X, o valor Y. No caso do exemplo, escrevemos no endereço "0", um número qualquer, "18". Esta escrita deve ser feita em UINT8 (0 até 255), caso seja necessário valores maiores, precisara usar mais Bytes da EEPROM.

 

-Função EEPROM:commit()

EEPROM.commit();

Esta função salva o que escrevemos anteriormente, sem isto, não irá salvar! Também pode ser feito pelo comando EEPROM.end(), que também efetua o commit().

 

-Função EEPROM::end()

EEPROM.end();

Fecha a EEPROM. Lembre-se que após usar esta função, não é possível escrever ou ler valores da EEPROM!


 

Curiosidades

Ao efetuar um teste que mostra o valor de cada Byte da EEPROM, os 4 primeiros Bytes do meu ESP8266 já estavam com valores modificados. Penso que tenha sido alguma biblioteca externa ou ?.... Teste você mesmo e diga nos comentários se também havia algo alterado!

Código para efetuar a leitura completa da EEPROM:

#include <EEPROM.h>


void setup()
{
   Serial.begin(9600);
   Serial.println();
   Serial.println();

   EEPROM.begin(4096);//Inicia toda a EEPROM.

   for (int i = 0; i < 4097; i++)//Loop que irá mostrar no Serial monitor cada valor da EEPROM.
   {
      Serial.print(EEPROM.read(i));
      Serial.print(" ");
   }

   EEPROM.end();//Fecha a EEPROM.
}

void loop()
{

}

Desafio

O desafio desta vez, é maximizar a eficiência da EEPROM, salvando dados de um sensor apenas quando for maior que o anterior. Assim, estendendo a vida útil dela.

Fechamento

Você aprendeu a usar a EEPROM de micro controladores de um jeito muito fácil. Agora, podemos salvar dados e mante-los mesmo caso a alimentação seja cortada, ou o MCU seja reiniciado. Dúvidas? Sugestões? Críticas? Comente abaixo!


Servidor WEB com ESP - NodeMCU

Servidor WEB com NodeMcu - ESP

Vamos aprender à criar um Servidor WEB usando HTML e TCP/IP em nosso pequeno ESP8266 ou ESP32. Para essa experiência usaremos o NodeMcu, mas daremos as instruções para você fazer o mesmo projeto com o ESP32. Um servidor web é, como o nome sugere, um servidor de informações que serão fornecidas pelo MCU através da internet ou até LAN. Podemos acessar estes dados em computadores, celulares ou outros MCU's, e também enviar informações e instruções para o MCU.

Http servidor web

Aplicação prática

Acionar LEDs, motores, luzes, ventiladores, etc. Você terá uma interface HMI (Interface Homem-Máquina) e com isso, conseguirá manipular seu sistema das mais diversas formas. Ver status de funcionamento de sensores ou atuadores, as possibilidades são muitas, depende de você. Mostraremos apenas o básico, o controle de um LED por botão, porém, após você entender o funcionamento deste sistema, conseguira fazer muitas coisas!

Para este projeto, você verá o básico necessário para implementar com sucesso um acionamento (transmissão de dados SITE->MCU).

TCP

O protocolo TCP/IP (Transmission Control Protocol) é um protocolo para transmissão orientado à conexão, ou seja, permite que as maquinas se comuniquem e gerenciem o estado atual da transmissão.

Uma característica muito importante sobre o TCP é seu gerenciamento do status da rede e os dados, com isto, podemos saber se o dado enviado foi realmente entregue ao destinatário, também garante a entrega ordenada das informações sem que haja colisões e perdas imperceptíveis.

De um jeito mais fácil, TCP será nosso “Caminhão”, que irá levar as informações até o navegador de quem acessar nosso IP.


HTML

HTML é uma linguagem de marcação utilizada em sites da WEB e são interpretadas pelos navegadores (http request). Quando o usuário se conectar ao IP do ESP pelo navegador, o mesmo irá enviar os dados no formato do HTML via TCP e com isso, após o navegador receber os dados, irá mostrar a página web!

Clique aqui para ver mais Informações sobre HTML


Mãos à obra

Componentes necessários

Hardware

Vamos acender o LED_BUILTIN do NodeMCU, este LED OnBoard, está conectado ao pino D4 do NodeMCU.

NodeMcu trabalhando como servidor web

Código do projeto

Não se esqueça de colocar suas credenciais do WiFi na linha 14 para o funcionamento do código!

#include <ESP8266WiFi.h>//Biblioteca que gerencia o WiFi.
#include <WiFiServer.h>//Biblioteca que gerencia o uso do TCP.

WiFiServer servidor(80);//Cria um objeto "servidor" na porta 80 (http).
WiFiClient cliente;//Cria um objeto "cliente".

String html;//String que armazena o corpo do site.

void setup()
{
   Serial.begin(9600);//Inicia comunicaçao Serial.

   WiFi.mode(WIFI_STA);//Habilita o modo STATION.
   WiFi.begin("SUA REDE", "SUA SENHA");//Conecta no WiFi (COLOQUE O NOME E SENHA DA SUA REDE!).

   Serial.println(WiFi.localIP());//Printa o IP que foi consebido ao ESP8266 (este ip que voce ira acessar).
   servidor.begin();//Inicia o Servidor.

   pinMode(D4, OUTPUT);//Define o LED_BUILTIN como Saida.
}

void loop()
{
   http();//Sub rotina para verificaçao de clientes conectados.
}

void http()//Sub rotina que verifica novos clientes e se sim, envia o HTML.
{
   cliente = servidor.available();//Diz ao cliente que há um servidor disponivel.

   if (cliente == true)//Se houver clientes conectados, ira enviar o HTML.
   {
      String req = cliente.readStringUntil('\r');//Faz a leitura do Cliente.
      Serial.println(req);//Printa o pedido no Serial monitor.

      if (req.indexOf("/LED") > -1)//Caso o pedido houver led, inverter o seu estado.
      {
         digitalWrite(D4, !digitalRead(D4));//Inverte o estado do led.
      }

      html = "";//Reseta a string.
      html += "HTTP/1.1 Content-Type: text/html\n\n";//Identificaçao do HTML.
      html += "<!DOCTYPE html><html><head><title>ESP8266 WEB</title>";//Identificaçao e Titulo.
      html += "<meta name='viewport' content='user-scalable=no'>";//Desabilita o Zoom.
      html += "<style>h1{font-size:2vw;color:black;}</style></head>";//Cria uma nova fonte de tamanho e cor X.
      html += "<body bgcolor='ffffff'><center><h1>";//Cor do Background

      //Estas linhas acima sao parte essencial do codigo, só altere se souber o que esta fazendo!

      html += "<form action='/LED' method='get'>";//Cria um botao GET para o link /LED
      html += "<input type='submit' value='LED' id='frm1_submit'/></form>";

      html += "</h1></center></body></html>";//Termino e fechamento de TAG`s do HTML. Nao altere nada sem saber!
      cliente.print(html);//Finalmente, enviamos o HTML para o cliente.
      cliente.stop();//Encerra a conexao.
   }
}

Entendendo a fundo

Software

-Função WiFiServer::available()

cliente = servidor.available();

Aqui, estamos dizendo ao cliente que há um servidor disponível para conexão.

-Detectando clientes conectados

if (cliente == true){}

Com esta condicional, é verificado a existência de clientes conectados no ESP, e se sim, enviará o HTML para o cliente.

-Enviando a estrutura do HTML

cliente.print(html);

Após a criação da estrutura do HTML, precisamos enviar para o cliente. É feito com um simples print().

-Fechando conexão

cliente.stop();

Após o envio do HTML, encerramos a conexão pois não é necessário se manter conectado.


Foi usado um botão do tipo SUBMIT para fazer uma requisição GET ao Host, para entender melhor como funcionam os botoes no HTML, veja ESTE tutorial.

Fechamento

Com a possibilidade de receber e enviar dados pela internet, nossos horizontes ficam bem amplos. Podemos tanto controlar o MCU para por exemplo acionar o portão da garagem, ou descobrir se esta chovendo com sensores e etc. Dúvidas? Sugestões? Críticas? Comente abaixo!


Software Timer - ESP8266

Software Timer - ESP8266

Software Timer

Em várias situações, é necessário de certa forma, a manipulação do tempo em micro controladores. O jeito mais fácil é pelas funções básicas (delay e derivados), porém, normalmente, estas funções travam o micro controlador, e com isto, você é incapaz de ler botões ou algo do tipo enquanto o delay não acabar. Isto além de gerar terríveis problemas nos mais variados projetos, não é uma pratica saudável. Neste tutorial, vamos aprender sobre o OS_TIMER do ESP8266, este timer é baseado no software do ESP8266 e o limite inferior é 1mS e máximo de ~2 horas. Este software timer não é aconselhado para projetos em que o tempo é crítico. Apesar de nossos testes darem certa confiança, por ele ser baseado em software, alguns fatores podem atrasa-lo em alguns mS, tome cuidado.

 

Demonstrando a diferença

Neste exemplo apenas para comparação do Software Timer, usaremos um exemplo que acende 3 LEDs a cada 1 segundo e enquanto isso, ficaremos  enviando dados na Serial para mostrar o funcionamento do código. Antes de ir para o software timer, testem este código abaixo no ESP8266 e veja no Serial Monitor como é o recebimento de informações.

Neste código, estamos usando Delay para fazer o acionamento simples dos LEDs. Você perceberá que só irá aparecer mensagens a cada 4 Segundos.

long x;//Variavel para mostrar o desenvolvimento do codigo no Serial Monitor.

void setup()
{
   pinMode(D1, OUTPUT);//Define D1 como Saida.
   pinMode(D2, OUTPUT);//Define D2 como Saida.
   pinMode(D3, OUTPUT);//Define D3 como Saida.

   Serial.begin(9600);//Inicia a comunicaçao Serial para provar que o codigo nao trava.
}

void loop()
{
   led();//Sub rotina para acender os LED`s.

   Serial.println(x++);//Mostra no serial monitor o desenvolvimento do codigo.
}

void led()//Sub rotina para acender os LED`s.
{
   digitalWrite(D1, 1);//Acende o led 1.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D2, 1);//Acende o led 2.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D3, 1);//Acende o led 3.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D1, 0);//-
   digitalWrite(D2, 0);//-
   digitalWrite(D3, 0);//-Apaga os 3 leds.
   delay(1000);//Aguarda 1 segundo.
}

Após ver que o ESP só pula para a linha debaixo da função led() a cada 4 segundos, percebe-se que o ESP fica travado durante 4 segundos apenas para acender os LEDs, inutilizando totalmente o seu uso para outras coisas.

Agora chega de papo e vamos ao Software Timer.

 

 

Normalmente, na maioria dos casos, as funções de delay travam o código até que o delay se acabe. Ao usar delay(60000), o micro controlador ficará travado por 1 Minuto nesta linha até que o tempo acabe e não fara mais nada. Se desejarmos acender um LED a cada 30 segundos, isto irá gerar muitos problemas usando delay, então, usaremos os Timer’s. O Timer gera uma interrupção no sistema a cada intervalo de tempo e voltara a fazer a sua rotina padrão após terminar suas instruções.

Lembre-se, A rotina de um timer (Interrupção) não pode conter comandos de Delay, Serial e vários outros. A rotina do ISR deve ser a mais breve possível e normalmente usamos flag’s armazenadas na RAM para agilizar o processo e evitar erros internos.

 

Mãos à obra

Componentes necessários

Montando o projeto

 

Veja como ficou nossa montagem:

 

 

Código do projeto

#include <user_interface.h>;//Biblioteca necessaria para acessar os Timer`s.

os_timer_t tmr0;//Cria o Timer. Maximo de 7 Timer's.

volatile byte status;//Variavel armazenada na RAM para Status do LED.
long x;//Variavel para mostrar o funcionamento do Codigo.

void setup()
{
   os_timer_setfn(&tmr0, led, NULL); //Indica ao Timer qual sera sua Sub rotina.
   os_timer_arm(&tmr0, 1000, true);  //Inidica ao Timer seu Tempo em mS e se sera repetido ou apenas uma vez (loop = true)
                                     //Neste caso, queremos que o processo seja repetido, entao usaremos TRUE.

   pinMode(D1, OUTPUT);//Define D1 como Saida.
   pinMode(D2, OUTPUT);//Define D2 como Saida.
   pinMode(D3, OUTPUT);//Define D3 como Saida.

   Serial.begin(9600);//Inicia a comunicaçao Serial.
}

void loop()
{
   leitura();//Sub rotina para processar os LED`s.

   //O codigo irá funcionar normalmente sem que haja delays e acendendo os LED`s no intervalo definido.
   //Para demonstraçao, abra o Serial monitor e voce vera que o codigo continua normalmente.

   Serial.println(x++);//Print para provar que o codigo nao trava. Abra o Serial monitor e veja
                       //que o codigo continua rodando enquanto os LED`s piscam a cada 1 Segundo.
}

void leitura()//Sub rotina para processar os LED`s.
{
   switch (status)
   {
   case(1)://Caso status seja 1, acenda o led 1.
      digitalWrite(D1, 1);
   break;

   case(2)://Caso status seja 2, acenda o led 2.
      digitalWrite(D2, 1);
   break;

   case(3)://Caso status seja 3, acenda o led 3.
      digitalWrite(D3, 1);
   break;

   case(4)://Caso status seja 4, Apague os 3 LED`s.
      digitalWrite(D1, 0);
      digitalWrite(D2, 0);
      digitalWrite(D3, 0);
   break;
   }
}

void led(void*z)//Sub rotina ISR do Timer sera acessada a cada 1 Segundo e mudara o status do LED.
{
   if (status == 4)//Verifica se o maximo foi alcançado para resetar a contagem.
   {
      status = 0;
   }

   status++;
}

 


Entendendo a fundo

Hardware

As ligações são simples, apenas sendo necessário ligar o pino de cada LED em sua correspondente porta, não esquecendo o uso de resistores para limitar a corrente/tensão e também não queimar o LED. O outro pino do LED no GND. Este é o básico para um LED funcionar.

Software

 

-Função os_timer_setfn()

os_timer_setfn(&tmr0, led, NULL);

Esta função atribui uma função sua à rotina do Timer. Neste caso, definimos a nossa função led() ao timer tmr0, que criamos anteriormente.

 

-Função os_timer_arm()

os_timer_arm(&tmr0, 1000, true);

Com esta outra, é definido o tempo do timer e também se irá se repetir (loop). Neste caso, definimos ao timer tmr0, que entre na função anteriormente atribuída, a cada 1000mS. Se você não precisa que isso seja repetido, troque true por false, desativando o loop.

 

Finalizando

Comparando os dois códigos, podemos perceber claramente a diferença entre fazer tarefas com um Timer ou Delay. Enquanto o primeiro código só mostra a mensagem a cada 4 Segundos, o segundo mostra a mensagem diversas vezes ao mesmo tempo que gerencia os LEDs. Você pode usar isso em vários projetos em que é preciso fazer tarefas em tempos definidos, sem travar o resto do sistema com Delay. Dúvidas? Sugestões? Críticas? Comente abaixo!


Registrador de deslocamento

Registrador de deslocamento

Neste tutorial, você irá aprender a aumentar o número de portas do seu micro controlador (MCU) usando um registrador de deslocamento 74HC595 (Shift Register). Funciona com qualquer MCU: ATtiny85, Arduino, PIC, ESP8266, ESP32, Raspberry, Onion, etc. Usaremos neste tutorial um ATtiny85 para controlar 8 LEDs apenas com 3 pinos do MCU!

 

O que são?

Dentro de um registrador de deslocamento há diversos Flip-Flops interligados que de tal forma, consegue converter sinais de um tipo para outro (Serial-Paralelo/Paralelo-Serial) ou até mesmo para expansão de portas de um micro controlador.

Usaremos o 74HC595, um registrador de deslocamento Serial-Paralelo de 8bits, isto significa, que cada registrador irá controlar até 8 componentes. Também é possível liga-los em modo cascata, um após o outro. Com isto, podemos ligar diversos registradores e usando apenas 3 pinos, controlar 40, 80, 160 componentes e assim por diante. Este registrador tem apenas pinos de saída, caso seja necessário leitura de botões (input de dados), procure por outros, existem até alguns com comunicação I2C!

Para mais informações sobre registradores de deslocamento, clique AQUI.

Datasheet do 74HC595.

As aplicações para um registrador de deslocamento são bem variadas, pode tanto fazer a conversão de dados Seriais para Paralelo, Paralelo para Serial, ou quando é necessário mais pinos para nosso MCU. Com 5 registradores de deslocamento de 8 bits em cascata, usamos 3 pinos do MCU para controlar até 40 componentes! Perfeito para matrizes de LED 3D ou robôs com vários atuadores.

Fig 1 - Matriz de LED 3D.

Mãos à obra

Componente necessários

Para este tutorial, usaremos um ATtiny85, mas você pode usar qualquer MCU.

Montando o projeto

Agora vamos conectar os componentes do projeto. Monte seu circuito conforme a figura a seguir. Não se esqueça de ler a explicação do hardware logo abaixo.

 

 

Veja como ficou o nosso:

 

Código do projeto

/*
Pino 0 = Clock.
Pino 1 = Latch.
Pino 2 = Serial IN.
*/

void setup()
{
   for (byte i = 0; i < 3; i++)//Declaração dos pinos de saida.
   {
      pinMode(i, OUTPUT);
   }

   int x = 1;
   for (byte i = 0; i < 8; i++)//Ligamos um LED após o outro, permanecendo o estado do anterior.
   {
      s595(x);//Função que faz o gerencimento do registrador.
      x = (x * 2) + 1;//Conta binaria que faz BitShift: 0b001 -> 0b011 -> 0b111...
      delay(150);
   }
}

void loop()
{
   s595(random(0, 256));
   delay(500);
}

void s595(byte data)//O argumento para acender os LEDs pode ser em binario
{
   digitalWrite(1, LOW);//Fecha o Latch para input de dados.
   shiftOut(2, 0, LSBFIRST, data);//Função própria da Arduino IDE.
   digitalWrite(1, HIGH);//Abre o Latch para output dos dados.
}

Entendendo a fundo

Software

 

-Função s595()

void s595(byte data)
{
    digitalWrite(1, LOW);//Fecha o Latch para input de dados.
    shiftOut(2, 0, LSBFIRST, data);//Função própria da Arduino IDE.
    digitalWrite(1, HIGH);//Abre o Latch para output dos dados.
}

Esta função criada faz todo o gerenciamento do registrador de deslocamento.

Primeiramente fechamos o Latch para a entrada de novos valores, após a entrada dos valores pelo shiftOut(), abrimos o Latch para que as saídas sejam iguais ao dados que definimos com a entrada anterior.

Para entender melhor sobre a função shiftOut(), clique AQUI.

O legal desta função é que podemos usar diretamente binário para representar os LEDs, por exemplo:

s595(0b11001100);

Com isto, os LEDs serão idênticos ao binário, respectivamente Q0 -> Q7. As saídas Q0, Q1, Q4 e Q5 estarão em HIGH e o restante em LOW.

Hardware

Pinos necessários para o registrador funcionar. Adicione MR ao Vcc  e  OE ao GND.

O nosso registrador de deslocamento usado, tem 3 pinos básicos: Serial data IN, Latch e Clock.

  • Serial data IN: Aqui é adicionado os bit's para futuramente após o latch, virarem output.
  • Output Enable (OE): Ativo em LOW.
  • Latch: O latch funciona como se fosse um portão. quando em HIGH, o portão se abre, liberando os bit's que adicionamos anteriormente.
  • Clock: O clock deve ser oscilado a cada bit de entrada, para que sejam armazenados corretamente.
  • Master Reclear (MR): Ativo em LOW.
  • Q7': Este pino é usado para a ligação em cascata de mais registradores de deslocamento.
  • Q0 a Q7: São as saídas do registrador, use elas normalmente como se fossem pinos de saída, obedecendo os limites de tensão e corrente.

 

A figura abaixo mostra o efeito do Serial+Clock

Após a conclusão da entrada de dados, ao abrir o Latch, os pinos marcados com 1, ficarão em HIGH, e pinos com 0, em LOW. Então se usarmos "0b10010011", as saídas (Q0 até Q7) ficarão respectivamente: 1, 0, 0, 1, 0, 0, 1, 1.


Desafio

Primeiramente, veja qual LED acende com s595(0b10000000);  e depois dentro da função s595(), troque "LSBFIRST" para "MSBFIRST", veja qual LED acende e nos conte porque isto acontece!

Finalizando

Em alguns projetos, como matrizes de LED 3D, é necessário o uso de MUX e registradores de deslocamento, uma vez que nosso MCU não tem pinos suficientes para fazer o controle de cada componente. Com este simples e eficiente componente, podemos controlar diversos outros com poucos pinos do MCU, deixando os outros pinos do MCU livres para tarefas mais complicadas.


Segurança de dados com AES

Segurança de dados

A segurança é algo essêncial em muitos projetos, principalmente nos conectados à Internet. Desde esconder senhas ou mensagens para que ninguém além do destino possa ler, a segurança faz parte do nosso cotidiano e iremos aprender a implementa-la nos Microcontroladores. Aprenderemos usar a criptografia AES (Advanced Encryption Standard) com foco em apenas sobre sigilo do dado, o download dela estará ao fim do tutorial. Esta biblioteca para criptografia com AES, funciona tanto para Arduino, quanto para ESP8266 ou ESP32.

 

 

Um pouco sobre segurança

Antes de entrar em detalhes sobre o AES, um resumo sobre a segurança de dados.

 

-Codificação

A codificação é possivelmente o método mais simples e antigo, trata-se da troca de uma linguagem, para outro padrão. É necessário conhecer os caracteres codificados para poder decodificar. O objetivo da codificação não é tornar a mensagem secreta. Exemplo: Morse(Fig 1), que converte os caracteres para pulsos elétricos, sons, luzes, etc.

-Criptografia simétrica

A criptografia simétrica faz o uso de uma chave privada que deve ser mantida em segredo, já que é usada tanto para encriptação, quanto para desencriptação. Esta é mais simples e leve que a criptografia assimétrica. Exemplo: AES, DES.

-Criptografia assimétrica

A criptografia assimétrica faz o uso de duas chaves, uma pública e outra privada. A pública pode ser usada para encriptação e a privada para desencriptação. Esta é mais pesada e lenta. Exemplo: RSA.

O uso delas é bem diferente e logo, a comparação direta não faz sentido. Por exemplo, a assimétrica permite autenticidade dos dados e pode garantir que o dado recebido é de uma pessoa autorizada e não de alguém re-enviando o dado.

 

 

-Hash

Hash é um algoritmo de uma via, ou seja, é irreversível. É muito usado com senhas da seguinte forma: Primeiramente é gerado um Hash da senha e este, será apenas comparado ao Hash armazenado no destino. Caso os Hash's sejam iguais, logo a senha é igual. Exemplo: MD5, SHA-1.

Clique AQUI para mais informações sobre Hash.

 

-AES

AES (Advanced Encryption Standard), é uma criptografia de blocos com chave simétrica (cifra de bloco) e será usado AES-128 no exemplo deste tutorial. AES trabalha com o sistema de blocos de 16 Bytes. É possível utilizar valores de entrada menores sem problemas, mas maiores será necessário dividir em blocos de 16B.

 

 

Imagine que você use dois micro controladores para transmissão de mensagens (Exemplo: Whatsapp, Facebook...), muito provavelmente você deseja que ninguém consiga ler as mensagens, isto pode ser feito com a encriptação, que irá cifrar (embaralhar) a mensagem e deixa-la ilegível para qualquer pessoa sem a chave, garantindo que apenas as pessoas com a chave, consigam ler.

Também pode ser usada para protocolos de comunicação entre dispositivos Wireless ou Wired, para preservar a integridade do mesmo e evitar "curiosos de plantão".


Mãos à obra

Código do projeto

#include <AES.h>//Biblioteca do AES.

AES aes;//Cria a classe aes.
byte key[16], out[16], inp[32];//Cria arrays (vetores) para a chave, input e output de dados.
const char pass[] = "abc";//Define a chave usada, neste exemplo usamos AES128, então precisa ser <= 16 Bytes.


void setup()
{
   Serial.begin(115200);//Habilita a serial.
   Serial.println();//Limpa o monitor.

   enc128("vida de silicio", 1);//Faz a função de encriptação e retorna o HEX encriptado.
}

void loop()
{

}


void enc128(const char txt[], bool db)//Argumentos: (texto e debug)
{
   if (strlen(pass) > 16)//Verifica se a chave tem o tamanho limite de 16 caracteres.
   {
      if (db == true)
      {
         Serial.println("Chave para AES128 <= 16 Bytes");
      }
      return;//Se a chave for maior, irá sair da função.
   }

   if (strlen(txt) > 16)//Verifica se o texto tem o tamanho limite de 16 caracteres.
   {
      if (db == true)
      {
         Serial.println("Frase/numero para AES <= 16 Bytes / bloco");
      }
      return;//Se o texto for maior, irá sair da função.
   }

   for (byte i = 0; i < strlen(pass); i++)//Adiciona a chave(pass) na array key.
   {
      key[i] = pass[i];
   }

   for (byte i = 0; i < strlen(txt); i++)//Adiciona o texto na array input.
   {
      inp[i] = txt[i];
   }

   //Adiciona a chave ao algoritimo.
   if (aes.set_key(key, 16) != 0)//Verifica se a chave esta correta, caso nao, sairá da função.
   {
      if (db == true)
      {
         Serial.println("Erro ao configurar chave");
      }
      return;//Sai da função
   }

   //Faz a encriptação da array INPUT e retorna o HEXA na array OUTPUT.
   if (aes.encrypt(inp, out) != 0)//Verifica se a encriptação esta correta, se não, sairá da função.
   {
      if (db == true)
      {
         Serial.println("Erro ao encriptar");
      }
      return;//Sai da função
   }

   if (db == true)//Se o debug estiver on (1), irá mostrar o HEXA no serial monitor.
   {
      for (byte i = 0; i < 16; i++)
      {
         Serial.print(out[i], HEX);
         Serial.print(" ");
      }
      Serial.println();
   }

   aes.clean();//Limpa a chave e residuos sensiveis da encriptação.
}

Entendendo a fundo

Software

A função que desenvolvemos enc128() torna o uso muito simples, mas você deve estudar mais sobre o AES e a biblioteca usada para entender melhor o funcionamento. Aqui será mostrado apenas a encriptação, mas também é possível fazer a desencriptação da mesma forma, este será o desafio de vocês para aprendizado.


 

-Variaveis usadas

byte key[16], out[16], inp[32];

Criamos os vetores (Arrays) para alocar a CHAVE e mensagens de INPUT e OUTPUT do buffer AES.

 

-Definindo a chave

char pass[] = "abc";

Definimos a Key (chave) da nossa criptografia. Deve ter no mínimo 1 caractere, e no máximo 16 (AES 128).  0 < Key <= 16. Aqui usamos "abc", mas é aconselhado o uso de letras e números aleatórios.

Você deve usar chaves grandes e aleatórias. Sem isso, seu sistema estará em grandes riscos. Usamos uma chave simples para fácil entendimento.

 

-Função enc128()

enc128("vida de silicio", 1);

enc128(texto, debug);

A função criada para encriptação dos dados torna o processo bem fácil. Os parâmetros necessários para ela é o texto que deseja encriptar, e em seguida, o debug, que mostra no serial monitor possíveis erros e por fim, o HEX da encriptação.

O texto para encriptação deve estar entre aspas e ser menor que 17 caracteres (bytes). 0 < texto <= 16.

O debug é ativado com 1 e desativado com 0, aconselhamos a sempre usar 1 para caso aconteça erros.

 

-Função AES::set_key()

aes.set_key(key, 16);

Com esta função, é adicionado a nossa chave ao sistema de criptografia interno.

Obs: A chave para AES é 128/192/256b, porém, para ser didático, foi usado apenas 3 caracteres. Tome cuidado ao usar chaves de outros tamanhos, alguns lugares não aceitam!

 

-Função AES::encrypt()

aes.encrypt(inp, out);

Esta função, faz a encriptação dos dados que estão dentro do vetor INP, e retorna os valores dentro do vetor OUT.


Colocando para funcionar

Ao testar o código que foi mostrado aqui, será gerado exatamente este código em hexadecimal "4A 38 3A 94 FC FB C4 C6 E1 4F D2 5D 34 7B B5 80", este código hexadecimal é a nossa mensagem encriptada. Encontrei um site bem legal que faz a encriptação e desencriptação dos dados AES, usarei ele.

Coloquei a nossa chave "abc" e o código hexadecimal gerado pelo micro controlador. Após clicar para desencriptar, é mostrado a mensagem original, e como podemos ver, funcionou.

o AES permite vários métodos de encriptação, a mais simples é a ECB, a biblioteca usada no tutorial também permite a CBC que é mais segura, porém mais complicada.

Clique AQUI para ir ao site.


Desafio

O desafio para vocês é que façam a desencriptação de um código hex, estudem sobre o assunto e veja as funções da biblioteca! Vocês podem desencriptar o próprio hex gerado da sua encriptação, ou usar o site indicado anteriormente para obter um hex e ver se a desencriptação funciona. Lembrando que esta biblioteca funciona para Arduino, ESP8266 e ESP32.

Download da biblioteca: https://github.com/spaniakos/AES

 

Fechamento

A segurança é extremamente importante em IoT e nao deve ser esquecida. Sempre adicione caso seja necessário em seu projeto, e principalmente em produtos comerciais. Tem dúvidas? sugestões? críticas? Comente abaixo!


Controlando seu projeto usando Telegram

Controlando seu projeto usando Telegram - ESP

Controlando seu projeto com Telegram

Imagine uma automação ou projeto que permite você “conversar” com seu Microcontrolador (MCU) e também receber comandos, parece difícil, mas é bem simples. Aprenderemos a usar o Telegram para criar automações e projetos das mais diversas possibilidades e utilidades que estabelece uma comunicação amigável com o MCU. Para essa experiência usaremos o NodeMCU 8266, mas você pode fazer com outros ESPs, tal como os da linha ESP8266 e o ESP32.

 

[toc]

O Telegram

Podemos fazer desde simples controles de LEDs, ou até uma automação residencial controlada pelo Telegram, já que os BOTs permitem controle total de informações.

 

Usaremos o Telegram pois nos permite criar “BOTs”. Estes BOT's, são como robôs virtuais e com eles, conseguimos criar uma interface IHM (Interface Homem-Máquina). Este método, permite o fluxo de informações de ambos sentidos (Input e Output), então conseguimos controlar o sistema e também ser notificado pelo sistema.

 

Criando seu Bot no Telegram

1-) Pesquise pelo "BotFather" no menu de pesquisa do Telegram, entre nele e clique em "Começar ou Reiniciar".

 

 

 

2-) Pelo BotFater podemos criar novos Bots, configura-los e muito mais. Para criar, faça:

  1. Digite "/newbot".
  2. Digite o nome do seu novo Bot.
  3. Digite o usuário do Bot com a terminação "bot".

 

3-) Logo após a criação, o BotFater enviará uma mensagem com o link do Bot e logo abaixo o Token do Bot. Você pode clicar neste link para abrir a conversa com seu Bot ou pode pesquisa-lo futuramente.

Você precisa desse Token para inserir no código!

 

Mãos a obra

Componentes necessários

Para este projeto, usaremos o ESP8266 (versão NodeMCU). Entretanto, pode ser feito igualmente com o ESP32, sendo necessário alguns pequenos ajustes.

  • 1x – ESP8266. (Usaremos o NodeMCU).
  • 1x – Telegram no Celular.
  • 1x - LED. (Usaremos o LED OnBoard da placa).

- Biblioteca utilizada

Clique AQUI para ir a pagina de download da biblioteca "UniversalTelegramBot" utilizada.

Alguns usuários relatam erro com a biblioteca "ArduinoJson".  Caso aconteça com você, será necessário instalar a biblioteca na Arduino IDE.

Para isso vá em "Gerenciador de bibliotecas", procure pela biblioteca "ArduinoJson", instale-a e reinicie a Arduino IDE.

- Código do projeto

Não se esqueça de alterar as credenciais do WiFi e também o Token do seu Bot. Sem isso não irá funcionar.

Vários usuários relatam erro com a versão 2.5 do esp8266 (core) instalado na Arduino IDE, que é resolvido instalando a 2.4.0.

 

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#define BOTtoken "135924:AAErDKEJaQpEnqs_xj35asdGQ5kK6dQet4"//Define o Token do *seu* BOT

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

String id, text;//Váriaveis para armazenamento do ID e TEXTO gerado pelo Usuario
unsigned long tempo;

void setup()
{
   pinMode(D4, OUTPUT);//LED conectado à saida
   WiFi.mode(WIFI_STA);//Define o WiFi como Estaçao
   connect();//Funçao para Conectar ao WiFi
}

void loop()
{
   if (millis() - tempo > 2000)//Faz a verificaçao das funçoes a cada 2 Segundos
   {
      connect();//Funçao para verificar se ainda há conexao
      readTel();//Funçao para ler o telegram
      tempo = millis();//Reseta o tempo
   }
}

void connect()//Funçao para Conectar ao wifi e verificar à conexao.
{
   if (WiFi.status() != WL_CONNECTED)//Caso nao esteja conectado ao WiFi, Ira conectarse
   {
      WiFi.begin("SUA REDE", "SUA SENHA");//Insira suas informaçoes da rede
      delay(2000);
   }
}

void readTel()//Funçao que faz a leitura do Telegram.
{
   int newmsg = bot.getUpdates(bot.last_message_received + 1);

   for (int i = 0; i < newmsg; i++)//Caso haja X mensagens novas, fara este loop X Vezes.
   {
      id = bot.messages[i].chat_id;//Armazenara o ID do Usuario à Váriavel.
      text = bot.messages[i].text;//Armazenara o TEXTO do Usuario à Váriavel.
      text.toUpperCase();//Converte a STRING_TEXT inteiramente em Maiuscúla.

      if (text.indexOf("ON") > -1)//Caso o texto recebido contenha "ON"
      {
         digitalWrite(D4, 0);//Liga o LED
         bot.sendMessage(id, "LED ON", "");//Envia uma Mensagem para a pessoa que enviou o Comando.
      }

      else if (text.indexOf("OFF") > -1)//Caso o texto recebido contenha "OFF"
      {
         digitalWrite(D4, 1);//Desliga o LED
         bot.sendMessage(id, "LED OFF", "");//Envia uma Mensagem para a pessoa que enviou o Comando.
      }

      else if (text.indexOf("START") > -1)//Caso o texto recebido contenha "START"
      {
         bot.sendSimpleMessage(id, id, "");//Envia uma mensagem com seu ID.
      }

      else//Caso o texto recebido nao for nenhum dos acima, Envia uma mensagem de erro.
      {
         bot.sendSimpleMessage(id, "Comando Invalido", "");
      }
   }

}

Colocando para funcionar

Após a criação do BOT e upload do código, podemos ver funcionando. Veja o BOT respondeu como o esperado aos comandos:

 


Entendendo a fundo

Software

-Função UniversalTelegramBot::sendMessage()

bot.sendMessage(id, "LED OFF", "");

Com esta função, é feito o envio da mensagem para o determinado ID (referente ao ID de quem enviou a mensagem ao Bot). Logo ao iniciar seu BOT, automaticamente é enviado uma mensagem "/START", e nosso sistema irá responder com o seu ID do Telegram; você pode usar isso para aceitar apenas comandos de seu ID.

 

-Variável id

id = bot.messages[i].chat_id;

Toda vez que o Bot receber um novo update (mensagem), irá armazenar o ID da pessoa que enviou a mensagem na variável id.

 

-Variável text

text = bot.messages[i].text;

Toda vez que o Bot receber um novo update (mensagem), irá armazenar o texto na variável text.

 

A biblioteca do Telegram permite mais opções interessantes, como por exemplo obter o horário em que a mensagem foi enviada ao Bot! Dê uma olhada na referência da biblioteca.

 

-Função UniversalTelegramBot::getUpdates()

int newmsg = bot.getUpdates(bot.last_message_received + 1);

Esta função faz a verificação de novas mensagens, sempre será lido da última (mais recente), para a primeira (mais antiga) mensagem no buffer do Bot. Isto será feito até que se tenha lido todas as mensagens disponíveis então tome cuidado para não travar ou atrasar o resto do seu código!


Desafio

Qualquer pessoa que adicionar seu Bot (basta pesquisar), pode enviar comandos e controla-lo. Você terá que criar algum tipo de “cadeado” para aceitar apenas comandos de pessoas autorizadas. Cada usuário no Telegram tem um ID, então você pode usar isso à seu favor e fazer o sistema aceitar apenas comandos de algumas pessoas.

Fechamento

Podemos facilmente incluir este controle com o Telegram em diversos projetos, permitindo que o mesmo seja controlado à distancia e até mesmo que você seja notificado, como por exemplo um alarme para sua casa que mande mensagem para seu celular ao detectar movimento. As aplicações são imensas, dependendo apenas da sua criatividade. Dúvidas? Sugestões? Críticas? Comente!


conhecendo a família esp

O que é ESP8266 - A Família ESP e o NodeMCU

O que é ESP8266 - A Família ESP e o NodeMCU 

Que tal conectar seu projeto à imensidão da internet de forma simples e barata? Essa é a proposta do ESP8266 que têm sido cada vez mais usado em projetos de automação e robótica para conectar as mais diversas ideais à internet. Neste tutorial você irá conhecer a família de microcontroladores ESP8266 que é tendência no mundo dos Makers e nos mais diversos exemplos de Internet das Coisas (IoT), e também aprenderá como funciona a sua programação e dar o primeiro upload. Entre eles: ESP-01 A, ESP-7, ESP-12E e NodeMcu 

[toc]

O que é ESP8266?

É possível que você já tenha ouvido falar sobre o ESP8266, ele tem se tornado cada vez mais popular entre projetos de Internet das Coisas!

Os ESP8266's são microcontroladores que já possuem tudo que é necessário para se conectar a Internet. Ou seja, eles são como um Arduino com integração Wi-Fi.

Outro ponto importante é que eles são pequenos e isso viabiliza projetos pequenos.

Fig 1: ESP-01 A ESP8266
Fig 1: ESP-01 A

Um exemplo é o ESP8266-01, esta minúscula placa, também chamado de "Módulo" por alguns, tem um potencial muito maior do que o aparenta, veja algumas especificações:

  • CPU: 32bit RISC Tensilica Xtensa LX106 rodando à 80/160 MHz.
  • RAM: 64 kB.
  • FLASH: QSPI Externo - de 512 kB até 4 MB.
  • WiFi: IEEE 802.11 - b/g/n.

Comparando diretamente com o Arduino, o ESP8266 tem um poder de processamento maior, porem há poucas GPIO's para usar nesta versão. Esta versão, conta apenas com 4 GPIO's para uso, sendo que dois são para comunicação Serial.

Para resolver esse problema de pinos insuficientes, existem versões mais robustas do ESP8266, como por exemplo, este ESP8266-12:

Fig 2: ESP8266 ESP-12
Fig 2: ESP-12

Este, é exatamente o mesmo que o anterior, mas conta com mais GPIO's disponíveis para uso geral.

 

APLICAÇÕES DO ESP8266

 

 

O uso para esse Micro controlador beira ao "Infinito", já que conta com poder de processamento e WiFi embutido. Com ele, também é possível ser usado como um "Módulo" com outros Micro controladores, isto pode ser feito através de comandos AT. Além disso, as versões menores, como o 01 ou 09, são muito usados como uma "Ponte Serial-WiFi", já que contam com poucos pinos; sendo assim, é possível receber dados por um aplicativo/WEB e enviar estes dados para um Arduino e acender uma lampada por exemplo! O oposto também é possível, enviar dados do Arduino para um aplicativo ou página WEB.

 

Algumas aplicações interessantes:

  • Automação residencial.
  • Rede de sensores.
  • Robótica.
  • Comunicação Wireless entre MCU's (Micro controller Unit).
  • Aplicativos e Paginas WEB para controle geral.
  • Monitoramento de Informações remotamente.
  • E muito mais.

 

 

A Família ESP8266

Apresentaremos as principais características dos dois principais mais vendidos, que são: ESP8266-01 e o ESP8266-12 na versão NodeMCU.

ESP-01

Este pequeno ESP8266-01, conta com poucos pinos para uso geral, porém é muito usado por conta do seu tamanho como a "Ponte Serial-WiFi", segue a explicação dos pinos:

GND: Terra-GND.

Vcc: Alimentação de 3,3V.

RESET: Reset ativo quando em LOW.

CH_PD: Chip enable, deve estar em HIGH para funcionamento do MCU.

RXD: Receive data, usado para receber dados da comunicação de outros MCU's.

TXD: Tansmit data, usado para transmitir dados a outros MCU's.

GPIO0: GPIO (General Purpose Input/Output), este pino é para uso geral, tanto como Entrada/Saída e até Digital/PWM. Deve estar conectado ao GND para novos Upload's (Veja na Fig 4, Boot Modes).

GPIO2: GPIO para uso geral.

 

Para dar um novo upload à este carinha, você precisa de um conversor Serial (FTDI) para transmitir os dados até ele. As ligações são estas:

Lembrando que a alimentação deve ser feita com 3,3V, inclusive o Rx. Com isto, voce já sera capaz de dar upload de seus códigos.

 

NodeMCU

 

NodeMcu esp8266 ESP-32
NodeMcu
Pinagem NodeMcu
Pinagem NodeMcu

Esta versão do ESP8266-12 vem numa placa de desenvolvimento, chama-se de NodeMCU. Esta belezinha conta com conversor Serial e regulador de tensão próprio, não sendo necessário ambos como nas outras versões fora da placa. Também há pinos próprios para I2C, SPI, Analógico e outros.

 

GPIO's ESP8266:

Esta imagem, mostra todas definições de GPIO's do ESP8266, inclusive durante o boot, em que alguns pinos são mantidos em certos estados.


Mãos à obra

Este projeto é  o "Hello world" no mundo de Microcontroladores. Você irá ensinar a dar o primeiro upload para piscar o LED_BUILTIN (LED OnBoard) do ESP8266-01 usando um FTDI externo. Pegue a pipoca e vamos la!

 

Componentes necessários

As ligações ficarão parecidas com esta:

 

Estas são ligaçoes básicas, porém, para cada novo upload, é necessário colocar o GPIO0 em GND, como foi mostrado no esquema, GPIO0 já esta em GND. Não se esqueça dele sempre que for fazer um novo Upload!

 

Preparando a IDE Arduino

Usaremos a Arduino IDE, mas você pode programa-lo com LUA, ou até a propria SDK.

1-) Vá em Arquivos>Preferencias, e adicione este link em "URLs Adicionais...": http://arduino.esp8266.com/stable/package_esp8266com_index.json

2-) Vá em Ferramentas>Placa>Gerenciador de placas.

3-) Procure pelo ESP8266 e instale-o.

4-) Após instalar as placas do ESP8266, selecione-a em Ferramentas>Placa>Generic ESP8266 Module. (Estou usando o ESP8266-01, caso voce use por exemplo o NodeMCU, selecione NodeMCU...).

5-) Agora, é só configurar a placa, aconselho a usarem igual ao da foto. Testem primeiramente com o upload a 115200@bps, caso nao funcione, teste com outras velocidades! Não se esqueça de selecionar a porta que estiver seu FTDI.

Sua IDE esta pronta para funcionar com o ESP8266! Vamos ao código!

 

Código do projeto

void setup()
{
   pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED interno como Saida.
}

void loop()
{
   digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do LED de acordo com a leitura.
   delay(250);
}

 


Entendendo a fundo

Software

-Função pinMode()

pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED interno como Saida.

Esta função define um pino, como saída ou entrada. Neste caso, definimos o  pino do LED_BUILTIN como saída.

 

-Função digitalWrite() e digitalRead()

digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do LED de acordo com a leitura.

Aqui, estamos escrevendo um sinal lógico ao LED_BUILTIN. Neste caso, usamos a função digitalRead() que retorna o valor atual de um pino (1 para HIGH e 0 para LOW).

Usamos tambem um Inversor (NOT) "!" para inverter o estado de leitura, ou seja, caso o LED esteja ligado (1), invertemos para (0) e escrevemos isso à porta, assim, desligando-a.

 

-Função delay()

delay(250);

A função delay(), gera um atraso no código, fazendo com que o micro controlador trave naquela linha e fique até acabar o tempo. O tempo deve ser em mS, sendo que 1 Segundo = 1000mS.


 

De upload do codigo, e veja que o LED OnBoard (Azul) irá piscar a cada 250mS. Não se esqueça que para dar um novo upload, é necessário que o ESP8266 seja reiniciado com o GPIO0 em GND novamente.

 

Fechamento

Você aprendeu o que é este incrível microcontrolador e também como dar o primeiro upload à ele. Sinta-se à vontade para dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.

Você vai gostar de Conhecer o ESP32