RELÓGIO DESPERTADOR MELHORADO!? COM RÁDIO FM E ESTAÇÃO METEOROLÓGICA!
Vídeo deste Projeto no nosso canal do YouTube:
Um dos nossos artigos mais vistos aqui no blog é o despertador com o Arduino, mas, apesar disso, achamos que estava incompleto, e a solução foi juntar dois projetos interessantíssimos: a estação meteorológica e o rádio FM.
- Material Necessário
Para este projeto, vamos precisar dos seguintes materiais:
Imagem | Produto | Comprar |
---|---|---|
LilyGo TTGO V1.4 ESP32 | ||
Breadboard 830 Pinos | ||
Módulo Rádio TEA5767 | ||
4 Botões de Pressão | ||
4 Resistências de 1K | ||
LCD 16×2 I2C | ||
Jumpers Macho-Macho | ||
Jumpers Macho-Fêmea |
- API WorldTimeAPI (Documentação)
Esta será a API responsável por nos fornecer os dados de hora e data. Para o GET request, apenas é preciso aceder ao link com a seguinte composição:
http://worldtimeapi.org/api/timezone/America/Argentina/Salta
no nosso caso:
http://worldtimeapi.org/api/timezone/Europe/Lisbon
- API OpenWeatherMapAPI (Documentação)
Esta API será responsável por fornecer as informações do estado do tempo. Esta, porém, não é tão direta como a anterior, pelo que é preciso registar na plataforma e obter uma chave única, utilizada posteriormente no código.
- Montagem do Circuito
No que toca à montagem, vamos apenas utilizar a comunicação I2C entre o LCD e a ESP32, ligando o pino SCL ao pino 22 da ESP e o pino SDA ao pino 21 da mesma placa. No que toca aos botões e ao buzzer ativo, ligamos os mesmos à ESP32 desta forma:
- Botão Menu -> Pino 19
- Botão Confirmação -> Pino 18
- Botão Anterior -> Pino 2
- Botão Avançar -> Pino 5
- Buzzer -> Pino 15
- Arduino IDE
Para terminar, basta abrirmos o Arduino IDE, e compilarmos o código do projeto. Para isso, vamos instalar as seguintes livrarias:
-
- Livraria LiquidCrystal_I2C -> Para o LCD
- Livraria WiFi.h -> Previamente instalada com as placas ESP32
- Livraria HttpClient.h -> Para efetuar os pedidos GET aos servidores
- Livraria Arduino_JSON.h -> Para descodificar o payload recebido pelos servidores
Código
/*Código para o Projeto: Relógio Despertador com Meteorologia e Rádio FM - Material necessário: -> Placa ESP32 LilyGo TTGO V1.4 -> Breadboard -> LCD I2C 20x4 -> Módulo Rádio FM TEA5767 -> Buzzer Ativo -> 4 Botões de Pressão com 4 Resistências em configuração Pull-Up Resistor -> Jumper Macho-Fêmea Todo o material pode ser adquirido a partir do artigo do nosso blog deste projeto! *****************************************************LIGAÇÕES****************************************************** Vamos utilizar apenas a comunicação I2C entre o LCD, o módulo TEA5767 e a ESP32, ligando o pino SCL ao pino 22 da ESP e o pino SDA ao pino 21 da mesma placa. Vamos ligar o botão de menu ao pino 19, o botão de confirmação ao pino 18, o botão "anterior" ao pino 2 e o botão "avançar" ao pino 5. Resta ligar o buzzer ao pino 15 da ESP32. ******************************************************************************************************************* Para mais informações sobre o projeto: www.electrofun.pt/blog/relogio-despertador-melhorado-com-radio-fm-e-estacao-meteorologica Electrofun@2022 ----> www.electrofun.pt */ #define pinoBotaoMenu 19 #define pinoBotaoConfirmacao 18 #define pinoBotaoAnterior 2 #define pinoBotaoAvancar 5 #define pinoBuzzer 15 #include <LiquidCrystal_I2C.h> #include <WiFi.h> #include <HTTPClient.h> #include <Arduino_JSON.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27, 20, 4); TaskHandle_t Task1; const char* SSID_WIFI = "SSID"; //Inserir a SSID da sua rede local const char* PASSWORD_WIFI = "PASSWORD"; //Inserir a password da sua rede local String openWeatherMapAPIKey = "API_KEY"; //Inserir a chave da API da meteorologia String codigoPaisTempo = "PT"; String cidadeTempo = "Gaia"; String estadoTempo, dataTimeString, temperaturaString, temperaturaArredString; String dayNow, monthNow, yearNow, hourNow, minuteNow, secondNow; String minutoAntigo = "61"; bool atualizarLCD = false; int debouce = 200; int horaAlarme = 12; int minutoAlarme = 30; int hourNowInt, minuteNowInt; int estadoBotaoMenu, estadoBotaoConfirmacao, estadoBotaoAnterior, estadoBotaoAvancar; bool alarmeAcionado = false; bool alarmeAtivado = false; bool estadoRadio = false; float estacaoRadio = 107.2; byte simboloSino[] = { B01110, B01110, B11111, B11111, B11111, B11111, B00000, B00100 }; byte setaDireita[] = { B10000, B11000, B11100, B11111, B11111, B11110, B11000, B10000 }; byte setaEsquerda[] = { B00001, B00011, B00111, B11111, B11111, B01111, B00011, B00001 }; void setup() { pinMode(pinoBuzzer, OUTPUT); pinMode(pinoBotaoMenu, INPUT); pinMode(pinoBotaoConfirmacao, INPUT); pinMode(pinoBotaoAnterior, INPUT); pinMode(pinoBotaoAvancar, INPUT); Wire.begin(); Serial.begin(115200); WiFi.begin(SSID_WIFI, PASSWORD_WIFI); Serial.print("A ligar à rede Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(300); } Serial.println(); Serial.print("Conexão bem sucedida. IP: "); Serial.println(WiFi.localIP()); xTaskCreatePinnedToCore(atualizarDadosTempo, "Task1", 10000, NULL, 1, &Task1, 0); controlarRadio(estadoRadio, estacaoRadio); lcd.begin(); lcd.backlight(); lcd.setCursor(3, 0); lcd.print("Alarmuino V2.0"); lcd.setCursor(0, 1); lcd.print("Relogio Despertador"); lcd.setCursor(4, 2); lcd.print("com Arduino"); lcd.setCursor(1, 3); lcd.print("by Electrofun@2022"); delay(5000); lcd.clear(); } void atualizarDadosTempo( void * pvParameters ) { for (;;) { String updateWeatherPath = "http://api.openweathermap.org/data/2.5/weather?q=" + cidadeTempo + "," + codigoPaisTempo + "&lang=pt&units=metric&APPID=" + openWeatherMapAPIKey; String dataTimePath = "http://worldtimeapi.org/api/timezone/Europe/Lisbon"; if (WiFi.status() == WL_CONNECTED) { String weatherRequest = httpGETRequest(updateWeatherPath.c_str()); String dataTimeRequest = httpGETRequest(dataTimePath.c_str()); JSONVar weatherContentJSON = JSON.parse(weatherRequest); JSONVar dataTimeContentJSON = JSON.parse(dataTimeRequest); if (JSON.typeof(weatherContentJSON) == "undefined" || JSON.typeof(dataTimeContentJSON) == "undefined") { Serial.println("Não foi possível descodificar o JSON!"); return; } temperaturaString = JSON.stringify(weatherContentJSON["main"]["temp"]); temperaturaArredString = temperaturaString.substring(0, 4); String weatherContentString = JSON.stringify(weatherContentJSON["weather"]); //Serial.println(temperaturaString); int indexDescription = weatherContentString.indexOf("description"); int indexIcon = weatherContentString.indexOf("icon"); estadoTempo = weatherContentString.substring(indexDescription + 14, indexIcon - 3); estadoTempo.replace("é", "e"); estadoTempo[0] = toupper(estadoTempo[0]); //Serial.println(estadoTempo); dataTimeString = JSON.stringify(dataTimeContentJSON["datetime"]); int indexT = dataTimeString.indexOf("T"); String dataTimeNow = dataTimeString.substring(1, indexT); dayNow = dataTimeNow.substring(8, 12); monthNow = dataTimeNow.substring(5, 7); yearNow = dataTimeNow.substring(0, 4); //Serial.print(dayNow); //Serial.print("/"); //Serial.print(monthNow); //Serial.print("/"); //Serial.println(yearNow); String timeNow = dataTimeString.substring(indexT + 1, indexT + 9); hourNow = timeNow.substring(0, 2); minuteNow = timeNow.substring(3, 5); secondNow = timeNow.substring(6, 8); //Serial.print(hourNow); //Serial.print(":"); //Serial.print(minuteNow); //Serial.print(":"); //Serial.println(secondNow); } else { Serial.println("WiFi Desconectado"); } if (alarmeAcionado == 1) { digitalWrite(pinoBuzzer, HIGH); delay(100); digitalWrite(pinoBuzzer, LOW); } else { digitalWrite(pinoBuzzer, LOW); } vTaskDelay(100 / portTICK_PERIOD_MS); } } void loop() { if (minutoAntigo != minuteNow || atualizarLCD == true) { funcaoAtualizarLCD(); minutoAntigo = minuteNow; atualizarLCD = false; } hourNowInt = hourNow.toInt(); minuteNowInt = minuteNow.toInt(); //Serial.println(hourNowInt); //Serial.println(minuteNowInt); if (hourNowInt == horaAlarme && minuteNowInt == minutoAlarme && alarmeAtivado == 1) { alarmeAcionado = 1; } estadoBotaoMenu = digitalRead(pinoBotaoMenu); if (estadoBotaoMenu == 1) { delay(debouce); menu1Alarme(); } } void funcaoAtualizarLCD() { lcd.setCursor(0, 0); lcd.print("Hora: "); lcd.print(hourNow); lcd.print(":"); lcd.print(minuteNow); lcd.setCursor(11, 0); lcd.print("||"); if (horaAlarme < 10) { lcd.print("0"); lcd.print(horaAlarme); } else { lcd.print(horaAlarme); } lcd.print(":"); if (minutoAlarme < 10) { lcd.print("0"); lcd.print(minutoAlarme); } else { lcd.print(minutoAlarme); } if (alarmeAtivado == 1) { lcd.createChar(3, simboloSino); lcd.setCursor(19, 0); lcd.write(3); } lcd.setCursor(0, 1); lcd.print("Temp: "); lcd.print(temperaturaArredString); lcd.print(char(223)); lcd.print("C"); lcd.setCursor(0, 2); lcd.print(estadoTempo); lcd.setCursor(14, 2); lcd.setCursor(0, 3); lcd.print("Radio: "); if (estadoRadio == 0) { lcd.print("OFF"); } else if (estadoRadio == 1) { lcd.print("ON"); lcd.setCursor(14, 3); lcd.print(estacaoRadio); } } void menu1Alarme() { lcd.clear(); lcd.setCursor(5, 0); lcd.print("1 - Alarme"); if (alarmeAtivado == 1) { lcd.setCursor(7, 2); lcd.print("Ligado"); } else if (alarmeAtivado == 0) { lcd.setCursor(5, 2); lcd.print("Desligado"); } lcd.createChar(1, setaEsquerda); lcd.setCursor(0, 3); lcd.write(1); lcd.createChar(2, setaDireita); lcd.setCursor(19, 3); lcd.write(2); do { estadoBotaoMenu = digitalRead(pinoBotaoMenu); estadoBotaoConfirmacao = digitalRead(pinoBotaoConfirmacao); estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); } while (estadoBotaoMenu == 0 && estadoBotaoConfirmacao == 0 && estadoBotaoAnterior == 0 && estadoBotaoAvancar == 0); if (estadoBotaoConfirmacao == 1) { delay(debouce); alarmeAtivado = !alarmeAtivado; if (!alarmeAtivado) { alarmeAcionado = false; } atualizarLCD = true; menu1Alarme(); } else if (estadoBotaoAnterior == 1) { delay(debouce); definirFrequenciaRadio(); } else if (estadoBotaoAvancar == 1) { delay(debouce); menu2Alarme(); } else if (estadoBotaoMenu == 1) { delay(debouce); lcd.clear(); atualizarLCD = true; return; } } void menu2Alarme() { lcd.clear(); lcd.setCursor(1, 0); lcd.print("2 - Definir Alarme"); if (horaAlarme < 10) { lcd.setCursor(7, 2); lcd.print("0"); lcd.setCursor(8, 2); lcd.print(horaAlarme); } else { lcd.setCursor(7, 2); lcd.print(horaAlarme); } lcd.setCursor(9, 2); lcd.print(":"); if (minutoAlarme < 10) { lcd.setCursor(10, 2); lcd.print("0"); lcd.setCursor(11, 2); lcd.print(minutoAlarme); } else { lcd.setCursor(10, 2); lcd.print(minutoAlarme); } lcd.setCursor(0, 3); lcd.write(1); lcd.setCursor(19, 3); lcd.write(2); do { estadoBotaoMenu = digitalRead(pinoBotaoMenu); estadoBotaoConfirmacao = digitalRead(pinoBotaoConfirmacao); estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); } while (estadoBotaoMenu == 0 && estadoBotaoConfirmacao == 0 && estadoBotaoAnterior == 0 && estadoBotaoAvancar == 0); if (estadoBotaoConfirmacao == 1) { delay(debouce); definirAlarme(); } else if (estadoBotaoAnterior == 1) { delay(debouce); menu1Alarme(); } else if (estadoBotaoAvancar == 1) { delay(debouce); menu3Radio(); } else if (estadoBotaoMenu == 1) { delay(debouce); lcd.clear(); atualizarLCD = true; return; } } void definirAlarme() { lcd.clear(); lcd.setCursor(1, 0); lcd.print("2 - Definir Alarme"); //Definir Hora Alarme do { if (horaAlarme < 10) { lcd.setCursor(7, 2); lcd.print("0"); lcd.setCursor(8, 2); lcd.print(horaAlarme); } else { lcd.setCursor(7, 2); lcd.print(horaAlarme); } lcd.setCursor(9, 2); lcd.print(":"); if (minutoAlarme < 10) { lcd.setCursor(10, 2); lcd.print("0"); lcd.setCursor(11, 2); lcd.print(minutoAlarme); } else { lcd.setCursor(10, 2); lcd.print(minutoAlarme); } estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); if (estadoBotaoAvancar == 1) { delay(debouce); horaAlarme++; if (horaAlarme > 23) { horaAlarme = 0; } } else if (estadoBotaoAnterior == 1) { delay(debouce); horaAlarme--; if (horaAlarme < 0) { horaAlarme = 23; } } } while (digitalRead(pinoBotaoConfirmacao) == 0); delay(debouce); //Definir Minutos Alarme do { if (horaAlarme < 10) { lcd.setCursor(7, 2); lcd.print("0"); lcd.setCursor(8, 2); lcd.print(horaAlarme); } else { lcd.setCursor(7, 2); lcd.print(horaAlarme); } lcd.setCursor(9, 2); lcd.print(":"); if (minutoAlarme < 10) { lcd.setCursor(10, 2); lcd.print("0"); lcd.setCursor(11, 2); lcd.print(minutoAlarme); } else { lcd.setCursor(10, 2); lcd.print(minutoAlarme); } estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); if (estadoBotaoAvancar == 1) { delay(debouce); minutoAlarme++; if (minutoAlarme > 59) { minutoAlarme = 0; } } else if (estadoBotaoAnterior == 1) { delay(debouce); minutoAlarme--; if (minutoAlarme < 0) { minutoAlarme = 59; } } } while (digitalRead(pinoBotaoConfirmacao) == 0); delay(debouce); atualizarLCD = true; lcd.clear(); } void menu3Radio() { lcd.clear(); lcd.setCursor(5, 0); lcd.print("3 - Radio"); if (estadoRadio == 0) { lcd.setCursor(9, 2); lcd.print("OFF"); } else if (estadoRadio == 1) { lcd.setCursor(9, 2); lcd.print("ON"); lcd.setCursor(7, 3); lcd.print(estacaoRadio); } lcd.setCursor(0, 3); lcd.write(1); lcd.setCursor(19, 3); lcd.write(2); do { estadoBotaoMenu = digitalRead(pinoBotaoMenu); estadoBotaoConfirmacao = digitalRead(pinoBotaoConfirmacao); estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); } while (estadoBotaoMenu == 0 && estadoBotaoConfirmacao == 0 && estadoBotaoAnterior == 0 && estadoBotaoAvancar == 0); if (estadoBotaoConfirmacao == 1) { delay(debouce); estadoRadio = !estadoRadio; controlarRadio(estadoRadio, estacaoRadio); atualizarLCD = true; lcd.clear(); } else if (estadoBotaoAnterior == 1) { delay(debouce); menu2Alarme(); } else if (estadoBotaoAvancar == 1) { delay(debouce); definirFrequenciaRadio(); } else if (estadoBotaoMenu == 1) { delay(debouce); lcd.clear(); atualizarLCD = true; return; } } void definirFrequenciaRadio() { lcd.clear(); lcd.setCursor(1, 0); lcd.print("4 - Definir Radio"); lcd.setCursor(7, 3); lcd.print(estacaoRadio); lcd.setCursor(0, 3); lcd.write(1); lcd.setCursor(19, 3); lcd.write(2); do { estadoBotaoMenu = digitalRead(pinoBotaoMenu); estadoBotaoConfirmacao = digitalRead(pinoBotaoConfirmacao); estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); } while (estadoBotaoMenu == 0 && estadoBotaoConfirmacao == 0 && estadoBotaoAnterior == 0 && estadoBotaoAvancar == 0); if (estadoBotaoConfirmacao == 1) { delay(debouce); do { lcd.setCursor(7, 3); lcd.print(estacaoRadio); estadoBotaoAnterior = digitalRead(pinoBotaoAnterior); estadoBotaoAvancar = digitalRead(pinoBotaoAvancar); if (estadoBotaoAvancar == 1) { delay(debouce); estacaoRadio = estacaoRadio + 0.10; if (estacaoRadio > 107.9) { lcd.clear(); estacaoRadio = 88.9; lcd.setCursor(1, 0); lcd.print("4 - Definir Radio"); lcd.setCursor(7, 3); lcd.print(estacaoRadio); lcd.setCursor(0, 3); lcd.write(1); lcd.setCursor(19, 3); lcd.write(2); } } else if (estadoBotaoAnterior == 1) { delay(debouce); estacaoRadio = estacaoRadio - 0.10; if (estacaoRadio < 88.9) { lcd.clear(); estacaoRadio = 107.9; lcd.setCursor(1, 0); lcd.print("4 - Definir Radio"); lcd.setCursor(7, 3); lcd.print(estacaoRadio); lcd.setCursor(0, 3); lcd.write(1); lcd.setCursor(19, 3); lcd.write(2); } } } while (digitalRead(pinoBotaoConfirmacao) == 0); controlarRadio(estadoRadio, estacaoRadio); delay(debouce); atualizarLCD = true; lcd.clear(); } else if (estadoBotaoAnterior == 1) { delay(debouce); menu3Radio(); } else if (estadoBotaoAvancar == 1) { delay(debouce); menu1Alarme(); } else if (estadoBotaoMenu == 1) { delay(debouce); lcd.clear(); atualizarLCD = true; return; } } String httpGETRequest(const char* serverName) { WiFiClient client; HTTPClient http; http.begin(client, serverName); int httpResponseCode = http.GET(); String payload = "{}"; if (httpResponseCode > 0) { payload = http.getString(); } else { Serial.println("Não foi possível efetuar o GET Request"); Serial.print("URL do Servidor: "); Serial.println(serverName); Serial.print("Código de Erro: "); Serial.println(httpResponseCode); } http.end(); return payload; } void controlarRadio(bool estado, float frequencia) { unsigned int frequencyB = 4 * (frequencia * 1000000 + 225000) / 32768; byte frequencyH = frequencyB >> 8; byte frequencyL = frequencyB & 0XFF; if (estado) { Wire.beginTransmission(0x60); Wire.write(frequencyH); Wire.write(frequencyL); Wire.write(0xB0); Wire.write(0x10); Wire.write(0x00); Wire.endTransmission(); delay(100); } else { Wire.beginTransmission(0x60); Wire.write(frequencyH); Wire.write(frequencyL); Wire.write(10110110); Wire.write(0x10); Wire.write(0x00); Wire.endTransmission(); delay(100); } }
Não se esqueçam de ver o nosso vídeo sobre este artigo no nosso canal do YouTube:
Para mais projetos, percorram o nosso blog, onde podem encontrar vários artigos interessantes relacionados com eletrónica, robótica e muito mais! Visitem também o nosso site, onde encontram tudo para eletrónica e robótica!