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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
#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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
#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