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

 

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

 

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:

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!