Contador de horas para un motor a combustion

Buen dia,

Antes que nada agradezco a todos por su tiempo y como lo había dicho les dejo un código de un cuenta segundos que logre hacer con la idea de NOTER.

Utilice un pulsador como entrada digital para simular el arranque o parada del motor:

Este código solo guarda en la EEPROM cuando el pulsador esta en LOW o lo que equivale al motor parado.

PD: si a alguien se le ocurren correcciones o mejoras los escucho.

Saludos

[/
int hora=0;
int minut= 0;
int seg=0;
int cuentasegundos=0;
int cuentasegundos2=0;
int pulsador=0;
int pulsadoranterior=0;
int direc1 = 0;
int direc2 = 1;
int direc3 = 2;
long milisegundos;
long tprev=0;
int u=0;
int d= 0;
int c=0;

void setup() 
{
pinMode (26, INPUT);
}

void loop()
 {
  pulsador=digitalRead(26);

  if(pulsador!=pulsadoranterior)

  { c =  EEPROM.read(direc1);
    d =  EEPROM.read(direc2);
    u =  EEPROM.read(direc3);
    cuentasegundos2= cuentasegundos+(c*100)+(d)*10+ u;
  
  if (pulsador==HIGH)
  {
    milisegundos= (millis())-tprev;
    seg=milisegundos/1000;

   if (seg==60)
   {seg=0;
   tprev=millis();
   minut= minut + 1;
   }

  if (minut==60)
  {minut=0;
  hora=hora+1;
  }
  cuentasegundos= minut*60 + seg;
 
  }
  }

  else
    { c=cuentasegundos/100;
    d=(cuentasegundos-c*100)/10;
    u= (cuentasegundos-c*100-d*10);
    EEPROM.write(direc1,c);
    EEPROM.write(direc2,d);
    EEPROM.write(direc3,u);
 
    cuentasegundos2= cuentasegundos+(c*100)+(d)*10+ u;

    }
  
  pulsador = pulsadoranterior;]

Buenos días, disculpen pero aca sigo yo de necio sugiriendo una memoria serial que aguantan 1.000.000 de write/erase y cuesta el 10% de lo que cuesta un chip ATmega328p.

El código que planteo lo que hace es que cada minuto busca en una dirección de la memoria un conteo acumulado y verifica si ya se cumplieron las 100 horas y si no entonces le incrementa 1 minuto al conteo y lo guarda en la misma localidad de la memoria. Muy simple.

#include <Wire.h>
#include <Eeprom24C04_16.h>
#define EEPROM_ADDRESS  0x50
static Eeprom24C04_16 eeprom(EEPROM_ADDRESS);

 byte data_40, data_41, dato1, dato2, lectura1, lectura2;
 
void setup() {
    Serial.begin(9600);
    pinMode(13,OUTPUT);  //Este pin lo usaremos como bandera para indicar que ya se cumplieron las 100 horas
    eeprom.initialize();

 //Como el conteo de 6000 minutos en hexa equivale a 1770 entonces lo arreglo de la siguiente manera:
 //como cada direccion puedo grabar 1 byte, es decir FF entonces grabo en la direccion como sigue:
    eeprom.writeByte(40, 0x17);  //Aca grabo el primer byte 0x17 emn la dirección 40
    delay(10);                    //Segun datasheet debo esperar 10 mseg posterior a un write...
    eeprom.writeByte(41, 0x70);   //Luego acá grabo el segundo byte 0x70 en la dirección 41 
    delay(10);                     

    //Nota: Coloque aca el código con 0x17 y 0x70 para que veas como se organizo el contador pero debes iniciar con 0x00 y 0x00.
    
    Serial.println("Inicializado...!");
    lectura1 = eeprom.readByte(40);   //Acá leo el primer byte de la address 40
    lectura2 = eeprom.readByte(41);   //Acá leo el segundo byte de la address 41
    Serial.print(lectura1,HEX);       //Esto lo hice con fines de referencia para visualizar con que conteo arranco perode debe ser cero.
    Serial.println(lectura2,HEX);
    digitalWrite(13,LOW);  //debo empezar con mi led bandera apagado....
   }

void loop() {
  delay(1000);  //aca simulo que 1 seg es 1 hora pero debes colocar 60000
  verificar();  //en este bucle verifico si ya se cumplieron las 100 horas, que equivalen a 6000 minutos
}

 void verificar(){
  dato1 = eeprom.readByte(40);  //Aca leo el primer byte de la address 40
  dato2 = eeprom.readByte(41);  //Aca leo el segundo byte de la address 41

  //Lo que sigue es una comparación de lo que este guardado en la memoria 0x17 = 23 en decimal y 0x70 = 112
  if((dato1 == 23) && (dato2 == 112)){    //si se cumplen ambas condiciones enciendo el led bandera de las 100 horas.
    Serial.println("Se han cumplido las 100 horas.."); 
    digitalWrite(13,HIGH); 
  }else{    //sino se cumplen las condiciones entonces voy a incrementar 1 minuto al conteo en la rutina grabar()
    grabar(); 
  }
 }
 
void grabar(){
 
 data_40 = eeprom.readByte(40);   //Acá leo el primer byte de la address 40
 data_41 = eeprom.readByte(41);   //Acá leo el segundo byte de la address 41
 
 //EL contador funciona asi: como son 2 direcciones de 1 byte entonces seria FF y FF. el primer byte se incrementara en 1
 //cada vez que el segundo byte llegue a FF, por lo tanto debo verificar si el segundo byte = 255 que seria FF en hexa
 //si es igual a 255 entonces le sumo 1 al contador del primer byte
 
     if(data_41 == 255){     
      data_40++;                //incremento 1 minuto al conteo
      eeprom.writeByte(40, data_40);  //y acá lo grabo en la memoria en la misma dirección 40
      delay(10);                     
    }
 data_41++;    //se cumpla o no se cumpla el if de arriba siempre voy a sumarle 1 minuto al contador del segundo byte...
 eeprom.writeByte(41, data_41);   //acá lo grabo en la memoria
 delay(10);
 Serial.print("Ahora el conteo grabado es de :");   //ya aquí lo utilizo como referencia pero tu no tendrás una laptop pegada, asi que obvia eso.
 Serial.print(data_40,HEX);   //obvia esto
 Serial.print(data_41,HEX);   //igual esto
 Serial.println("");          //y esto también :)
 
  }

Recuerda que este código esta pensado para 100 horas, si lo deseas para otra cantidad de horas debes modificar el programa para que compare y tambien ten en cuenta que el delay en el loop es de 1 seg y no de 1 minuto. Lo hice así para agilizar la simulación.

Saludos cordiales.

yo tengo una plca que cuenta minutos, ésta se alimenta de una fuente ajustada a 5,6 voltios, con un diodo el serie alimento a traves del +5v (NO el Vin) el arduino, en la cual hay un condensasor de 1F 5,5 (los usados antes como BK de las memorias en tv's y otros aparatos), y con otro diodo un "relé" de bobina 5 voltios (de hecho un opto) y en una pata x del arduino que si no detecta la tension o masa en la entrada x grabe datos, el condensador le da la autonomia sufiiente que incluso con el display mantiene los datos 5 segundos, de esta forma no hay que sufrir por la memoria. tambien puedes tener un relé con bobina 220 que se alimenta del grupo, al caer ésta se desclava el relé y te guarda datos, luego al reiniciarse el arduino recupera datos y antes de que se estropee la memoria se acaba el mundo.
si quieres más seguridad, que cada 48 horas te grabe una vez, o poner un cuentahoras mecanico.

hugogimenez:
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

a partir de la version de ide 1.6.2 la libreria eeprom incorpora los metodos put y get que permiten trabajar con cualquier tipo de datos:
https://www.arduino.cc/en/Reference/EEPROM

Hola carlos,

Gracias por tu aporte. Soy bastante nuevo con arduino así que desconozco la memoria que vos me mencionas. Voy a probar también hacerlo de esta manera.
En lugar de usar la memoria que vos me mencionas, yo tengo un adaptador de tarjetas sd para arduino y la sd que te parece si guardo los datos ahí?

Otra duda que me surge según lo que posteo Jose es la de la funcion get y put, yo tenia entendido que se utilizaban para guardar variables con decimales. Como guardarías por ejemplo 6.000.000 minutos
utlizando get y put???

Por supuesto, cualquier memoria que no sea la del chip se puede usar. NO conozco mucho sobre la SD pero no creo que tengas problemas con ella.

hugogimenez:
En lugar de usar la memoria que vos me mencionas, yo tengo un adaptador de tarjetas sd para arduino y la sd que te parece si guardo los datos ahí?

Y por qué no? Las tarjetas SD son baratas (incluso 8 GB es exagerado para muchas aplicaciones de Arduino), los datos son fáciles de respaldar (tener copias del archivo en una PC, en caso de que la tarjeta llegara a dañarse), y la librería para este propósito también es muy fácil de usar :smiley:

La única limitante es cuando se maneja un gran volumen de datos y se tiene que hacer muy rápido, ¡pero en tu caso eso no importa! :wink:

hugogimenez:
Hola carlos,

Gracias por tu aporte. Soy bastante nuevo con arduino así que desconozco la memoria que vos me mencionas. Voy a probar también hacerlo de esta manera.
En lugar de usar la memoria que vos me mencionas, yo tengo un adaptador de tarjetas sd para arduino y la sd que te parece si guardo los datos ahí?

Otra duda que me surge según lo que posteo Jose es la de la funcion get y put, yo tenia entendido que se utilizaban para guardar variables con decimales. Como guardarías por ejemplo 6.000.000 minutos
utlizando get y put???

toda la informacion la tienes en esta misma web , pestaña Learning -> Reference .Estan todos los tipos de variables y sus rangos,hay que buscar un poco.....como el tiempo no va a ser negativo y el tipo int te se queda corto ,podrias usar unsigned long : https://www.arduino.cc/en/Reference/UnsignedLong En el enlace que te puse de la eeprom,estan los metodos explicados.Para guardar un dato con eeprom.put():
https://www.arduino.cc/en/Reference/EEPROMPut
Solo necesita dos parametros ,la direccion de la eeprom y el dato a grabar:

unsigned long minutos = 6000000;
EEPROM.put(0,minutos);  //guarda el contenido de minutos a partir de la direccion 0

Para recoger un dato:
https://www.arduino.cc/en/Reference/EEPROMGet
Mismos parametros ,la direccion y el dato .Tienes que pasarle un tipo de datos igual que el que guardaste y la direccion donde lo guardaste ,en este caso un unsigned long y la direccion 0 de la eeprom:

unsigned long contenido;
EEPROM.get(0,contenido);
Serial.println(contenido);

En cuanto a la discusion de las memorias ,si podemos aprovechar los recursos que ya tenemos ,no veo porque gastar en memorias externas, para este proyecto en concreto ,ya que con una buena programacion que limite el numero de escrituras de la eeprom se puede tirar con lo que hay.Ademas el metodo put usa el metodo update ,que solo efectua la grabacion si el dato que se le pasa es diferente del que ya hay grabado .

Te agradezco jose, si este código funciona simplificaría bastante el que tengo ya que no tengo que descomponer el tiempo y almacenarlo en direcciones diferentes. Lo pruebo y vuelvo subir a mi código.

Por lo que veo se armo una discusión sobre donde almacenar los datos del horometro como yo soy muy inexperto (este es mi primer proyecto) dejo en sus manos cual es la mejor solución.

Si lo que dice jose funciona a lo sumo despues de 100.000 escrituras se arruina la direccion 0 quedando disponibles 255 direcciones mas para guardar datos en la EEPROM......creo que llegaríamos primero a cumplir la vida útil del motor antes de arruinar una direccion de la memoria. Pero esto es algo que se me ocurre a mi y aun no descarto las otras posibilidades.

Si lo mejor es almacenarlo fuera de la placa yo me inclinaría por una SD.

Hugogimenez, porque no le haces caso a lo que te ha explicado efec2000 que el pone un capacitor de 1F o mas no recuerdo como bakcup. Mantiene el Arduino por 5 segundos aun con rele y LCD.

5 segundos es una eternidad en arduino.
Necesitas 3.3 mseg para guardar un dato en la EEPROM. Para que quieres guardar permanentemente y en todo momento en la EEPROM?

Guardas en una variable, y vigilas la tensión de alimentación. Si detectas falta de energía en 10 mseg digamos haces.. la detección de que te has quedado sin energía, guardas el dato en la EEPROM y resuelto el problema. Seguro que eso no lleva ni 5 mseg.

1 vez cada cuantas semanas guardarás un dato?

Hola surbyte,

Con el código que subí solo estoy guardando en la EEPROM cuando el motor se para, es decir, cuanto mucho una vez al día. NO ESTOY GUARDANDO DATOS PERMANENTEMENTE ese fue mi error al comienzo y lo corregí con la ayuda de los comentarios.
Esto es igual a colocar el capacitor y guardar en la EEPROM cuando se corte la energía, la diferencia esta en que no necesito agregar ningún elemento extra a parte de la placa.

Bien!!! Ahora te entiendo yo.. Disculpa.

Totalmente correcto si tienes garantizado que cuando paras el motor llega la señal low al arduino antes de quedarse éste sin alimentación, que es precisamente por lo que surbyte insistía en el condensador o capacitor: para tener un tiempo entre la detección del apagado y el apagado por falta de corriente del propio arduino.
Por cierto, no sé si lo tienes controlado, pero recuerda prevenir los rebotes y posibles interferencias en la señal (los motores de explosión son bastante ruidosos eléctricamente hablando).

hugogimenez:
Con el código que subí solo estoy guardando en la EEPROM cuando el motor se para, es decir, cuanto mucho una vez al día. NO ESTOY GUARDANDO DATOS PERMANENTEMENTE ese fue mi error al comienzo y lo corregí con la ayuda de los comentarios.
Esto es igual a colocar el capacitor y guardar en la EEPROM cuando se corte la energía, la diferencia esta en que no necesito agregar ningún elemento extra a parte de la placa.

Pero asegurate de que la escritura se haga una sola vez al momento en que se apaga. No vaya a ser que se intente "actualizar" cada vez que se acaba el loop y el motor sigue apagado.

Pregunto: es un motor que arranca eléctricamente? (con batería) De ser así, hay que programar dos "gatillos" que "disparen" el guardado a la EEPROM: motor apagado y pérdida de energía eléctrica.

noter:
Por cierto, no sé si lo tienes controlado, pero recuerda prevenir los rebotes y posibles interferencias en la señal (los motores de explosión son bastante ruidosos eléctricamente hablando).

  • Lo del rebote es fácil: si la "señal de apagado" la da un interruptor mecánico, que haya un delay de 200 milisegundos despues del guardado. Total no creo que tenga que hacer algo más durante ese proceso.
  • En un motor a gasolina sí podría haber ruido eléctrico (por las chispas de las bujías), pero en uno diésel lo dudo mucho. En ambos casos, la única fuente de ruido en común, es el alternador.

Bueno aclaro:

El motor es ciclo Diesel y arranca electricamente con una batería y motor de arranque.

Yo ya tengo hecho con arduino un sensor de temperatura y presion de aceite, de forma tal que, cuando la presión es nula el motor se encuentra apagado con lo cual mi variable estadmotor se hace 0 y en ese momento hago un único guardado de datos de tiempo en la EEPROM.

La tensión que alimenta a mi placa mega la tomo de la bateria pero colocando antes una placa reguladora de voltaje: Modulo ajuste de tension LM2596 1.5 a 35v 2 a 3amper.

hugogimenez:
Bueno aclaro:

El motor es ciclo Diesel y arranca electricamente con una batería y motor de arranque.

Yo ya tengo hecho con arduino un sensor de temperatura y presion de aceite, de forma tal que, cuando la presión es nula el motor se encuentra apagado con lo cual mi variable estadmotor se hace 0 y en ese momento hago un único guardado de datos de tiempo en la EEPROM.

Eso está bien. El otro detalle es que el "disparo" por pérdida de energía eléctrica igual se debería hacer; uno nunca sabe... ::slight_smile:

hugogimenez:
La tensión que alimenta a mi placa mega la tomo de la bateria pero colocando antes una placa reguladora de voltaje: Modulo ajuste de tension LM2596 1.5 a 35v 2 a 3amper.

Muy buena idea. Porque 14.5v (voltaje de carga de una batería de automóvil) es demasiado para el regulador incorporado en las placas de Arduino.
Además, el LM2596 es un integrado utilizado en "convertidores Buck", un tipo de SMPS (fuente de poder conmutada). Estas se caracterizan por su alta eficiencia (bajas pérdidas de energía), lo que los vuelve la mejor opción para aplicaciones que se alimentan con baterías...