Go Down

Topic: delay 7 dias es posible? (Read 548 times) previous topic - next topic

felipin

Hola amigos:

Me estoy iniciando en este mundo y tengo algunas dudas:


- Necesito que la placa Arduino active y desactive unos relé con un delay de 7 días, es decir que al séptimo día se apague un rele y se encienda el otro y así con un total de 4 reles

1)    ¿se puede agregar un delay de tanto tiempo? ¿habrá algún inconveniente con eso? he visto solo
        ejemplos con intervalos de segundos.

2)    debido a que cada rele estará activo por 7 días y en el caso que se pierda la electricidad en el sexto
       día, ¿en vez de reiniciarse es posible que continué del día que se perdió la electricidad?

Se los agradezco!!  :)

RIG

Hola Bienvenido
En cuanto a tu pregunta si se puede agregar un delay de 7 dias, la respuesta es claro que se puede, incluso muchos mas
Quote
¿habrá algún inconveniente con eso?
Que bueno que hiciste esta pregunta porque tienes un gran problema si usas un delay tan grande, esto es que durante 7 días tu arduino no hará nada de nada, solo esperar a que transcurra ese tiempo, dicho en otras palabras: estará bloqueado durante 7 días

Quote
en el caso que se pierda la electricidad en el sexto
       día, ¿en vez de reiniciarse es posible que continué del día que se perdió la electricidad?
De la forma que lo planteas, con el uso de delay no es posible.


En tu caso creo que lo mas recomendable sera que uses un RTC, mira estos videos:

Como se usa un RTC

Como automatizar

Tambien te recomiendo que le heches un ojo a la funcion millis() Aqui puedes descargar un pdf que explica muy bien esta funcion   para que aprendas a evitar en lo posible el uso del delay

felipin

Te agradezco la respuesta RIG! vere lo que me recomiendas.

surbyte

Ya te contestaron 1 asi que no vale la pena insistir.
Odio delay por la razón antes expuesta. Detiene al arduino y deja de ser un elemento que puede hacer cosas y observar su entorno para convertirse en una máquina si/no por 7 dias. mas alla del punto 2.

Quote
2)    debido a que cada rele estará activo por 7 días y en el caso que se pierda la electricidad en el sexto
       día, ¿en vez de reiniciarse es posible que continué del día que se perdió la electricidad?
Claro que es posible.

Bueno, no das muchos datos sobre la tarea.
podria suponer que quieres que este 7 dias funcionando pero no que comience a un horario determinado asi que lo del RTC no lo comparto pero se puede justificar si quieres que transcurran 7 dias exactos desde el momento en que se presionó el botón.

Supongamos que tu vienes y presionas un botón y desde ese instante quieres 7 dias completos.
Bien.. eso se logra con delay() aunque no nos gusta y/o con millis()

Pero millis() igual que delay se ven afectados por un corte de energía.
Si se cortara la energía por un día, con un pequeño truco que guardara la información del tiempo transcurrido hasta el corte en la EEPROM potrías al volver a tener energía calcular cuando queda y entonces volver a accionar el rele por ese tiempo restante.

Pero si lo que buscas son 7 dias exactos desde el momento del accionamiento del botón, entonces requieres alguna forma de reloj sea RTC, NTP via WIFI o ETHERNET, u otro medio.

Espero te sirva la respueta.

felipin

#4
May 27, 2018, 02:22 am Last Edit: May 27, 2018, 10:42 pm by surbyte
Surbyte:

Agradezco tu respuesta mira:

La función es simple el rele debe mantener funcionando una bomba hidráulica por 7 días y al séptimo día desactivarla y activar la bomba 2 luego de 7 días activar la bomba 3 y luego la 4 con la simple razón de que se ocupen de forma pareja.

Tu me dices que generando un código que guarde la información en la EEPROM, luego de forma automática al volver la corriente volveria a trabajar la misma bomba respetando el tiempo transcurrido?










surbyte

BIen entonces es mas simple todavía porque hablas de funcionamiento parejo de las bombas.
No hace falta ser estricto, pero si poner un límite como has dicho de 7 dias.
Entonces llevas el tiempo de ambas bombas y en función de como se vayan cumpliendo activas la que este despareja.

Entonces lo que vas a almacenar son los valores de cuanto tiempo llevan funcionando una y otra bomba y cambias cuando se alcancen los 7 dias. Yo lo haría dia a dia, total que lo impide?

En fin son criterios. Ademas las bombas no trabajan todo el tiempo sino que lo hacen hasta que se llena el tanque. Supongamos que hablas de un edificio que tiene dos bombas de agua.
Entonces arranca 1... y carga y esta funcionado por x minutos por ejemplo. Al siguiente ciclo podrias hacer que la segunda bomba equilibre las cuentas hasta el mismo tiempo o bien que acumulen horas como tu lo estas pensando 1 o 7 dias. Sería lo mismo.



felipin

#6
May 30, 2018, 02:33 am Last Edit: May 30, 2018, 05:30 am by surbyte
Así es, finalmente obtuve un modulo RTC y una pantalla, con la pantalla no tengo problemas pero contar días con el modulo RTC me tiene complicado, nose como dejar fija una fecha de inicio de una bomba para comenzar a contar los días (7) y todo en función del RTC para que siga contando incluso en cortes de corriente, si me puedes dar alguna orientación o recomendarme alguna librería para ir estudiando te lo agradecería. Saludos.



surbyte

Y yo te dije que necesitabas  un RTC? No. Te sugerí usar el millis() porque lo único que quieres hacer es llevar la cuenta del tiempo.

Contar tiempo con un RTC no es tan fácil, implica el uso de la libreria Time que te permite hacer operaciones.
Aca tienes la librería y mira este ejemplo TimeRTCLog.ino

Code: [Select]
/*
 * TimeRTCLogger.ino
 * example code illustrating adding and subtracting Time.
 *
 * this sketch logs pin state change events
 * the time of the event and time since the previous event is calculated and sent to the serial port.
 */

#include <TimeLib.h>  // https://github.com/PaulStoffregen/Time
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

const int nbrInputPins  = 6;             // monitor 6 digital pins
const int inputPins[nbrInputPins] = {2,3,4,5,6,7};  // pins to monitor
boolean state[nbrInputPins] ;            // the state of the monitored pins
time_t  prevEventTime[nbrInputPins] ;    // the time of the previous event

void setup()  {
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to sync the time from the RTC
  for (int i=0; i < nbrInputPins; i++) {
     pinMode( inputPins[i], INPUT);
     // uncomment these lines if pull-up resistors are wanted
     // pinMode( inputPins[i], INPUT_PULLUP);
     // state[i] = HIGH;
  }
}

void loop()
{
   for (int i=0; i < nbrInputPins; i++) {
     boolean val = digitalRead(inputPins[i]);
     if (val != state[i]) {
        time_t duration = 0; // the time since the previous event
        state[i] = val;
        time_t timeNow = now();
        if (prevEventTime[i] > 0) {
           // if this was not the first state change, calculate the time from the previous change
           duration = timeNow - prevEventTime[i];
        }
        logEvent(inputPins[i], val, timeNow, duration );  // log the event
        prevEventTime[i] = timeNow;                       // store the time for this event
     }
   }
}

void logEvent( int pin, boolean state, time_t timeNow, time_t duration)
{
   Serial.print("Pin ");
   Serial.print(pin);
   if (state == HIGH) {
      Serial.print(" went High at ");
   } else {
     Serial.print(" went  Low at ");
   }
   showTime(timeNow);
   if (duration > 0) {
     // only display duration if greater than 0
     Serial.print(", Duration was ");
     showDuration(duration);
   }
   Serial.println();
}


void showTime(time_t t)
{
  // display the given time
  Serial.print(hour(t));
  printDigits(minute(t));
  printDigits(second(t));
  Serial.print(" ");
  Serial.print(day(t));
  Serial.print(" ");
  Serial.print(month(t));
  Serial.print(" ");
  Serial.print(year(t));
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void showDuration(time_t duration)
{
  // prints the duration in days, hours, minutes and seconds
  if (duration >= SECS_PER_DAY) {
     Serial.print(duration / SECS_PER_DAY);
     Serial.print(" day(s) ");
     duration = duration % SECS_PER_DAY;
  }
  if (duration >= SECS_PER_HOUR) {
     Serial.print(duration / SECS_PER_HOUR);
     Serial.print(" hour(s) ");
     duration = duration % SECS_PER_HOUR;
  }
  if (duration >= SECS_PER_MIN) {
     Serial.print(duration / SECS_PER_MIN);
     Serial.print(" minute(s) ");
     duration = duration % SECS_PER_MIN;
  }
  Serial.print(duration);
  Serial.print(" second(s) ");
}



Puedes ver como se efectúan operaciones con los tiempos. Es la única forma de hacerlo. Estudia bien el ejemplo.


GO_zalo

creo que te están complicando un poco con el tema de contar las horas...

si has comprado un rtc usa la función   Alarm.alarmRepeat para hacer una alarma cada domingo por ejemplo

Luego cuando llegue el domingo y arduino ejecute la función asociada solo tienes que leer la eeprom, value = EEPROM.read(1); por ejemplo para saber que bomba esta en marcha y poner la siguiente, y claro actualizar tu valor de eeprom para que la próxima vez sepa donde se quedo EEPROM.write(1, value+1); y claro si value llega al máximo de reles lo devuelves a 0

el RTC y el uso de eeprom solucionan el tema de que te quedes sin batería.

la pantalla ni la necesitas

si es una bomba que esta en marcha para mantener presión a un circuito, no se puedes estar poniendo y parando cada día y es mejor hacerlo cada semana, otra cosa es que fuera una bomba que se pusiera bajo demanda

felipin

#9
Jun 07, 2018, 03:02 am Last Edit: Jun 15, 2018, 02:14 am by surbyte Reason: Códigos y errores con etiquetas
Gracias GO_ zalo

El problema es que las bombas deben durar 8 dias encendidas cada una y no empezar un dia de la semana especifico y si alguna falla se debe activar la bomba siguiente, ademas de no reiniciarse si se corta la luz, lograr programar eso me ha costado por las siguientes razones:


si opero con el RTC y trabajo en función de los días definiendo por ejemplo:

Code: [Select]

rele[4]=8,9,10,11;

void setup {

diadeinicio=now.day, (//now.day me entrega el numero del dia actual)
}

void loop{

if (now.day-diadeinicio<=8) {

  digitalWrite(rele[0],high);}

else  {

digitalWrite(rele[0],low);
diadeinicio=now.day;
  
}

if (now.day-diadeinicio<=8) {

  digitalWrite(rele[1],high);}

else  {

digitalWrite(rele[1],low);
diadeinicio=now.day;
  
}


y asi hasta llegar a la cuarta bomba, (ojo no es el código es solo para mostrar lo que quiero hacer)

EL PROBLEMA  esta que si resto dias va a llegar un momento de cambio de mes y reinicio de dias donde me daran valores negativos por ejemplo hoy es 6 y el inicio de esta bomba fue el 31 entonces 6-31= -25, y eso no esta bien.

ademas de hacer que cuando a un pin le llegue un high de error se detenga y se active la bomba de la posición siguiente, esta difícil la cosa, acepto mas sugerencias. Saludos.

surbyte

O sea que lo que yo estaba haciendo estaba bien encaminado pero la idea de Go_zalo era simple y buena.

GO_zalo

Fácil

Si el resultado es negativo entonces los días que han pasado son diasdelmes-diainicio+now.day()

Los días del mes los puedes almacenar en un array. El mes actual lo lees del etc con getMonth()

Fallara los años bisiestos

Entonces lees el año y si es bisiesto sumas un día

Recuerda que los años bisiestos son divisible entres 4, excepto aquellos divisibles entre 100 pero no entre 400

Espero que te sirva de ayuda

Go Up