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!
Comments
Comentários