//Noviembre 2021
#include <RTClib.h>
//#include <Wire.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>
#include <FastLED.h>
//Variables & Defines del RTC
//#define DS3231_I2C_ADDR 0x68
//#define DS3231_TEMPERATURE_ADDR 0x11
//RTC_DS3231 RTC;
RTC_DS1307 RTC;
DateTime Reloj;
int mes, dia, annio;
int hora, minuto, segundo;
int temp = 0;
int th_temp = 28; //Temperatura a partir de la que empieza a a encender ventilador (cogida del RTC)
//Variables & Defines del módulo Bluetooth
SoftwareSerial Blue(10,11); // RX, TX
int nueva_fecha;
char seleccion;
int nuevo_anio, nuevo_mes, nuevo_dia, nuevo_hora, nuevo_ms, nuevo_segundo, nuevo_minuto;
bool cambio_hora_bluetooth = 0;
int prev_anio=0, prev_mes = 0, prev_dia = 0, prev_hora = 0, prev_ms = 0;
bool ajustado_b = 1;
//Variables EEPROM
byte adress = 0;
byte encendido;
byte nuevo_encendido;
//Variables Rele
bool rele_on = 0, rele_off = 1;
//Variables Brillo
int luz, brillo;
//Variables & Defines Tiras de LED
#define TiraPIN1 23 //Es el pin al que se debe conectar la tira que se declara con este nombre como argumento
#define TiraPIN2 25
#define TiraPIN3 27
#define TiraPIN4 29
#define TiraPIN5 31
#define TiraPIN6 33
#define TiraPIN7 35
#define TiraPIN8 37
#define TiraPIN9 39
#define TiraPIN10 41
#define TiraPIN11 43
#define TiraPIN12 45
#define TiraPIN13 24
#define TiraPIN14 26
#define TiraPIN15 28
#define TiraPIN16 30
#define TiraPIN17 32
#define TiraPIN18 34
#define TiraPIN19 36
#define TiraPIN20 38
#define TiraPIN21 40
#define TiraPIN22 42
#define TiraPIN23 44
#define TiraPIN24 46
#define nLedsPorTira 10 // Cambiar este valor con el número de pixeles
#define brilloLEDsIni 255 // Brillo de los leds
#define tipoLed WS2812B // Tipo de Led
#define nTiras 24 // Numero de tira
CRGB leds[nTiras][nLedsPorTira];
//Variables Control del programa
#define porcentajeLongitudSegundos 100
#define porcentajeLongitudMinutos 100
#define porcentajeLongitudHoras 50
byte tramo_seg, tramo_min, tramo_hora;
byte tramo_hora_prev, tramo_min_prev, tramo_seg_prev;
byte hora_prev, min_prev, seg_prev; bool cambio_de_hora, cambio_de_minuto, cambio_de_segundo;
bool ajustado = 0;
byte longitud_segundos, longitud_minutos, longitud_horas;
unsigned long ahora, previo, intervalo = 300;
unsigned long milisegundos_evaluar, milisegundos_ahora;
void set_horas(byte tramo_horass, byte longitud_h){
for(byte i = 0; i < longitud_h; i++){ //Medida de la aguja, por el modo en que se actualiza,dependerá de la longitud de las horas y los minutos
leds[tramo_horass][i] = CRGB(165, 0, 0);// 255, 250, 255 Este es el color, para cambiarlo
//hay que cambiar los 3 números, convirtiendo el codigo de color hexadecimal a RGB
}
}
void set_minutos(byte tramo_minn, byte longitud_m){
for(byte i = 0; i < longitud_m; i++){ //Medida de la aguja, por el modo en que se actualiza,dependerá de la longitud de las horas y los minutos
leds[tramo_minn][i] = CRGB(255, 250, 255);// Este es el color, para cambiarlo
//hay que cambiar los 3 números, convirtiendo el codigo de color hexadecimal a RGB
}
}
void set_segundos(byte tramo_segg, byte longitud_s){
for(byte i = 0; i < longitud_s; i++){ // Para cambiar la medida habría que cambiar el 10 por la longitud deseada
leds[tramo_segg][i] = CRGB(0,0,250); // Este es el color, para cambiarlo hay que cambiar
//los 3 números, convirtiendo el codigo de color hexadecimal a RGB
}
}
byte tramo_hora_actual(int hora_actual, int minuto_actual){
byte tramo;
int hora_calculada;
if(minuto_actual >= 30 && minuto_actual < 45){
hora_calculada = (hora_actual * 100) + 30;
}
else if(minuto_actual > 44){
hora_calculada = (hora_actual * 100) + 100;
}
else if(minuto_actual < 30){
hora_calculada = (hora_actual * 100);
}
switch(hora_calculada){
case 0:
tramo = 0;break;
case 30:
tramo = 1;break;
case 100:
tramo = 2;break;
case 130:
tramo = 3;break;
case 200:
tramo = 4;break;
case 230:
tramo = 5;break;
case 300:
tramo = 6;break;
case 330:
tramo = 7;break;
case 400:
tramo = 8;break;
case 430:
tramo = 9;break;
case 500:
tramo = 10;break;
case 530:
tramo = 11;break;
case 600:
tramo = 12;break;
case 630:
tramo = 13;break;
case 700:
tramo = 14;break;
case 730:
tramo = 15;break;
case 800:
tramo = 16;break;
case 830:
tramo = 17;break;
case 900:
tramo = 18;break;
case 930:
tramo = 19;break;
case 1000:
tramo = 20;break;
case 1030:
tramo = 21;break;
case 1100:
tramo = 22;break;
case 1130:
tramo = 23;break;
case 1200:
tramo = 0;break;
}
return tramo;
}
byte tramo_minuto_actual(int minuto_actual, int segundo_actual, byte tramo_actual_min){
int minutos_para_calculo;
if(segundo_actual > 30){
minutos_para_calculo = (minuto_actual * 10)+ 5;
}
else{
minutos_para_calculo = (minuto_actual * 10);
}
if((minutos_para_calculo % 25) == 0){
tramo_actual_min = minutos_para_calculo / 25;
}
if(tramo_actual_min == 0 && minuto_actual != 0){
tramo_actual_min = minuto_actual/2.5;
}
return tramo_actual_min;
}
byte tramo_segundo_actual(int segundo_actual, byte tramo_actual_segundo){
if(segundo_actual*10 % 25 == 0){
tramo_actual_segundo = segundo_actual * 10 / 25;
}
if((segundo_actual*10 + 5) % 25 == 0){
tramo_actual_segundo = (segundo_actual * 10 +5)/ 25;
}
if(segundo_actual != 0 && tramo_actual_segundo == 0){
tramo_actual_segundo = segundo_actual / 2.5;
}
return tramo_actual_segundo;
}
byte zeller(int anio, byte mess, byte ddia) {
anio -= (mess <= 2) ? 1 : 0;
mess += (mess <=2) ? 12 : -2;
int a = anio % 100;
int b = anio / 100;
return
(
700 + ( (26 * mess - 2) / 10 ) + ddia + a +
a / 4 + b / 4 - 2 * b
) % 7 ;
}
float DS3231_get_treg()
{
int rv; // Reads the temperature as an int, to save memory
// float rv;
uint8_t temp_msb, temp_lsb;
int8_t nint;
// Wire.beginTransmission(DS3231_I2C_ADDR);
// Wire.write(DS3231_TEMPERATURE_ADDR);
Wire.endTransmission();
// Wire.requestFrom(DS3231_I2C_ADDR, 2);
temp_msb = Wire.read();
temp_lsb = Wire.read() >> 6;
if ((temp_msb & 0x80) != 0)
nint = temp_msb | ~((1 << 8) - 1); // if negative get two's complement
else
nint = temp_msb;
rv = 0.25 * temp_lsb + nint;
return rv;
}
void setup() {
Serial.begin(9600);
Blue.begin(9600);
Wire.begin();
RTC.begin();
encendido = EEPROM.read(adress);
//RTC.adjust(DateTime(2021,11,20,6,17,55)); //Aqui se cambia la fecha entera, en orden: año, mes, dia, hora minuto y segundo,
//la primera vez que se resetee el reloj.Se deberá subir el programa con esta instrucción pero sin las barras de comentario
//y volver a subir el programa de nuevo pero con la sentencia comentada
FastLED.addLeds<tipoLed, TiraPIN1, GRB>(leds[0], nLedsPorTira); //Declaramos las tiras de leds que tenemos
FastLED.addLeds<tipoLed, TiraPIN2, GRB>(leds[1], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN3, GRB>(leds[2], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN4, GRB>(leds[3], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN5, GRB>(leds[4], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN6, GRB>(leds[5], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN7, GRB>(leds[6], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN8, GRB>(leds[7], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN9, GRB>(leds[8], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN10, GRB>(leds[9], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN11, GRB>(leds[10], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN12, GRB>(leds[11], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN13, GRB>(leds[12], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN14, GRB>(leds[13], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN15, GRB>(leds[14], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN16, GRB>(leds[15], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN17, GRB>(leds[16], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN18, GRB>(leds[17], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN19, GRB>(leds[18], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN20, GRB>(leds[19], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN21, GRB>(leds[20], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN22, GRB>(leds[21], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN23, GRB>(leds[22], nLedsPorTira);
FastLED.addLeds<tipoLed, TiraPIN24, GRB>(leds[23], nLedsPorTira);
FastLED.setBrightness(brilloLEDsIni); //Seteamos el brillo que hemos definido
FastLED.clear(); // Limpiamos los datos de los leds
for(int j = 0; j < nTiras; j++){ // Hacemos una animación que encenderá los leds 1 a 1, empezando con la 1a tira y acabando con la última
for(int i = 0; i < nLedsPorTira; i++){
leds[j][i] = CRGB::White;
FastLED.show();
delay(5);
}
}
FastLED.clear();
pinMode(4, OUTPUT); //PIN PARA EL RELE--------------------
pinMode(22, OUTPUT); //PIN PARA RELE VENTILADOR
if (!RTC.begin()) {
Serial.println("RTC No encontrado");
while (1);
}
Reloj = RTC.now();
hora = Reloj.hour();
minuto = Reloj.minute();
segundo = Reloj.second();
mes = Reloj.month();
dia = Reloj.day();
longitud_horas = nLedsPorTira * (float(porcentajeLongitudHoras) / float(100)); //Cálculo de la longitud de cada aguja
longitud_minutos = nLedsPorTira * (float(porcentajeLongitudMinutos) / float(100));
longitud_segundos = nLedsPorTira * (float(porcentajeLongitudSegundos) / float(100));
Serial.print("Longitud Agujas Horas: ");Serial.println(longitud_horas);
Serial.print("Longitud Agujas Minutos: ");Serial.println(longitud_minutos);
Serial.print("Longitud Agujas Segundos: ");Serial.println(longitud_segundos);
}
void loop() {
while(Blue.available() && cambio_hora_bluetooth == 0){
seleccion = Blue.read();
cambio_hora_bluetooth = 1;
Serial.print("Selec: ");
Serial.println(seleccion);
}
if(cambio_hora_bluetooth == 1){
switch(seleccion){
case 'A':
while(Blue.available()){
if(prev_anio == 0){
nuevo_anio = Blue.parseInt();
Serial.println("-");
Serial.println(nuevo_anio);
if(nuevo_anio != 0){
prev_anio = prev_anio + 1;
cambio_hora_bluetooth = 0;
Reloj = RTC.now();
hora = Reloj.hour();
minuto = Reloj.minute();
segundo = Reloj.second();
mes = Reloj.month();
dia = Reloj.day();
RTC.adjust(DateTime(nuevo_anio,mes,dia,hora,minuto,segundo));
break;
}
}
}
break;
case 'M':
while(Blue.available()){
if(prev_mes == 0){
nuevo_mes = Blue.parseInt();
Serial.println("-");
Serial.println(nuevo_mes);
if(nuevo_mes != 0){
prev_mes = prev_mes + 1;
cambio_hora_bluetooth = 0;
Reloj = RTC.now();
hora = Reloj.hour();
minuto = Reloj.minute();
segundo = Reloj.second();
annio = Reloj.year();
dia = Reloj.day();
RTC.adjust(DateTime(annio,nuevo_mes,dia,hora,minuto,segundo));
break;
}
}
}
break;
case 'D':
while(Blue.available()){
if(prev_dia == 0){
nuevo_dia = Blue.parseInt();
Serial.println("-");
Serial.println(nuevo_dia);
if(nuevo_dia != 0){
prev_dia = prev_dia + 1;
cambio_hora_bluetooth = 0;
Reloj = RTC.now();
hora = Reloj.hour();
minuto = Reloj.minute();
segundo = Reloj.second();
annio = Reloj.year();
mes = Reloj.month();
RTC.adjust(DateTime(annio,mes,nuevo_dia,hora,minuto,segundo));
break;
}
}
}
break;
case 'H':
while(Blue.available()){
if(prev_hora == 0){
nuevo_hora = Blue.parseInt();
Serial.println("-");
Serial.println(nuevo_hora);
if(nuevo_hora != 0){
prev_hora = prev_hora + 1;
cambio_hora_bluetooth = 0;
Reloj = RTC.now();
dia = Reloj.day();
minuto = Reloj.minute();
segundo = Reloj.second();
annio = Reloj.year();
mes = Reloj.month();
RTC.adjust(DateTime(annio,mes,dia,nuevo_hora,minuto,segundo));
break;
}
}
}
break;
case 'S':
while(Blue.available()){
if(prev_ms == 0){
nuevo_ms = Blue.parseInt();
Serial.println("-");
Serial.println(nuevo_ms);
if(nuevo_ms != 0){
prev_ms = prev_ms + 1;
cambio_hora_bluetooth = 0;
nuevo_minuto = nuevo_ms / 100;
nuevo_segundo = nuevo_ms - (nuevo_minuto * 100);
Reloj = RTC.now();
dia = Reloj.day();
annio = Reloj.year();
hora = Reloj.hour();
mes = Reloj.month();
RTC.adjust(DateTime(annio,mes,dia,hora,nuevo_minuto,nuevo_segundo));
break;
}
}
}
break;
default:
cambio_hora_bluetooth = 0;
break;
}
}
ahora = millis();
if(ahora-previo > intervalo){
temp = DS3231_get_treg();
Serial.print("Temperatura Leída: ");Serial.println(temp);
if(temp > th_temp){
digitalWrite(22, HIGH);
}
else{
digitalWrite(22, LOW);
}
Reloj = RTC.now();
hora = Reloj.hour();
minuto = Reloj.minute();
segundo = Reloj.second();
annio = Reloj.year();
mes = Reloj.month();
dia = Reloj.day();
if(hora >= 12){
hora = hora - 12;
}
tramo_hora = tramo_hora_actual(hora, minuto);
tramo_min = tramo_minuto_actual(minuto, segundo, tramo_min);
tramo_seg = tramo_segundo_actual(segundo, tramo_seg);
Serial.print(annio);Serial.print(" / ");Serial.print(mes); Serial.print(" / ");Serial.print(dia);
Serial.print(" Hora: ");Serial.print(hora);Serial.print(" : ");Serial.print(minuto);
Serial.print(" : ");Serial.println(segundo);
previo = millis();
}
if(tramo_seg != tramo_seg_prev){
FastLED.clearData();
luz = analogRead(A0);//Serial.println(luz);
brillo = map(luz, 0, 1023, 100, 255);//Serial.println(brillo);
FastLED.setBrightness(255);
if(tramo_seg != tramo_hora){
set_segundos(tramo_seg, longitud_segundos);
}
set_minutos(tramo_min, longitud_minutos);
set_horas(tramo_hora, longitud_horas);
FastLED.show();
if((rele_off == 1 && ( hora == 5/*NUMERO DE HORA ACTIVACION*/ && minuto == 5/*NUMERO DE MINUTO ACTIVACION*/)) || (rele_off==1 && encendido==1)){
digitalWrite(21, HIGH);
rele_off = 0;
rele_on = 1;
nuevo_encendido = 1;
EEPROM.write(adress, nuevo_encendido); //Guardamos en la EEPROM el nuevo número de cápsulas
encendido = nuevo_encendido;
}
else if((rele_on == 1 && ( hora == 5/*NUMERO DE HORA DESACTIVACION*/ && minuto == 6/*NUMERO DE MINUTO DESACTIVACION*/)) || (rele_off == 0 && encendido == 0)){
digitalWrite(21, LOW);
rele_off = 1;
rele_on = 0;
nuevo_encendido = 0;
EEPROM.write(adress, nuevo_encendido); //Guardamos en la EEPROM el nuevo número de cápsulas
encendido = nuevo_encendido;
}
if(zeller(annio, mes, dia) == 0 && 31 - dia < 7 && (mes == 3 || mes == 10) ) {
if(hora == 2 && mes == 3){
RTC.adjust(DateTime(annio,mes,dia,hora + 1,minuto,segundo)); Serial.println("+1");
}
else if(hora == 3 && mes == 10 && ajustado == 0){
RTC.adjust(DateTime(annio,mes,dia,hora - 1,minuto,segundo)); Serial.println("-1");
ajustado = 1;
}
if(ajustado == 1 && hora == 4 && mes == 10){
ajustado = 0;
}
}
}
tramo_seg_prev = tramo_seg;
}