#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>
const int timbreLargo = 8000;
const int timbreCorto = 4000;
const int timbreCorto1 = 2500;
unsigned long t = 0;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#define NOP __asm__ __volatile__("nop\n\t") //62.5ns en 16MHz
//RTC_DS3231 rtc;
RTC_DS1307 rtc;
const char daysOfTheWeek [7][4] = {"Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"};
byte rx = 0, offset = 0;
byte datos[6];
bool Timbre = false;
struct timbre_e {
byte hora;
byte minutos;
uint32_t duracion; // en mseg
};
// datos de hora, minutos y duracion en mseg de disparo del timbre
const timbre_e datosTimbre[] = {
{7, 0, timbreLargo},
{7, 40, timbreCorto},
{8, 20, timbreLargo},
{8, 30, timbreLargo},
{9, 0, timbreCorto1},
{9, 10, timbreCorto},
{9, 30, timbreCorto1},
{9, 50, timbreLargo},
{10, 0, timbreLargo},
{10, 40, timbreCorto},
{11, 20, timbreLargo},
{11, 30, timbreLargo},
{12, 10, timbreCorto},
{12, 23, timbreCorto},
{12, 33, timbreLargo},
{12, 36, timbreCorto},
{14, 20, timbreLargo},
{14, 30, timbreLargo},
{15, 10, timbreCorto1},
{15, 40, timbreCorto1},
{15, 50, timbreLargo},
{16, 00, timbreLargo},
{16, 40, timbreCorto},
{17, 20, timbreLargo},
{17, 30, timbreLargo},
{22, 15, timbreLargo}
};
byte timbreIndex = 0;
byte numTimbres = sizeof(datosTimbre) / sizeof(datosTimbre[0]);
// ------------------------------------------------------------
// verifica cual es la siguiente alarma (por si hubo un reset o ajuste de hora)
void verificar_proxima_alarma() {
DateTime now = rtc.now ();
// pasa hora y minutos actual a minutos para facilitar la comparación
int tmp = now.hour() * 60 + now.minute();
byte i = 0;
while (i < numTimbres) {
if(datosTimbre[i].hora * 60 + datosTimbre[i].minutos > tmp) {
break;
}
i++;
}
timbreIndex = i;
if (timbreIndex == numTimbres) timbreIndex = 0;
}
// ------------------------------------------------------------
void setup() {
Serial.begin(115200);
lcd.begin (16, 2);
delay (3000);
if (!rtc.begin()) {
Serial.println (F("Opssss!!!... no encuentro el RTC!!!"));
while (1);
}
pinMode (2, OUTPUT);
digitalWrite (2, LOW);
verificar_proxima_alarma();
lcd.clear();
}
void loop() {
if (Serial.available()) {
Timbre = true;
rx = (uint8_t) Serial.read();
datos [offset] = rx;
offset ++;
if (offset == 6 ) {
rtc.adjust (DateTime (datos[0] + 2000, datos[1], datos[2], datos[3], datos[4], datos[5]));
offset = 0;
Timbre = false;
verificar_proxima_alarma();
}
}
DateTime now = rtc.now ();
lcd.setCursor (0, 0);
lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
lcd.print (" ");
if (now.day() < 10) lcd.print(0);
lcd.print(now.day());
lcd.print('/');
if (now.month() < 10) lcd.print(0);
lcd.print(now.month());
lcd.print('/');
lcd.print(now.year());
lcd.setCursor(0, 1);
if (now.hour() < 10) lcd.print(0);
lcd.print(now.hour());
lcd.print(':');
if (now.minute() < 10) lcd.print(0);
lcd.print (now.minute());
lcd.print(':');
if (now.second() < 10) lcd.print(0);
lcd.print(now.second());
if (now.dayOfTheWeek() == 0 || now.dayOfTheWeek() == 6) { //chequea sabado y domingo
Serial.println (F("Sabado o domingo"));
} else { //si es dia de semana
//********************************************************************************************************
if (Timbre == false) {
if (now.hour() == datosTimbre[timbreIndex].hora && now.minute() == datosTimbre[timbreIndex].minutos && now.second() <= 1) {
//Activar timbre
Serial.println(F("Timbre ON"));
digitalWrite(2, HIGH);
Timbre = true;
t = millis();
}
} else {
if ( millis() - t > datosTimbre[timbreIndex].duracion ) {
Serial.println(F("Timbre OFF"));
digitalWrite (2, LOW);
Timbre = false;
timbreIndex++;
if (timbreIndex == numTimbres) timbreIndex = 0;
}
}
}
//##################################################################################################
delay(1000);
}