Contador de horas para un motor a combustion

Hola,

Soy nuevo en el foro, necesito ayuda para hacer un cuenta horas para el mantenimiento de un motor a combustión.

Yo use la función millis() para cronometrar el tiempo de encendido del motor, pero no se como hacer para que se guarde en la memoria EEPROM de arduino el ultimo valor de tiempo tomado y de esta manera cada vez que se encienda dicho motor se acumulen las horas de funcionamiento.

Saludos

agrego el código que utilice para econtar minutos por ejemplo, pero al apagar arduino y encenderlo de nuevo la cuenta se inicia de 0.

[#include "U8glib.h"
U8GLIB_ST7920_128X64_4X u8g(18, 16, 17);
#include <EEPROM.h>//Se incluye la librería EEPROM

int hora=0;
int minut=0;
int seg=0;
long milisegundos;
long tprev=0;


int minutosacumuladoas=0;
int horasparamantenimiento=0;
int direccion=2;
int cuentaminutos=0;

void setup() {
 cuentaminutos=EEPROM.read(direccion);//Guardamos en la variable contador el valor almacenado en la dirección elegida. 

}

void loop() {
// aca hacemos un cronometro con la funcion millis
 milisegundos= (millis())-tprev;
 seg=milisegundos/1000;
 
 if (seg>59)
  {seg=0;
  tprev=millis();
  minut= minut + 1;
 }
if (minut>59)
 {minut=0;
 hora=hora+1;
 }

cuentaminutos= cuentaminutos + minut;

EEPROM.write(direccion, cuentaminutos);//Guardamos el valor en la dirección de la EEPROM elegida



 u8g.firstPage();  
 do {
   u8g.setContrast (150); 
   u8g.setFont(u8g_font_5x7);
   u8g.setPrintPos(5,20);
   u8g.print(cuentaminutos);
   u8g.setPrintPos(5,35);
   u8g.print(minut);
   } 
 while( u8g.nextPage() );
 
 
 delay(1000); 

}[table]
[tr]
[td][/td]
[/tr]
[/table]]

Hola Hugo Buenas tardes, te expongo varias cosas:

1.- Te va a morder el administrador del foro, por favor postea el código como se debe dentro de las etiquetas

....tu código aquí....

. Esto según las normas del foro.

2.- De donde tomas la señal de encendido del motor para activar el contador?. 3.- Seria muy simple usar una memoria de 2k seria mas que suficiente para tu proyecto. La 24C02 te serviría y es muy barata.

4.- Podrías hacer un contador que cada 60000 milisegundos actualice el conteo de minutos en tu memoria. 5.- Cuando quieras visualizar el tiempo de operación del motor podrías leer la dirección de la memoria donde se guarda esa variable y mostrarla por display.

Ok gracias carlos por la info del foro.

Tengo un código escrito el cual ya lee la temperatura y presión del motor, cuando tengo lectura de presión de motor nombre una variable estadomotor que pasa de 0 a 1 y cuando esto sucede se inicia el conteo de tiempo.

El objetivo de esto es lograr tener las horas de funcionamiento totales del motor estacionario y que cada 250 hs se imprima en pantalla un mensaje de mantenimiento del motor.

Esto asi como lo planteas no debes. Porque? Por que en 100.000 ciclos te quedas sin EEPROM en ese bloque. La EEPROM del ATMEGA permite 100K ciclos/escritura/borrado.

Debes hacer algo para grabar pero no de este modo. Yo creo que lo mejor es, colocar un gran capacitor en la alimentación de tu Arduino que garantice algunos segundos de backup. Usar un divisor resistivo conectado a la fuente de alimentación, sea la que sea. Si se corta la luz, tu detectas eso y ahi si grabas en la EEPROM 1 sola vez pero no siempre. Es simple y es eficaz.

Surbyte y que opinas de usar una memoria 24C02 que cada minuto actualice el conteo en una localidad de esa memoria de manera que si pierde la energía el arduino quede guardado el dato en la memoria. Lógico, por eso fue que le sugerí usar una memoria externa para no usar la del atmega.

Si. Es posible pero asi como está el programa es una barbaridad.
No puedes grabar sea en la EEPROM o en una EEPROM externa en cada ciclo.
Puede usar la del ATMEGA o la que tu sugieres, pero cuando corresponda. No siempre!!

Yo sugiero cada minuto que grave en la memoria externa de manera que si se pierde la energía solo se pierde 1 minuto de conteo que no es algo importante o no impactaría mucho en el conteo de las 250 horas.

Tal vez no fui claro, el proyecto es para un motor estacionario de un generador, el mismo se utiliza solo los fines de semanas, es decir, A LO SUMO SE USA 8 hs por semana, el resto del tiempo se mantiene apagado. Por lo tanto la idea de un capacitor para mantener la carga el lapso de tiempo que se encuentre apagado no me parece una solución.

Se me ocurre que ir guardando los datos del horometro en una tarjeta sd ya que la EEPROM me limita mucho. Pero no estoy seguro de esto.

otra solucion que se te propones (esta la he hecho yo en la practica) es que cuando desenchufes el generador haga una interrupcion y escriba en la EEPROM y se duerma el arduino y cuando arranque vualva a leer la EEPROM y prosiga. Es como te ha dicho el Coronel surbayte es tambien buena cosa eliges la que mas te guste.

hugogimenez:
Tal vez no fui claro, el proyecto es para un motor estacionario de un generador, el mismo se utiliza solo los fines de semanas, es decir, A LO SUMO SE USA 8 hs por semana, el resto del tiempo se mantiene apagado. Por lo tanto la idea de un capacitor para mantener la carga el lapso de tiempo que se encuentre apagado no me parece una solución.

Se me ocurre que ir guardando los datos del horometro en una tarjeta sd ya que la EEPROM me limita mucho. Pero no estoy seguro de esto.

Tu hablas del tiempo de marcha del equipo y yo hablo del momento de grabar en la EEPROM el Dato de las horas acumuladas de funcionamiento. Son dos cosas diferentes.
Yo te digo que cuando se quede sin energía necesitas milisegundos para detectar que asi pasó, grabar en la EEPROM el dato del tiempo acumulado y luego que siga la vida.
Si se usa una vez x mes, cada 6 meses o una vez por año me da igual.
SE entiende?
Tu ahora grabas a lo loco. con la falla posible de la EEPROM en poco tiempo. Quieres que te haga una cuenta? La hice hace poco. El proceso de escritura en la EEPROM demora 3.3 mseg puedes verlo aca link
Asi que supongamos 4 mseg para tu loop tal como esta que graba a lo loco
100.000 ciclos* 4 mseg = 400.000 mseg = 400 seg = 6min 40 seg
En ese tiempo se te debería bloquear la dirección.
Supongamos que como leí en la web, los 100k son solo estadística y soportas como alguien que hizo la prueba 1Millon de ciclos. O sea multiplicas x 10. y tendras 1h 6min 40 seg

Ahora yo digo que con un divisor resistivo, medimos con un pin analógico el nivel o bien puedes poner algo tipo un nivel logico de 5V que cuando se caiga a 0, detectaremos, eso pasa en menos de 1 mseg de loop
En ese tiempo SI y AHORA SI, grabo la EEPROM. 1 Sola vez.

Solo un para de mseg que debe soportar un capacitor al arduino para hacer esta tarea, detectar ausencia de energía y cuando vea la condición, grabar la EEPROM.
Mira que simple y que eficiente!!!

Ok gracias Surbyte ahora entendí lo que queres decir.

Yo tengo definida una variable que es estadomotor, la misma es 0 cuando el motor esta parado y 1 cuando el motor esta en marcha, entonces se me ocurre lo siguiente:

[If (estadomotor==0),
{EEPROM.Write(direccion,cuentaminutos);
}

De esta manera grabaría la cuenta de minutos en la memoria cada vez que el motor se para, es decir, supongamos una o dos veces por día que se usa el motor.

Que te parece?

Te hago otra pregunta de principiante: supongamos que se cumplieron los 100.000 ciclos que mencionas que sucede con esa dirección en la EEPROM?

Hola.
Hago inciso y reunifico conceptos.

Tal y como lo propones ahora, escribiría en EEPROM constantemente siempre que esté apagado el motor, pues cada vez que se evalúe la condición (estadomotor==0) se cumplirá. Lo lógico es grabar en EEPROM cuando pasa de encendido a apagado, es decir algo así (ten en cuenta que es pseudocódigo para que entiendas el planteamiento, no código final)

if (estadomotor != estadoanterior) { // Se cumple cuando cambia de encendido a apagado o viceversa
    if (estadomotor==1) { // acabamos de encender motor
        tiempofuncionamiento=leeeprom();  // leemos el último valor de tiempo de funcionamiento grabado para sumar a partir de ahí
        inicioencendido = milli();
    } 
    else {  // acabamos de apagar motor
    	tiempofuncionamiento = tiempofuncionamiento + millis() - inicioencendido; // sumamos al tiempo almacenado el nuevo tramo de encendido
        escribeeeprom(tiempofuncionamiento); // 
    }
}
estadoanterior=estadomotor;

Con eso llevaríamos un conteo bastante fiel, salvo en el caso de que se vaya la corriente del arduino mientras el motor estaba funcionando. Tal vez la opción más robusta es la que propone carlosjq10 de, cuando el motor está en funcionamiento, ir grabando cada minuto (o lapso mayor) el tiempo acumulado de funcionamiento en EEPROM.

Tal vez la opción más robusta es la que propone carlosjq10 de, cuando el motor está en funcionamiento, ir grabando cada minuto (o lapso mayor) el tiempo acumulado de funcionamiento en EEPROM.

jaja Voy a refutar a Serafín (noter). veamos 100k ciclos de escritura a 1 minuto, cuantós minutos me da antes que falle?

100.000 x 1 min = 100.000 minutos = 1666.6666 horas = *2 meses 9 dias 10 hs 40 min * y se muere la dirección. Optimista 1 Millon de ciclos escritura/borrado *1 año 11 meses 4 dias 10 horas 40 min * y adivinen que? Se arruina la dirección.

Se salva porque esto esta pensado en modo continuo y dice que lo usará 8hs por semana. Asi que la proporcion de 8hs x semana es => 1 semana = 7 dias = 7 x 24 hs = 168 horas la proporción es 8/168 = 1/21 Quiere decir que esos 2 meses pesimistas serán 21 veces mayores => 4 años 18 dias 8 hs

Espero que siempre sean 8hs semanales y guarda tu código para cuando deje de funcionar a los 4 años.

Bueno. Realmente va un poco más allá, porque sólo se grabará cada minuto (también se puede hacer cada 5 minutos, por ejemplo) DE FUNCIONAMIENTO DE MOTOR, osea, cuando está parado no se graba nada.

Sería, en el peor de los casos tus 2 meses 9 dias 10 hs 40 min de funcionamiento de motor, aunque también se podría ampliar la cosa variando la posición de escritura (complicaría el código, claro).

No obstante, estoy contigo en que lo mejor es leer cuando se arranca el motor y guardar cuando se para el motor o se produce brownout (¿era así el palabro?) en el arduino. Ya motor encendido y arduino apagado, ni mediante vudú podremos deducir cuánto tiempo estuvo encendido. EDITO: El cálculo que comento al principio creo que es el que comentas al final (4 años).

hugogimenez: Yo tengo definida una variable que es estadomotor, la misma es 0 cuando el motor esta parado y 1 cuando el motor esta en marcha, entonces se me ocurre lo siguiente:

[If (estadomotor==0),
{EEPROM.Write(direccion,cuentaminutos);
}

De esta manera grabaría la cuenta de minutos en la memoria cada vez que el motor se para, es decir, supongamos una o dos veces por día que se usa el motor.

Si para cuando se para el motor pero el Arduino sigue encendido, sí funcionaría.

Si es para grabar cuando se vaya a cortar el suministro eléctrico, sólo sirve dentro de una ISR (interrupción) sí o sí. Porque como en ese preciso momento al Arduino sólo le quedan unos escasos milisegundos antes de apagarse, entonces hay que hacer que el microprocesador "deje de hacer lo que estaba haciendo y se dedique a ejecutar la ISR lo más pronto posible". En términos de código sería: hacer que "de la nada" (en realidad es debido a algo tipo digitalRead que se ejecuta constantemente, fuera del código principal y en segundo plano) el flujo de instrucciones salte hacia la función que está preprogramada como ISR.

No sé si me he explicado bien o por hablar demasiado acabé confundiendo a alguien... ::)

Hola Noter, gracias por la ayuda.

Entiendo lo que planteas de gravar solo cuando cambie la variable estadomotor de una condición a otra.

Te aclaro una cosa: cuando se pasa a estadomotor=0 la placa arduino mega también se apaga ya que se alimenta con la misma batería que el motor por lo tanto no seguiría guardando mas datos.

Me surge una segunda pregunta, según entiendo los valores que se pueden almacenar en la EEPROM son de 0 a 255 (yo hice la prueba de intentar guardar en la dirección 0 el valor 256 y cuando leo la EEPROM devuelve un 0 si escribo 257 devuelve un 1 y asi....) supongamos que la cuenta de minutos u horas sea de 330 como guardo estos valores en la EEPROM??? Se me ocurre que el cuenta horas tenga como tope 100.000 hs y vuelva a arrancar a 0.

¿Entonces podemos decir que básicamente el arduino se va a encender y apagar a la vez que el motor? ¿Es decir, que siempre que está encendido el arduino lo está el motor y viceversa? Si es así, ¿podemos decir que el arduino debe medir e ir sumando el tiempo que él mismo está encendido?

Caso afirmativo, no lo dudes. La opción de escritura en EEPROM es la del condensador que te proponían antes.

En cuanto a los valores posibles en una dirección EEPROM son de 0 a 255, pero como disponemos de bastantes más posiciones, podemos guardar potencialmente lo que queramos, siempre que lo recuperemos en el orden correcto. Por ejemplo, utilizando dos posiciones podemos guardar un número de 0 a 65536, usando 4 un número entre 0 y 4.000.000 (aproximadamente). Utilizando x posiciones podemos guardar un texto de x longitud... el problema, como te dije, es saber dónde está el dato y de qué forma está guardado para realizar el proceso inverso en la lectura. Ese no será el problema, créeme.

Noter,

Es afirmativo, lo que decis, el arduino debe medir el tiempo que el mismo se encuentra encendido.

Entonces en cada una de las posiciones puedo guardar un dígito del cuenta horas y al leer hago una composición de cada uno de los digitos.

Te agradezco me has sido de gran ayuda. Voy a probar armar el codigo, si este funciona lo comporto al foro por si le es de utilidad a alguien.

Saludos

Señores, una memoria que no sea la del arduino puede usar tranquilamente y grabar las veces que quiera. Tan simple como usar la 24C04 de 2k y listo. a la final solo se tiene que usar una sola dirección para grabar sobre ella actualizando así el conteo de minutos.

No entiendo que tanto debate con la memoriqa del arduino. Eso a la final te va a matar el chip.