Go Down

Topic: DS3231 retraso de tiempo (Read 329 times) previous topic - next topic

fmreja

Feb 18, 2017, 12:48 pm Last Edit: Feb 18, 2017, 01:23 pm by fmreja
Hola a todos!!

Tengo un problema con el DS3231 y por más que he leído en el foro no he encontrado algo como lo que parece que es mi problema, os comento:

Estoy haciendo un sistema con un arduino "Elegoo UNO R3", un reloj DS3231 y una pantalla de 20x4. Consiste en hacer una simulación de amanecer y atardecer para los pájaros.

En la aplicación se establece una hora de comienzo y de fin tanto para el amanecer como para el atardecer en el cual una tira de leds se va encendiendo o apagando progresivamente. Mientras esto ocurre en la pantalla veo la hora del sistema, las horas de inicio y fin del amanecer y del atardecer y el estado del sistema (Espera, amaneciendo, atardeciendo).

Bueno, voy al problema, que me lio: durante las ejecuciones de amanecer o atardecer me di cuenta de que lo hacía en tiempo aproximado, pero no exacto. Probé a poner la hora, minutos y segundos en el monitor serie del ordenador y me fije que cada 10-12 segundo se saltaba uno. No sé si es por el retardo del sistema al ir leyendo la hora del reloj y ejecutar otras instrucciones, si es por el arduino que no es original...

¿Podéis echarme una mano?

Os pego el código, aunque es un tocho, disculpad si no es adecuado ponerlo así.

Un saludo y muchas gracias

Code: [Select]

#include <Wire.h>
#include "RTClib.h"
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x3f
LiquidCrystal_I2C             lcd(I2C_ADDR,2, 1, 0, 4, 5, 6, 7);

RTC_DS3231 rtc;
RTC_DS3231 rtc2;
int tiraleds1=3;

int horaInicioAmanecer=11;
int minutosInicioAmanecer=16;
int horaFinAmanecer=11;
int minutosFinAmanecer=21;


int horaInicioAtardecer=11;
int minutosInicioAtardecer=19;
int horaFinAtardecer=11;
int minutosFinAtardecer=22;

int estado=0;


void setup () {

 Serial.begin(9600);
 pinMode(tiraleds1, OUTPUT);

   if (! rtc.begin()) {
   Serial.println("Couldn't find RTC");
   while (1);
 }
 if (! rtc2.begin()) {
   Serial.println("Couldn't find RTC");
   while (1);
 }

 lcd.begin (20,4);    // Inicializar el display con 20 caraceres 4 lineas
 //lcd.setBacklightPin(3,POSITIVE);
 lcd.setBacklight(HIGH);

 
}

void loop () {
   DateTime now = rtc.now();

   horaSistema(now, horaInicioAmanecer, minutosInicioAmanecer, horaFinAmanecer, minutosFinAmanecer,
   horaInicioAtardecer, minutosInicioAtardecer, horaFinAtardecer, minutosFinAtardecer, estado );

   if (horaInicioAmanecer==now.hour() && minutosInicioAmanecer==now.minute()){
     amanecer (now, horaInicioAmanecer, minutosInicioAmanecer, horaFinAmanecer, minutosFinAmanecer, estado);
     }

   if (horaInicioAtardecer==now.hour() && minutosInicioAtardecer==now.minute()){
     atardecer (now, horaInicioAtardecer, minutosInicioAtardecer, horaFinAtardecer, minutosFinAtardecer, estado);
     }





 Serial.print(now.hour());
 Serial.print(':');
 Serial.print(now.minute());
 Serial.print(':');
 Serial.print(now.second());
 Serial.println();
 delay(1000);
   
 
}

static double calcularDelay (int horaInicio, int minutosInicio, int horaFin, int minutosFin){

 int totalMinutosInicio, totalMinutosFin;
 double tiempoPaso, tiempoPasoMills;

 totalMinutosInicio=(horaInicio*60)+minutosInicio;         //Pasar a minutos la hora de inicio
 Serial.print(totalMinutosInicio);
 Serial.println();
 totalMinutosFin=(horaFin*60)+minutosFin;                  //Pasar a minutos la hora de fin
 Serial.print(totalMinutosFin);
 Serial.println();
 tiempoPaso=(totalMinutosFin-totalMinutosInicio);          //Calcular el número de minutos del proceso de amanecer
 Serial.print(tiempoPaso);
 Serial.println();
 tiempoPaso=tiempoPaso*60*1000;                           //Pasar a milisegundos los minutos del proceso de amanecer
 Serial.print(tiempoPaso);
 Serial.println();
 tiempoPasoMills=tiempoPaso/255;                           //Calcular el tiempo de "delay" que tendra la función amanecer  
 Serial.print(tiempoPasoMills);
 Serial.println();
 return tiempoPasoMills;
 

}

static void amanecer(DateTime now, int horaInicioAmanecer, int minutosInicioAmanecer, int horaFinAmanecer, int minutosFinAmanecer, int estado){

 double delayCalculado= calcularDelay(horaInicioAmanecer, minutosInicioAmanecer, horaFinAmanecer, minutosFinAmanecer);
 estado=1;

 for (int i=0; i<=255; i++){
   horaSistema (now, horaInicioAmanecer, minutosInicioAmanecer, horaFinAmanecer, minutosFinAmanecer,
   horaInicioAtardecer, minutosInicioAtardecer, horaFinAtardecer, minutosFinAtardecer, estado);
   
   analogWrite(tiraleds1, i);
   Serial.println(i);
   
   delay(delayCalculado);
   }

   analogWrite(tiraleds1, 0);
   estado=0;
   
 
 }

 

static void atardecer(DateTime now, int horaInicioAtardecer, int minutosInicioAtardecer, int horaFinAtardecer, int minutosFinAtardecer, int estado){

 double delayCalculado= calcularDelay(horaInicioAtardecer, minutosInicioAtardecer, horaFinAtardecer, minutosFinAtardecer);
 estado=2;
 for (int j=255; j>=0; j--){
   horaSistema (now, horaInicioAmanecer, minutosInicioAmanecer, horaFinAmanecer, minutosFinAmanecer,
   horaInicioAtardecer, minutosInicioAtardecer, horaFinAtardecer, minutosFinAtardecer, estado);
   
   analogWrite(tiraleds1, j);
   Serial.println(j);
   
   delay(delayCalculado);
   }
  estado=0;
 }

static void horaSistema(DateTime now, int horaInicioAmanecer, int minutosInicioAmanecer, int horaFinAmanecer, int minutosFinAmanecer,  
int horaInicioAtardecer, int minutosInicioAtardecer, int horaFinAtardecer, int minutosFinAtardecer, int estado){

 DateTime now2 = rtc2.now();
   
   // línea 0
   lcd.print("                  ");
   lcd.setCursor ( 0, 0 );
   lcd.print("Hora sistema");
   lcd.setCursor ( 15, 0 );
   lcd.print(now2.hour());
   lcd.setCursor ( 17, 0 );
   lcd.print(":");
   lcd.setCursor ( 18, 0 );
   lcd.print(now2.minute());

 //línea 1
 //lcd.print("                  ");
 lcd.setCursor ( 0, 1 );
 lcd.print("Amanec");
 lcd.setCursor (8, 1 );
 lcd.print(horaInicioAmanecer);
 lcd.setCursor ( 10, 1 );
 lcd.print(":");
 lcd.setCursor ( 11, 1 );
 lcd.print(minutosInicioAmanecer);
 lcd.setCursor ( 13, 1 );
 lcd.print("-");
 lcd.setCursor ( 14, 1 );
 lcd.print(horaFinAmanecer);
 lcd.setCursor ( 16, 1 );
 lcd.print(":");
 lcd.setCursor ( 17, 1 );
 lcd.print(minutosFinAmanecer);
 
 //línea 2
// lcd.print("                  ");
 lcd.setCursor ( 0, 2 );
 lcd.print("Atardec");
 lcd.setCursor ( 8, 2 );
 lcd.print(horaInicioAtardecer);
 lcd.setCursor ( 10, 2 );
 lcd.print(":");
 lcd.setCursor ( 11, 2 );
 lcd.print(minutosInicioAtardecer);
 lcd.setCursor ( 13, 2 );
 lcd.print("-");
 lcd.setCursor ( 14, 2 );
 lcd.print(horaFinAtardecer);
 lcd.setCursor ( 16, 2 );
 lcd.print(":");
 lcd.setCursor ( 17, 2 );
 lcd.print(minutosFinAtardecer);
 

 //linea 3
 if (estado==0){
   lcd.setCursor ( 0, 3 );
   lcd.print("                  ");
   lcd.setCursor ( 0, 3 );
   lcd.print("Estado: Espera");
 }

 if (estado==1){
   lcd.setCursor ( 0, 3 );
   lcd.print("                  ");
   lcd.setCursor ( 0, 3 );
   lcd.print("Estado: Amanecer");
 }

 if (estado==2){
   lcd.setCursor ( 0, 3 );
   lcd.print("                  ");
   lcd.setCursor ( 0, 3 );
   lcd.print("Estado: Atardecer");
 }

}

noter

#1
Feb 18, 2017, 09:54 pm Last Edit: Feb 18, 2017, 09:57 pm by noter
Hola.
Creo que tu programa tiene un enfoque demasiado lineal. Piensa que aunque el microprocesador sólo puede hacer una cosa a la vez, las puede hacer muy deprisa. No lo tengas haciendo delays cuando puede hacer cosas más provechosas. ¿No te parecería mejor planteamiento algo así?
  • Leo hora del RTC
  • Comparo segundo actual con el último segundo guardado. Si no ha cambiado, vuelvo al paso 1, pues no hay nada que actualizar.
  • Como ha cambiado de segundo, guardo ese valor como valor de último segundo, y ejecuto los cálculos.
  • Calculo, en base a la hora, en qué fase estoy, y qué valor de analogWrite corresponde a esa hora.
  • Escribo los datos de fase, hora, etc., en pantalla y el analogWrite calculado.
Para no volverte loco con los cálculos de analogWrite, cuando estés en amanecer, convierte la hora actual a segundos transcurridos desde el inicio del amanecer, y haciendo un mapeo de los segundos transcurridos, los que durará todo el amanecer, y 0-255, obtendrás el valor para tu analogWrite. Para el anochecer el proceso equivalente.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy