Relógio em Tempo Real com Arduino para Horários de Oração Islâmica
Componentes e Materiais
| Arduino UNO | 1 |
| Display Nokia 5110 | 1 |
| RTC DS1307 (Seeed Pi RTC) | 1 |
Ferramentas Necessárias
- Fios jumper macho/macho premium (40 x 75mm)
- Protoboard 400 pinos
Aplicativos e Serviços Online
- Arduino IDE
Sobre o Projeto
Este é um relógio em tempo real capaz de exibir a data gregoriana e os horários diários de oração. Para este circuito simples, precisamos de um Arduino UNO (ou qualquer placa Arduino), um RTC DS1307 e um LCD Nokia 5110.
Materiais
Arduino UNO
O Arduino Uno é uma placa microcontroladora open-source baseada no microcontrolador ATmega328P. Possui conjuntos de GPIOs analógicos e digitais para interface com sensores, atuadores e outras placas.
- 14 pinos digitais de entrada/saída (6 como saídas PWM)
- 6 entradas analógicas
- Resonador cerâmico de 16 MHz
- 32 KB Flash (0.5 KB usado pelo bootloader)
- 2 KB SRAM, 1 KB EEPROM
- Jack de alimentação DC e porta USB
DS1307
O DS1307 é um relógio/calendário serial de tempo real (RTC) de baixo consumo, totalmente em decimal codificado binário (BCD). Fornece segundos, minutos, horas, dia, data, mês e ano. Ajusta automaticamente o fim do mês para meses com menos de 31 dias, incluindo correções para ano bissexto. Opera em formato 24h ou 12h com indicador AM/PM. Possui circuito de detecção de energia que muda automaticamente para bateria reserva.
Pinos do DS1307:
- VCC, GND: Alimentação DC
- SCL: Entrada de clock serial para sincronização
- SDA: Entrada/saída de dados serial (open drain, requer pull-up externo)
- SQW/OUT: Saída de onda quadrada (1Hz, 4kHz, 8kHz, 32kHz) quando habilitado
- X1, X2: Conexões para cristal de quartzo 32.768kHz
Display Nokia 5110
Display monocromático 84x48 pixels com backlight, controlador PCD8544 (mesmo do Nokia 3310), interface serial tipo SPI.
Pinout do Nokia 5110:
- VCC, GND: Alimentação
- RST: Reset do display (ativo baixo)
- CE (Chip Enable): Seleção de dispositivo (ativo baixo)
- D/C (Data/Command): HIGH para dados, LOW para comando
- DIN: Dados seriais SPI
- CLK: Clock SPI
- BL (Backlight): Controle de brilho (pode usar PWM nos pinos 3, 5, 6, 9, 10, 11)
Como Editar o Programa
Você deve adaptar a linha 161 do código:
calcPrayerTimes(year, month, dayOfMonth, 41.3, 20.6, 3, -18.5, -19, fajr, sunRise, zuhr, asr, maghrib, isha);
Os parâmetros necessários são:
- Longitude/Latitude/Fuso Horário do local desejado
- Ângulos de Fajr e Isha (variam conforme método de cálculo do país)
Obtenha as coordenadas geográficas da sua cidade no site IslamicFinder. Procure sua cidade e anote latitude, longitude, ângulo de Isha e ângulo de Fajr.
Como o Programa Funciona
A função recebe dados de Ano/Mês/Dia/Longitude/Latitude/FusoHorário/FajrTwilight/IshaTwilight mais 6 referências a variáveis double (Fajr/SunRise/Zuhr/Asr/Maghrib/Isha) para retornar os horários calculados. Inclui funções auxiliares para conversões (graus/radianos).
Exemplo para Cairo:
- Longitude: 30.2
- Latitude: 30
- Fuso Horário: +2
- Fajr Twilight: -19.5
- Isha Twilight: -17.5
A linha 161 ficaria:
calcPrayerTimes(year, month, dayOfMonth, 30.2, 30, 2, -19.5, -17.5, fajr, sunRise, zuhr, asr, maghrib, isha);
Os horários retornados são "double" e devem ser convertidos para formato de hora. A função doubleToHrMin (antes de calcPrayerTimes) separa o número em Horas e Minutos.
Não esqueça de deixar um joinha se achar útil!
PS: O algoritmo de cálculo de horários de oração foi escrito por Mahmoud Adly Ezzat. Leia mais no blog dele.
Código
#include "Wire.h"
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
int xegg, yegg;
#define DS1307_I2C_ADDRESS 0x68
long previousMillis = 0;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
long interval = 200;
int displayx, displayy, displayradius, x2, y2, x3, y3;
int zero = 0;
char *Day[] = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
double fajr, sunRise, zuhr, asr, maghrib, isha;
// Converte decimal para BCD
byte decToBcd(byte val) { return ((val / 10 * 16) + (val % 10)); }
// Converte BCD para decimal
byte bcdToDec(byte val) { return ((val / 16 * 10) + (val % 16)); }
// Obtém data/hora do DS1307
void getDateDs1307() {
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
second = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0x3f);
dayOfWeek = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
}
void setDateDs1307() {
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(zero);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void printTime() {
int hours, minutes;
char s[12];
display.clearDisplay();
display.setCursor(0, 16);
display.print(Day[dayOfWeek]);
display.print(":");
display.print(char(dayOfMonth / 10 + 0x30));
display.print(char(dayOfMonth % 10 + 0x30));
display.print("/");
display.print(char(month / 10 + 0x30));
display.print(char(month % 10 + 0x30));
display.print("/");
display.print("20");
display.print(char(year / 10 + 0x30));
display.print(char(year % 10 + 0x30));
display.setCursor(18, 26);
display.print(char(hour / 10 + 0x30));
display.print(char(hour % 10 + 0x30));
display.print(":");
display.print(char(minute / 10 + 0x30));
display.print(char(minute % 10 + 0x30));
display.print(":");
display.print(char(second / 10 + 0x30));
display.print(char(second % 10 + 0x30));
display.display();
delay(1000);
doubleToHrMin(fajr, hours, minutes);
display.clearDisplay();
display.setCursor(1, 1);
display.print("Fajr "); display.print(hours); display.print(":"); display.print(minutes);
display.display();
doubleToHrMin(zuhr, hours, minutes);
display.setCursor(1, 10);
display.print("Zuhr "); display.print(hours); display.print(":"); display.print(minutes);
display.display();
doubleToHrMin(asr, hours, minutes);
display.setCursor(1, 20);
display.print("Asr "); display.print(hours); display.print(":"); display.print(minutes);
display.display();
doubleToHrMin(maghrib, hours, minutes);
display.setCursor(1, 30);
display.print("Maghrib "); display.print(hours); display.print(":"); display.print(minutes);
display.display();
doubleToHrMin(isha, hours, minutes);
display.setCursor(1, 40);
display.print("Isha "); display.print(hours); display.print(":"); display.print(minutes);
display.display();
delay(5000);
}
void setup() {
Wire.begin();
display.begin();
display.clearDisplay();
display.setContrast(25);
xegg = (display.width()) / 2;
yegg = (display.height()) / 2;
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor(22, 18);
display.print("Hatem");
display.display();
delay(500);
display.setCursor(24, 28);
display.print("ZEHIR");
display.display();
delay(500);
getDateDs1307();
}
void loop() {
getDateDs1307();
calcPrayerTimes(year, month, dayOfMonth, 39.8, 21.4, 3, -18.5, -19, fajr, sunRise, zuhr, asr, maghrib, isha);
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
printTime();
}
}
/*-------------------------------------------------------------------------------------*/
// CÁLCULO DE HORÁRIOS DE ORAÇÃO (por Mahmoud Adly Ezzat, Cairo)
// Converte Graus para Radianos
double degToRad(double degree) { return ((3.1415926 / 180) * degree); }
// Converte Radianos para Graus
double radToDeg(double radian) { return (radian * (180 / 3.1415926)); }
// Garante valor entre 0 e 360
double moreLess360(double value) {
while (value > 360 || value < 0) {
if (value > 360) value -= 360;
else if (value < 0) value += 360;
}
return value;
}
// Garante valor entre 0 e 24
double moreLess24(double value) {
while (value > 24 || value < 0) {
if (value > 24) value -= 24;
else if (value < 0) value += 24;
}
return value;
}
// Converte double para Horas e Minutos
void doubleToHrMin(double number, int &hours, int &minutes) {
hours = floor(moreLess24(number));
minutes = floor(moreLess24(number - hours) * 60);
}
void calcPrayerTimes(int year, int month, int day, double longitude, double latitude, int timeZone, double fajrTwilight, double ishaTwilight, double &fajrTime, double &sunRiseTime, double &zuhrTime, double &asrTime, double &maghribTime, double &ishaTime) {
double D = (367 * year) - ((year + (int)((month + 9) / 12)) * 7 / 4) + (((int)(275 * month / 9)) + day - 730531.5);
double L = 280.461 + 0.9856474 * D; L = moreLess360(L);
double M = 357.528 + (0.9856003) * D; M = moreLess360(M);
double Lambda = L + 1.915 * sin(degToRad(M)) + 0.02 * sin(degToRad(2 * M)); Lambda = moreLess360(Lambda);
double Obliquity = 23.439 - 0.0000004 * D;
double Alpha = radToDeg(atan((cos(degToRad(Obliquity)) * tan(degToRad(Lambda))))); Alpha = moreLess360(Alpha);
Alpha = Alpha - (360 * (int)(Alpha / 360));
Alpha = Alpha + 90 * (floor(Lambda / 90) - floor(Alpha / 90));
double ST = 100.46 + 0.985647352 * D;
double Dec = radToDeg(asin(sin(degToRad(Obliquity)) * sin(degToRad(Lambda))));
double Durinal_Arc = radToDeg(acos((sin(degToRad(-0.8333)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
double Noon = Alpha - ST; Noon = moreLess360(Noon);
double UT_Noon = Noon - longitude;
// Cálculo dos Horários de Oração
// 2) Zuhr [Meio-dia local]
zuhrTime = UT_Noon / 15 + timeZone;
// Asr Hanafi
double Asr_Alt = radToDeg(atan(1.7 + tan(degToRad(latitude - Dec))));
double Asr_Arc = radToDeg(acos((sin(degToRad(90 - Asr_Alt)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
Asr_Arc = Asr_Arc / 15;
// 3) Asr
asrTime = zuhrTime + Asr_Arc;
// 1) Shorouq (Nascer do sol)
sunRiseTime = zuhrTime - (Durinal_Arc / 15);
// 4) Maghrib
maghribTime = zuhrTime + (Durinal_Arc / 15);
double Esha_Arc = radToDeg(acos((sin(degToRad(ishaTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
// 5) Isha
ishaTime = zuhrTime + (Esha_Arc / 15);
// 0) Fajr
double Fajr_Arc = radToDeg(acos((sin(degToRad(fajrTwilight)) - sin(degToRad(Dec)) * sin(degToRad(latitude))) / (cos(degToRad(Dec)) * cos(degToRad(latitude)))));
fajrTime = zuhrTime - (Fajr_Arc / 15);
return;
}
Esquemático
Diagrama de conexões do circuito.
Processo de manufatura
- Relógio POV com Arduino: Construa um Display LED de Persistência de Visão
- Construa um Relógio Retrô Numitron com Arduino: Simples, Confiável e Eficiente
- Relógio de Palavras DIY com Arduino – Construa um Display Elegante de Tempo Real
- Construa um Relógio Mestre LED Personalizado com Alarme – Visível a 12 Metros
- Mealheiro Inteligente: Controlar Aceitador de Moedas com Arduino Nano
- Monitor de Temperatura e Relógio Tempo Real com Arduino Due e Display TFT 3.2"
- Controlar um LED via Bluetooth com Arduino – Guia DIY Simples
- Como Exibir Imagens em LCD TFT 1.17" com Arduino UNO
- Construa um Relógio Despertador Confiável com RTC DS1302 e Arduino UNO
- Controle de Ventoinha PWM 4 Pinos 25 kHz com Arduino Uno – Montagem, Código e Teste