Dispositivos embarcados inseridos em projetos de Internet das Coisas precisam, muitas vezes, de uma gama considerável de recursos, tais como: processamento, memórias, interação com sensores e protocolos de comunicação diversos, displays, etc. Enfim, tudo que envolve processamento, comunicação e interação com usuário e sensores pode ser elegível em um dispositivo embarcado de um projeto IoT.
Recentemente, a empresa chinesa Seeed Studio lançou o Wio terminal, um dispositivo que reúne tudo isso num só equipamento, sendo literalmente um All-In-One para makers e IoT.
Este artigo visa falar das especificações técnicas do Wio Terminal, assim como apresentar um projeto prático com ele.
Sobre a Seeed Studio
A Seeed Studio é uma empresa chinesa (sediada em Shenzhen) com mais de dez anos de mercado, com atuação dedicada a prover hardware e soluções para makers em sistemas embarcados IoT. Possui em seu portfólio diversos modelos de placas, sensores e periféricos diversos, sendo um dos nomes mais fortes no mundo no segmento.
Wio Terminal – visão geral
O Wio Terminal é um dispositivo que contém tudo que um projeto que deva interagir com o usuário precisa: processamento, display, botões e sensores. A figura 1 mostra suas diferentes faces.
Na sua face frontal, possui um display LCD de 2.4”, um mini-joystick de 5 posições e uma saída de áudio (buzzer). Dessa forma, como a tela ocupa boa parte da face frontal, é possível construir interfaces gráficas bastante interessantes para o usuário, algo muito útil em sistemas de monitoramento e telemetria remotos. Ainda, a Seeed Studio disponibiliza bibliotecas gráficas e vários exemplos de como utilizar o display, o que facilitará a vida na hora de desenhar uma interface gráfica.
Já na sua face traseira, possui uma janela transparente, a qual da visão direta a parte de sua PCB e também a um sensor de luminosidade e um emissor infravermelho. Ainda, a face traseira dispõe de um conector de 40 pinos compatível com o utilizado na Raspberry Pi. Dessa forma, o Wio Terminal pode ser utilizado na forma de um shield / hat para a Raspberry Pi também. Outro fator interessante na face traseira do Wio Terminal é a presença de imãs, o que permite a fixação dele em superfícies metálicas (como geladeiras, por exemplo).
Em sua face inferior, possui dois conectores para sensores / módulos Grove. Isso é muito interessante pois permite o uso de forma praticamente plug-and-play de módulos e sensores Grove, o que permite o desenvolvimento rápido de protótipos com a vantagem de ficar bem “clean” (sem conectores expostos), sendo definitivamente algo positivo em um dispositivo destinado para makers e hobistas em sistemas embarcados e Iot. Ainda, a face inferior conta com um conector USB-C para alimentação e programação.
Na face lateral, conta com entrada para micro-SD card, tornando possível a interação com arquivos maiores (fotos, por exemplo), assim como gravação de arquivos a partir do dispositivos (gravação de dados de sensores, por exemplo), sendo portanto um grande ponto positivo para este dispositivo. A face lateral também conta com um botão de três direções (on, off e reset).
Quanto a programação, o Wio Terminal pode ser programado pela Arduino IDE, a partir das bibliotecas disponíveis pela própria Seeed Studio.
Em termos de conectividade, a placa possui conectividade wi-fi (2.4GHz e 5GHz) e bluetooth (inclusive, suportando BLE 5.0). Isso é um dos pontos mais fortes deste dispositivo, pois com estas opções de conectividade, é possível sua inserção em praticamente qualquer projeto IoT.
Como pontos a melhorar, destaco a falta de suporte a bateria (seja interna ou externa), algo que desaponta um pouco considerando o potencial que o Wio Terminal tem de ser um dispositivo portátil e completo para IoT e interação com usuário. Além disso, sua documentação oficial reforça que é preciso fazer update de firmware do chip que controla wi-fi e Bluetooth (RTL8720DN, do fabricante Realtek), algo que pode ser complicado aos mais iniciantes e que, com certeza, toma um tempo considerável ao se aprender a lidar com o dispositivo.
Especificações técnicas
O Wio Terminal possui as seguintes especificações técnicas:
- Microcontrolador Microchip ATSAMD51P19, sendo um ARM Cortex-M4F rodando em uma frequência de 120MHz, com 4MB de memória flash (externa) e 192KB de memória RAM.
- Suporta os seguintes protocolos de comunicação: SPI, I2C, I2S, ADC, DAC, PWM, UART.
- Conectividade wi-fi (2.4Ghz / 5Ghz, 802.11 a/b/g/n) e Bluetooth (BLE / BLE 5.0) provida pelo RTL8720DN, do fabricante Realtek.
- USB-C OTG. Cabo já fornecido no produto.
- Display LCD: resolução de 320×240 px e 2.4” de tamanho
- Demais periféricos: acelerômetro (LIS3DHTR), microfone (1.0V-10V -42dB), buzzer, sensor de luminosidade (400-1050nm), emissor infravermelho (940nm), slot para cartão micro-SD (capacidade máxima: 16GB), conector de 40 pinos compatível com Raspberry Pi, botões simples (três) e um mini-joystick (5 posições).
A figura 2 mostra um overview do hardware do Wio Terminal.
Documentação oficial
Você pode conseguir informações adicionais, assim como um getting started do dispositivo (incluindo guia de quais bibliotecas instalar e procedimentos seguir), no seguinte endereço: https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/
Projeto-exemplo: central de controle
Para mostrar o Wio Terminal na prática, fiz um projeto simples porém que serve como base para seus futuros projetos com este dispositivo: uma central de controle, capaz de receber e mostrar informações de temperatura e pressão barométrica, prever o tempo com base na pressão barométrica recebida e, ainda, controlar 3 LEDs ligados em um dispositivo remoto, via Internet. O protocolo de comunicação utilizado entre Wio Terminal e dispositivo remoto é o MQTT, neste exemplo utilizado junto com um broker público.
Para melhor mostrar as funcionalidades do projeto, veja o vídeo a seguir:
O projeto consiste em duas partes:
- ESP32 com sensor BMP180: parte responsável por medir, de segundo em segundo, a temperatura e a pressão barométrica e enviar tais dados, via Internet e MQTT, para o Wio Terminal. Ainda, conta com 3 LEDs, que são controlados via Internet e MQTT pelo Wio Terminal.
- Wio Terminal: parte responsável por receber os dados enviados pelo ESP32, exibir dados na tela, prever o clima com base na pressão barométrica (sol, nublado ou chuva) e, ainda, controlar 3 LEDs ligados no ESP32, via Internet e MQTT.
Circuito esquemático – placa com ESP32
O circuito esquemático da placa com ESP32 para medição remota de temperatura e pressão barométrica pode ser visto na figura 3.
Código-fonte: placa com ESP32
O código-fonte do software embarcado que roda na placa com ESP32 para medição remota de temperatura e pressão barométrica pode ser abaixo. Este código-fonte foi desenvolvido na Arduino IDE, e utiliza como bibliotecas a PubSubClient e a BMP085 (Adafruit). Caso não tenha o seu ambiente preparado para programar o ESP32 via Arduino IDE, recomendo fortemente a leitura deste artigo.
IMPORTANTE: para total compreensão do mesmo, leia atentamente seus comentários.
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_BMP085.h>
#include <Wire.h>
#define DESLIGADO 0x00
#define LIGADO 0x01
#define GPIO_LUZ_1 15
#define GPIO_LUZ_2 2
#define GPIO_LUZ_3 4
#define TOPICO_PUBLISH "wio_terminal_temp_pressao"
#define TOPICO_SUBSCRIBE "wio_terminal_controle_saida"
#define SDA_PIN 19
#define SCL_PIN 18
const char* SSID = " "; //coloque aqui o nome da rede wifi
const char* PASSWORD = " "; //coloque aqui a senha da rede wifi
const char* BROKER_MQTT = "broker.hivemq.com";
int BROKER_PORT = 1883;
WiFiClient espClient;
PubSubClient MQTT(espClient);
Adafruit_BMP085 bmp180;
char estado_luz_1 = DESLIGADO;
char estado_luz_2 = DESLIGADO;
char estado_luz_3 = DESLIGADO;
void mqtt_callback(char* topic, byte* payload, unsigned int length)
{
String msg;
//obtem a string do payload recebido
for(int i = 0; i < length; i++)
{
char c = (char)payload[i];
msg += c;
}
if (msg.equals("L1"))
{
if (estado_luz_1 == LIGADO)
{
digitalWrite(GPIO_LUZ_1, LOW);
estado_luz_1 = DESLIGADO;
}
else
{
digitalWrite(GPIO_LUZ_1, HIGH);
estado_luz_1 = LIGADO;
}
return;
}
if (msg.equals("L2"))
{
if (estado_luz_2 == LIGADO)
{
digitalWrite(GPIO_LUZ_2, LOW);
estado_luz_2 = DESLIGADO;
}
else
{
digitalWrite(GPIO_LUZ_2, HIGH);
estado_luz_2 = LIGADO;
}
return;
}
if (msg.equals("L3"))
{
if (estado_luz_3 == LIGADO)
{
digitalWrite(GPIO_LUZ_3, LOW);
estado_luz_3 = DESLIGADO;
}
else
{
digitalWrite(GPIO_LUZ_3, HIGH);
estado_luz_3 = LIGADO;
}
return;
}
}
/* Função: inicializa e conecta-se na rede WI-FI desejada
* Parâmetros: nenhum
* Retorno: nenhum
*/
void init_wifi(void)
{
delay(10);
Serial.println("------Conexao WI-FI------");
Serial.print("Conectando-se na rede: ");
Serial.println(SSID);
Serial.println("Aguarde");
reconnect_wifi();
}
/* Função: inicializa parâmetros de conexão MQTT(endereço do
* broker, porta e seta função de callback)
* Parâmetros: nenhum
* Retorno: nenhum
*/
void init_mqtt(void)
{
/* informa a qual broker e porta deve ser conectado */
MQTT.setServer(BROKER_MQTT, BROKER_PORT);
MQTT.setCallback(mqtt_callback);
}
/* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair)
* em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito.
* Parâmetros: nenhum
* Retorno: nenhum
*/
void reconnect_mqtt(void)
{
char mqtt_id_randomico[5] = {0};
while (!MQTT.connected())
{
Serial.print("* Tentando se conectar ao Broker MQTT: ");
Serial.println(BROKER_MQTT);
/* gera id mqtt randomico */
randomSeed(random(9999));
sprintf(mqtt_id_randomico, "%ld", random(9999));
if (MQTT.connect(mqtt_id_randomico))
{
Serial.println("Conectado com sucesso ao broker MQTT!");
MQTT.subscribe(TOPICO_SUBSCRIBE);
}
else
{
Serial.println("Falha ao reconectar no broker.");
Serial.println("Havera nova tentatica de conexao em 2s");
delay(2000);
}
}
}
/* Função: reconecta-se ao WiFi
* Parâmetros: nenhum
* Retorno: nenhum
*/
void reconnect_wifi()
{
/* se já está conectado a rede WI-FI, nada é feito.
Caso contrário, são efetuadas tentativas de conexão */
if (WiFi.status() == WL_CONNECTED)
return;
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println();
Serial.print("Conectado com sucesso na rede ");
Serial.print(SSID);
Serial.println("IP obtido: ");
Serial.println(WiFi.localIP());
}
/* Função: verifica o estado das conexões WiFI e ao broker MQTT.
* Em caso de desconexão (qualquer uma das duas), a conexão
* é refeita.
* Parâmetros: nenhum
* Retorno: nenhum
*/
void verifica_conexoes_wifi_mqtt(void)
{
/* se não há conexão com o WiFI, a conexão é refeita */
reconnect_wifi();
/* se não há conexão com o Broker, a conexão é refeita */
if (!MQTT.connected())
reconnect_mqtt();
}
/* Função: inicializa comunicação com sensor BMP180
* Parâmetros: nenhum
* Retorno: nenhum
*/
void init_bmp180(void)
{
if (!bmp180.begin())
{
Serial.println("[BMP180] Sensor nao encontrado.");
while (1)
{
delay(1);
}
}
}
void setup()
{
Serial.begin(115200);
/* Inicializa sensor BMP180 */
Wire.begin(SDA_PIN, SCL_PIN);
init_bmp180();
/* Inicializa saídas */
pinMode(GPIO_LUZ_1, OUTPUT);
pinMode(GPIO_LUZ_2, OUTPUT);
pinMode(GPIO_LUZ_3, OUTPUT);
digitalWrite(GPIO_LUZ_1, LOW);
digitalWrite(GPIO_LUZ_2, LOW);
digitalWrite(GPIO_LUZ_3, LOW);
estado_luz_1 = DESLIGADO;
estado_luz_2 = DESLIGADO;
estado_luz_3 = DESLIGADO;
/* Conecta-se no wi-fi e MQTT */
init_wifi();
init_mqtt();
}
void loop()
{
float temp, pressao_hpa;
char msg_mqtt[50];
/* garante que haja conectividade wi-fi e MQTT */
verifica_conexoes_wifi_mqtt();
temp = bmp180.readTemperature();
pressao_hpa = bmp180.readPressure()/100;
sprintf(msg_mqtt, "%.0f;%.1f", temp, pressao_hpa);
MQTT.publish(TOPICO_PUBLISH, msg_mqtt);
MQTT.loop();
delay(1000);
}
Código-fonte: Wio Terminal
O código-fonte do software embarcado que roda no Wio Terminal pode ser abaixo. Este código-fonte foi desenvolvido na Arduino IDE, e utiliza como bibliotecas a PubSubClient, as bibliotecas wifi mostradas na documentação oficial do dispositivo e a biblioteca para controle do display TFT_eSPI. Caso não tenha o seu ambiente preparado para programar o Wio Terminal via Arduino IDE, recomendo fortemente a leitura da documentação oficial.
#include "AtWiFi.h"
#include "SPI.h"
#include "TFT_eSPI.h"
#include <PubSubClient.h>
/* Definições gerais */
#define SERIAL_DEBUG_BAUDRATE 115200
#define SIM 0x01
#define NAO 0x00
#define TECLA_PRESSIONADA 0x01
#define TECLA_NAO_PRESSIONADA 0x00
/* Definições - local de medição da pressão */
#define ALTURA_NIVEL_DO_MAR 685.0 //coloque aqui a altura de sua cidade (em relação ao nível do mar)
#define P0_HPA 1013.0 //hPa
/* Definições - display */
#define TITULO_BARRA_SUPERIOR "Central de controle"
#define LARGURA_TELA 320
#define ALTURA_BARRA_SUPERIOR 28
#define TELA_MARGEM_ESQUERDA 5
#define COR_BARRA_SUPERIOR TFT_DARKCYAN
#define COR_TEXTO_BARRA_SUPERIOR TFT_WHITE
#define COR_TEXTO_TELA TFT_BLACK
#define COR_FUNDO_TELA TFT_WHITE
#define COORD_X_TEMPERATURA 180
#define COORD_Y_TEMPERATURA 90
#define COORD_X_PRESSAO TELA_MARGEM_ESQUERDA
#define COORD_Y_PRESSAO 135
/* Botões de ação */
#define TEXTO_BOTAO_1 "L1"
#define TEXTO_BOTAO_2 "L2"
#define TEXTO_BOTAO_3 "L3"
#define V1_TS1_X 140
#define V1_TS1_Y 233
#define V2_TS1_X 150
#define V2_TS1_Y 238
#define V3_TS1_X 160
#define V3_TS1_Y 233
#define V1_TS2_X 220
#define V1_TS2_Y 233
#define V2_TS2_X 230
#define V2_TS2_Y 238
#define V3_TS2_X 240
#define V3_TS2_Y 233
#define V1_TS3_X 300
#define V1_TS3_Y 233
#define V2_TS3_X 310
#define V2_TS3_Y 238
#define V3_TS3_X 320
#define V3_TS3_Y 233
/* Definições - WiFI */
const char* ssid = " "; //coloque aqui o nome da rede wifi
const char* password = " "; //coloque aqui a senha da rede wifi
/* Variáveis e objetos - display */
TFT_eSPI myGLCD = TFT_eSPI();
/* Variáveis e objetos - MQTT */
#define TOPICO_SUBSCRIBE "wio_terminal_temp_pressao"
#define TOPICO_PUBLISH "wio_terminal_controle_saida"
WiFiClient wifi_Client;
const char* broker_mqtt = "broker.hivemq.com"; /* MQTT broker URL */
int broker_port = 1883; /* MQTT broker port */
PubSubClient MQTT(wifi_Client);
/* Protótipos */
void init_wifi(void);
void conecta_wifi(void);
void verifica_e_conecta_wifi(void);
void init_mqtt(void);
void conecta_mqtt(void);
void verifica_e_conecta_mqtt(void);
void escreve_texto_desconectado(void);
void escreve_texto_conectado(void);
void escreve_temperatura(int temperatura);
void escreve_pressao_previsao_tempo(float pressao_hpa, char pressao_valida);
void desenha_rodape_botoes(void);
void mqtt_callback(char* topic, byte* payload, unsigned int length);
char le_tecla_debounce(int tecla);
void aguarda_tecla_ser_liberada (int tecla);
/*
* Implementações
*/
/* Função: inicializa wi-fi
* Parâmetros: nenhum
* Retorno: nenhum
*/
void init_wifi(void)
{
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(2000);
}
/* Função: conecta wi-fi
* Parâmetros: nenhum
* Retorno: nenhum
*/
void conecta_wifi(void)
{
/* Conecta o wifi */
if (WiFi.status() == WL_CONNECTED)
return;
escreve_texto_desconectado();
Serial.println("Conectando ao WiFI");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println("Conectado ao WiFi");
Serial.print("IP: ");
Serial.println (WiFi.localIP());
}
/* Função: verifica se conexão wifi está ativa e,
* se não estiver, refaz a conexão
* Parâmetros: nenhum
* Retorno: nenhum
*/
void verifica_e_conecta_wifi(void)
{
conecta_wifi();
}
/* Função: inicializa MQTT
* Parâmetros: nenhum
* Retorno: nenhum
*/
void init_mqtt(void)
{
MQTT.setServer(broker_mqtt, broker_port);
MQTT.setCallback(mqtt_callback);
}
/* Função: conecta MQTT
* Parâmetros: nenhum
* Retorno: nenhum
*/
void conecta_mqtt(void)
{
char mqtt_id_randomico[5] = {0};
while (!MQTT.connected())
{
Serial.print("* Tentando se conectar ao broker MQTT: ");
Serial.println(broker_mqtt);
/* gera id mqtt randomico */
randomSeed(random(9999));
sprintf(mqtt_id_randomico, "%ld", random(9999));
if (MQTT.connect(mqtt_id_randomico))
{
Serial.println("Conectado ao broker MQTT com sucesso!");
MQTT.subscribe(TOPICO_SUBSCRIBE);
escreve_texto_conectado();
}
else
{
Serial.println("Falha na tentativa de conexao com broker MQTT.");
delay(100);
}
}
}
/* Função: verifica se conexão MQTT está ativa e,
* se não estiver, refaz a conexão
* Parâmetros: nenhum
* Retorno: nenhum
*/
void verifica_e_conecta_mqtt(void)
{
conecta_mqtt();
}
/* Função: escreve texto de wifi e mqtt desconectado
* Parâmetros: nenhum
* Retorno: nenhum
*/
void escreve_texto_desconectado(void)
{
myGLCD.setTextSize(1);
myGLCD.setTextColor(TFT_RED, COR_FUNDO_TELA);
myGLCD.drawString("Desconectado", TELA_MARGEM_ESQUERDA, 40, 4);
}
/* Função: escreve texto de wifi e mqtt conectado
* Parâmetros: nenhum
* Retorno: nenhum
*/
void escreve_texto_conectado(void)
{
myGLCD.setTextSize(1);
myGLCD.setTextColor(TFT_BLUE, COR_FUNDO_TELA);
myGLCD.drawString("Conectado ", TELA_MARGEM_ESQUERDA, 40, 4);
}
/* Função: escreve temperatura
* Parâmetros: - temperatura
* - valor valido ou nao
* Retorno: nenhum
*/
void escreve_temperatura(int temperatura, char temp_valida)
{
char str_temp[3]={0};
myGLCD.setTextSize(1);
myGLCD.setTextColor(COR_BARRA_SUPERIOR, COR_FUNDO_TELA);
if (temp_valida == NAO)
{
myGLCD.drawString("--", COORD_X_TEMPERATURA, COORD_Y_TEMPERATURA, 8);
}
else
{
sprintf(str_temp, "%02d", temperatura);
myGLCD.drawString(str_temp, COORD_X_TEMPERATURA, COORD_Y_TEMPERATURA, 8);
myGLCD.drawString(".", COORD_X_TEMPERATURA+110, COORD_Y_TEMPERATURA-48, 8);
}
}
/* Função: escreve pressao e previsao do tempo baseado nela
* Parâmetros: - pressao (hpa)
* - valor valido ou nao
* Retorno: nenhum
*/
void escreve_pressao_previsao_tempo(float pressao_hpa, char pressao_valida)
{
char str_temp[10]={0};
float pressao_clima_sol = 0.0;
float diferenca_pressao = 0.0;
myGLCD.setTextSize(1);
myGLCD.setTextColor(TFT_BLACK, COR_FUNDO_TELA);
if (pressao_valida == NAO)
{
myGLCD.drawString("--", COORD_X_PRESSAO, COORD_Y_PRESSAO, 4);
}
else
{
/* Escreve pressão */
sprintf(str_temp, "%.1f hPa", pressao_hpa);
myGLCD.drawString(str_temp, COORD_X_PRESSAO, COORD_Y_PRESSAO, 4);
/* Calcula e escreve previsão do tempo */
pressao_clima_sol = P0_HPA*exp((-1.0*ALTURA_NIVEL_DO_MAR)/7990.0);
diferenca_pressao = pressao_hpa - pressao_clima_sol;
if ( diferenca_pressao > 2.5)
{
/* Sol */
myGLCD.drawString("Sol ", COORD_X_PRESSAO+20, COORD_Y_PRESSAO-25, 2);
myGLCD.fillCircle(COORD_X_PRESSAO + TELA_MARGEM_ESQUERDA, COORD_Y_PRESSAO - 17, 5, TFT_ORANGE);
}
if ( (diferenca_pressao >= -2.5) && (diferenca_pressao <= 2.5) )
{
/* Nublado */
myGLCD.drawString("Nublado ", COORD_X_PRESSAO+20, COORD_Y_PRESSAO-25, 2);
myGLCD.fillCircle(COORD_X_PRESSAO + TELA_MARGEM_ESQUERDA, COORD_Y_PRESSAO - 17, 5, TFT_LIGHTGREY);
}
if ( (diferenca_pressao < -2.5) )
{
/* Chuva */
myGLCD.drawString("Chuva ", COORD_X_PRESSAO+20, COORD_Y_PRESSAO-25, 2);
myGLCD.fillCircle(COORD_X_PRESSAO + TELA_MARGEM_ESQUERDA, COORD_Y_PRESSAO - 17, 5, TFT_BLUE);
}
}
}
/* Função: desenha rodapé (com indicações dos botões de ação)
* Parâmetros: nenhum
* Retorno: nenhum
*/
void desenha_rodape_botoes(void)
{
/* Botão 1 */
myGLCD.drawString(TEXTO_BOTAO_1, V1_TS1_X+5, V1_TS1_Y - 15, 2);
myGLCD.fillTriangle(V1_TS1_X, V1_TS1_Y, V2_TS1_X, V2_TS1_Y, V3_TS1_X, V3_TS1_Y, TFT_BLACK);
/* Botão 2 */
myGLCD.drawString(TEXTO_BOTAO_2, V1_TS2_X+3, V1_TS2_Y - 15, 2);
myGLCD.fillTriangle(V1_TS2_X, V1_TS2_Y, V2_TS2_X, V2_TS2_Y, V3_TS2_X, V3_TS2_Y, TFT_BLACK);
/* Botão 3 */
myGLCD.drawString(TEXTO_BOTAO_3, V1_TS3_X+3, V1_TS3_Y - 15, 2);
myGLCD.fillTriangle(V1_TS3_X, V1_TS3_Y, V2_TS3_X, V2_TS3_Y, V3_TS3_X, V3_TS3_Y, TFT_BLACK);
}
/* Callback MQTT */
void mqtt_callback(char* topic, byte* payload, unsigned int length)
{
String msg;
int temp_lida;
float pressao_lida;
int separador_idx;
//obtem a string do payload recebido
for(int i = 0; i < length; i++)
{
char c = (char)payload[i];
msg += c;
}
separador_idx = msg.indexOf(";");
temp_lida = msg.substring(0,separador_idx).toInt();
pressao_lida = msg.substring(separador_idx+1, msg.length()).toFloat();
escreve_temperatura(temp_lida, SIM);
escreve_pressao_previsao_tempo(pressao_lida, SIM);
}
/* Função: le tecla (com debounce) e, caso o acionamento da
* tecla for confirmado, faz um beep (no buzzer)
* Parâmetros: tecla a ser lida
* Retorno: TECLA_PRESSIONADA
* TECLA_NAO_PRESSIONADA
*/
char le_tecla_debounce(int tecla)
{
char resultado_tecla = TECLA_NAO_PRESSIONADA;
if (digitalRead(tecla) == LOW)
{
/* Aplica debounce para confirmar acionamento da tecla */
delay(150);
if (digitalRead(tecla) == LOW)
{
/* Acionamento confirmado */
analogWrite(WIO_BUZZER, 128);
delay(150);
analogWrite(WIO_BUZZER, 0);
resultado_tecla = TECLA_PRESSIONADA;
}
}
return resultado_tecla;
}
/* Função: aguarda liberação de uma tecla
* Parâmetros: tecla
* Retorno: nenhum
*/
void aguarda_tecla_ser_liberada (int tecla)
{
while (digitalRead(tecla) == LOW);
}
void setup()
{
/* Inicialização - UART de debug */
Serial.begin(SERIAL_DEBUG_BAUDRATE);
/* Inicialização das três teclas inferiores */
pinMode(WIO_KEY_A, INPUT_PULLUP);
pinMode(WIO_KEY_B, INPUT_PULLUP);
pinMode(WIO_KEY_C, INPUT_PULLUP);
/* Inicialização do buzzer */
pinMode(WIO_BUZZER, OUTPUT);
/* Inicialização = display */
myGLCD.init();
myGLCD.setRotation(1);
myGLCD.fillScreen(TFT_WHITE);
myGLCD.setTextSize(1);
myGLCD.fillRect(0, 0, LARGURA_TELA, ALTURA_BARRA_SUPERIOR, COR_BARRA_SUPERIOR);
myGLCD.setTextColor(COR_TEXTO_BARRA_SUPERIOR, COR_BARRA_SUPERIOR);
myGLCD.drawCentreString(TITULO_BARRA_SUPERIOR, 160, 4, 2);
escreve_texto_desconectado();
escreve_temperatura(0, NAO);
escreve_pressao_previsao_tempo(0, NAO);
desenha_rodape_botoes();
/* Inicializa WiFi e MQTT */
init_wifi();
conecta_wifi();
init_mqtt();
conecta_mqtt();
}
void loop()
{
/* Verifica conexões wifi e MQTT.
Se alguma delas não estiver operante, refaz
a conexão.
*/
verifica_e_conecta_wifi();
verifica_e_conecta_mqtt();
/* Verifica se alguma tecla foi pressionada.
Se sim, executa a ação correspondente */
if (le_tecla_debounce(WIO_KEY_C) == TECLA_PRESSIONADA)
{
MQTT.publish(TOPICO_PUBLISH, "L3");
MQTT.loop();
aguarda_tecla_ser_liberada(WIO_KEY_C);
}
if (le_tecla_debounce(WIO_KEY_B) == TECLA_PRESSIONADA)
{
MQTT.publish(TOPICO_PUBLISH, "L2");
MQTT.loop();
aguarda_tecla_ser_liberada(WIO_KEY_B);
}
if (le_tecla_debounce(WIO_KEY_A) == TECLA_PRESSIONADA)
{
MQTT.publish(TOPICO_PUBLISH, "L1");
MQTT.loop();
aguarda_tecla_ser_liberada(WIO_KEY_A);
}
MQTT.loop();
}
Saiba Mais
e-book Coleção ESP32 do Embarcados: Aplicações Low Power com ESP32










