Ayuda: Timpo herratico con Data-logger

Hola a todos, espero me puedan ayudar, con este detallito.

ARDUINO UNO.
DTH11
RTC 1302
SD SHIELD.

Estoy haciendo un Datalogger usando un sensor DTH11, para el cual descargue una libreria.
Una SD, para grabar los datos, y un RTC 1302.

Basicamente lo que hace es tomar la humedad y la temperatura cada dos segundos, asi como revisar el
estado de un PIN, para saber si un compresor esta conectado o no… luego imprime en un archivo en la SD los resultados.

Als probarlo en la proto, todo funciono, tenia el archivo y el formato de datos que buscaba, asi como la frecuencia en los datos, sin emabrgo al cambiarlo a una placa de prueba para llevarlo a dejar al lugar de los hechos. y lo conecto a el puerto seria, y me da una variacion en la prueba de loop, como lo veran en las fotos.

Varia entre 2 y 15 segundos, por lo que he visto.

Por un momento intente cambiar la frecuencia del puerto serial de 9600 a 11200, para ver si era esta velocidad la que afectaba la lectura de los datos, pero al parecer no tuve suerte.

Aqui el codigo, si alguien tiene alguna idea, se lo agradecere.

//PROGRAMA PARA LLEVAR A CABO UNA MUESTRA DE HUMEDAD Y TEMPERATURA
//DENTRO DE LA CAMARA DE JOSE 

#include <SPI.h>           //creo que inlcuye la libreria de comunicacion serial 
#include <SD.h>            //Incluye la libreria de la SD 
#include <dht.h>           //Incluye lalibreria del uso del sensor de humedad y temperatura 
dht DHT;                   // declara las variables mencionadas 
#define DHT11_PIN 7        //defin el pin para leer la temperatura y humedad 
const int chipSelect = 10;  //define el pin para comunicrse con la SD 
#include <virtuabotixRTC.h>  //inlcuye la libreria dle relog 
virtuabotixRTC myRTC(4, 5, 6); //defines los pines del relog 4-SCLK, 5 I/O, 6 CE

int PinComp = 8;            //pin para leer el estado del compresor 
int edoComp = 0;            //variable para almacenar el estado del compresor 
String estadoCompEnLoop;    //variable tipo string para poder imprimir en el archivo de texto


File dataFile;

void setup(){
  Serial.begin(19200);
    pinMode(PinComp, INPUT); 
      Serial.print("Initializing SD card...");
      // make sure that the default chip select pin is set to
      // output, even if you don't use it:
      pinMode(SS, OUTPUT);

  
      // see if the card is present and can be initialized:
      if (!SD.begin(chipSelect)) {
      Serial.println("Card failed, or not present");
      // don't do anything more:
      while (1) ;
      }
      Serial.println("card initialized.");
  
      // Open up the file we're going to log to!
      dataFile = SD.open("datalog.txt", FILE_WRITE);
      if (! dataFile) {
      Serial.println("error opening datalog.txt");
      // Wait forever since we cant write data
      while (1) ;
    }
    Serial.println("Humedad(%),Temperatura(C), Edo Comp"); //imprime los encabezados 
    dataFile.println("Humedad, Temp, Edo Comp,  Hora,  Fecha  ");   
}



void loop(){
//READ DATA
  myRTC.updateTime();
  int Datos = DHT.read11(DHT11_PIN);  // lee el sensor y ensambla en la variable datos

  edoComp = digitalRead(PinComp); 
    if(edoComp == 0){
      estadoCompEnLoop="Apagado  ";}
    if (edoComp ==1){
      estadoCompEnLoop="Encendido";}
  
  Serial.print(DHT.humidity, 1);      //requiere la humedad del sensor 
  Serial.print(" , ");                
  Serial.print(DHT.temperature, 1);
  Serial.print(" , "); 
  Serial.print(estadoCompEnLoop); 
  Serial.print(" , "); 
  Serial.print(myRTC.hours); 
  Serial.print(":"); 
  Serial.print(myRTC.minutes); 
  Serial.print(":"); 
  Serial.print(myRTC.seconds); 
  Serial.print(" , "); 
  Serial.print(myRTC.dayofmonth); 
  Serial.print("/"); 
  Serial.print(myRTC.month); 
  Serial.print("/"); 
  Serial.println(myRTC.year); 

  dataFile.print(DHT.humidity, 1);   
  dataFile.print(" , "); 
  dataFile.print(DHT.temperature, 1);
  dataFile.print("  ");
  dataFile.print(estadoCompEnLoop);

  dataFile.print("  ");
  dataFile.print(myRTC.hours);
  dataFile.print(":"); 
  dataFile.print(myRTC.minutes); 
  dataFile.print(":"); 
  dataFile.print(myRTC.seconds); 
  dataFile.print("  "); 
  dataFile.print(myRTC.dayofmonth); 
  dataFile.print("/"); 
  dataFile.print(myRTC.month); 
  dataFile.print("/"); 
  dataFile.println(myRTC.year); 

  dataFile.flush();
  delay(2000);
  
}

datalogger2.jpg

datalogger3.jpg

datalogger5.jpg

Yo esperaba que mostraras algo con la diferencia de tiempo no las fotos del protoboard. O al menos una captura del serial monitor.

Hola.

Como dice el refrán "nunca te acostarás sin saber una cosa más". Por lo que pone en el vínculo anterior, las escrituras numéricas con print efectúan muchos flush en el proceso. El remedio que proponen es abrir en modo O_WRITE en lugar de FILE_WRITE.

Yo prefiero construir primero en memoria la cadena a escribir con sprintf, y posteriormente imprimo la cadena creada de una vez, con lo que creo que también se soluciona el problema. Además, si necesitas ver esa misma cadena por Serial, también lo haces de una vez, en lugar de repetir todos los print.

surbyte: Yo esperaba que mostraras algo con la diferencia de tiempo no las fotos del protoboard. O al menos una captura del serial monitor.

:confused: toda la razón, se me paso ese detalle.... Gracias de cualquier manera.!

noter: Hola.

Como dice el refrán "nunca te acostarás sin saber una cosa más". Por lo que pone en el vínculo anterior, las escrituras numéricas con print efectúan muchos flush en el proceso. El remedio que proponen es abrir en modo O_WRITE en lugar de FILE_WRITE.

Yo prefiero construir primero en memoria la cadena a escribir con sprintf, y posteriormente imprimo la cadena creada de una vez, con lo que creo que también se soluciona el problema. Además, si necesitas ver esa misma cadena por Serial, también lo haces de una vez, en lugar de repetir todos los print.

Muchas gracias! Debo decir que siempre aprende uno cosas en estos foros. Me dices de ensamblar la cadwna , me imagino que en una string... Para poder imprimir una sola tanto en el serial como en SD... Algo como... String CadenaDatos

String CadenaDatos = int Datos, int Edocomp, MyRtc.Year, MyRtc.Month, MyRtc.Day, myRtc.hour, MyRtc,minute, MyRtc,second

Lo siento por la sintaxis, nunca he ensamblado una cadena de texto así... Pero muchas gracias por el tip... Investigare y regreso con el código corregido!!!!!

No es lo que pide noter!!!!

tu haces esto

  dataFile.print(DHT.humidity, 1);   
  dataFile.print(" , "); 
  dataFile.print(DHT.temperature, 1);
  dataFile.print("  ");
  dataFile.print(estadoCompEnLoop);

  dataFile.print("  ");
  dataFile.print(myRTC.hours);
  dataFile.print(":"); 
  dataFile.print(myRTC.minutes); 
  dataFile.print(":"); 
  dataFile.print(myRTC.seconds); 
  dataFile.print("  "); 
  dataFile.print(myRTC.dayofmonth); 
  dataFile.print("/"); 
  dataFile.print(myRTC.month); 
  dataFile.print("/"); 
  dataFile.println(myRTC.year);

Primero no entiendo porque a cada dato le pones la marca de tiempo. Se toman todos los datos y una lectura de tiempo que se corresponde y se guarda todo. Noter te sugiere esto

defines una array de caracteres de longitud que debes calcular (yo no me tomo el trabajo)

char str[50]; // supongamos que 50 es suficiente

luego cuando viene el momento de presentar o guardar datos haces esto

sprintf(str, "%d %d %d %d:%d:%d %d/%d/%d", DHT.humidity, temperature, estadoCompEnLoop, myRTC.hours, myRTC.minutes, myRTC.seconds, myRTC.dayofmonth, myRTC.month, myRTC.year);

%d es para enteros. %c caracteres %s para strings luego imprimes Serial.print(str);

o guardas dataFile.println(str);

Oraleeeee.... :open_mouth:

Caada dato lleva la tiempo y hora por q estoy tomando lecturas de humedad temperatura y di la refrigeracion esta encendida, para totalizar el tiempo de refrigeración, y demas datos que necesito para saber como mejorar la con servacion de la carne.

Me queda claro ahora a lo que se refieren!!! Aunque disculpa la pregunta y que pueda parecer ridicula..... Cual es la diferencia entre un char string, como el que me ejemplificas, y concatenar todo en un texto?. No que me quiera pasar de vivillo pero intento saber. Gracias!!!!

Existen dos tipos de cadenas de caracteres: string y String. El primer tipo consiste sencillamente en un array de caracteres, en el que se almacena la cadena en cuestión. Para indicar el final, sin tener que especificar el tamaño de la cadena en cada operación, se utiliza el "truco" de poner al final de la cadena un carácter '\0' (un byte a cero para entendernos). De esta forma, cuando se le pasa esa cadena a un print, por ejemplo, éste empieza a escribir caracteres desde el inicio del array hasta que encuentra el \0, que termina. Es un modo "primitivo" de tratar cadenas, ya que no permite operaciones tan intuitivas como el otro tipo, pero permite mayor control de la memoria ocupada y, existen funciones muy interesantes para tratar con ellas (por ejemplo el famoso sprintf). Particularmente me gusta utilizar este tipo en arduino, pero requiere tener cierto dominio de los arrays. El otro tipo es una clase, denominada String, que incluye, además del array de caracteres (de hecho el método toCharArray() de la clase String devuelve ese array), otras propiedades y métodos más "cómodos" para efectuar una serie de operaciones típicas. Es tu elección utilizar unas, otras, o ambas.

Por si te quedó claro, o al menos a mi si, falta agregar el '\0'

Entonces al final del formato del sprintf (Lo que va entre comillas) agregas el 0 y en el formato agregas un caracter para sumarlo

algo asi

sprintf(str, "%d %d %d %d:%d:%d %d/%d/%d\0", DHT.humidity, temperature, estadoCompEnLoop, myRTC.hours, myRTC.minutes, myRTC.seconds, myRTC.dayofmonth, myRTC.month, myRTC.year);

No es necesario, surbyte. Cuando se asigna algo entre comillas dobles, la cadena va a tener su terminador. Por ejemplo, esto es equivalente:

char *cadena={‘h’,‘o’,‘l’,‘a’,’\n’}; //aquí sí hay que poner el carácter \0 porque asignamos caracter a caracter como en un array de cualquier tipo (observa las llaves y las comas).

char *cadena=“hola”; // al asignar una cadena entre comillas, lleva implícito que después va su \0.
char cadena[5]=“hola”; // podemos indicar el tamaño del array, teniendo en cuenta el terminador.
char cadena=“hola”; // pero es más sencillo no ponerlo y que nos lo calcule el compilador

En todos los casos se reserva un array de cinco char que va a contener “hola” y su terminador.
Por supuesto, todas las funciones destinadas a crear cadenas de caracteres (sprintf por ejemplo) nos dejarán la cadena con su terminador. Sin embargo, al contrario que con los objetos String, que gestionan asignaciones de memoria por su cuenta, muchas de esas funciones te piden una dirección de memoria donde “escupirte” la cadena de salida (sprintf, por ejemplo :)) y por ello nosotros debemos prever qué tamaño necesitaremos y reservar un trozo de memoria (char buffer[50]).
Si es demasiado grande no pasa nada (el terminador de cadena indicará el final del string sin importar qué haya en el resto del buffer) pero si nos quedamos cortos y sprintf escribe más allá del tamaño previsto, machacaremos posiciones de memoria que a saber qué contenían.

noter: Existen dos tipos de cadenas de caracteres: string y String. El primer tipo consiste sencillamente en un array de caracteres, en el que se almacena la cadena en cuestión. Para indicar el final, sin tener que especificar el tamaño de la cadena en cada operación, se utiliza el "truco" de poner al final de la cadena un carácter '\0' (un byte a cero para entendernos). De esta forma, cuando se le pasa esa cadena a un print, por ejemplo, éste empieza a escribir caracteres desde el inicio del array hasta que encuentra el \0, que termina. Es un modo "primitivo" de tratar cadenas, ya que no permite operaciones tan intuitivas como el otro tipo, pero permite mayor control de la memoria ocupada y, existen funciones muy interesantes para tratar con ellas (por ejemplo el famoso sprintf). Particularmente me gusta utilizar este tipo en arduino, pero requiere tener cierto dominio de los arrays. El otro tipo es una clase, denominada String, que incluye, además del array de caracteres (de hecho el método toCharArray() de la clase String devuelve ese array), otras propiedades y métodos más "cómodos" para efectuar una serie de operaciones típicas. Es tu elección utilizar unas, otras, o ambas.

Muchas gracias por la clarificacion entre ambos tipos de String y string =). Invetigare mas y ahora que sepa bien, regreso a postear el codigo, para que me digan que opinan!!!!

Bueno, el dia de ayer me traje por fin el arduino y la SD... y tengo acceso a los datos, aunque noto algo muy extraño en ellos... dejenme poner un ejemplo;

81.0 , 5.0 Apagado 14:7:44 19/11/2014 81.0 , 5.0 Apagado 14:7:44 19/11/2014 Humedad, Temp, Edo Comp, Hora, Fecha 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 81.0 , 5.0 Apagado 14:8:44 19/11/2014 Humedad, Temp, Edo Comp, Hora, Fecha 81.0 , 5.0 Apagado 14:8:44 19/11/2014

como pueden ver... aparecen los titulos de nuevo en el archivo, estos titulos solo se imprimian desde el void Setup() Aparte de que como me ya me lo indicaron, hice mal el codigo y el tiempo de escritura para la sd era demasiado largo...

void setup(){
  Serial.begin(19200);
    pinMode(PinComp, INPUT); 
      Serial.print("Initializing SD card...");
      // make sure that the default chip select pin is set to
      // output, even if you don't use it:
      pinMode(SS, OUTPUT);

  
      // see if the card is present and can be initialized:
      if (!SD.begin(chipSelect)) {
      Serial.println("Card failed, or not present");
      // don't do anything more:
      while (1) ;
      }
      Serial.println("card initialized.");
  
      // Open up the file we're going to log to!
      dataFile = SD.open("datalog.txt", FILE_WRITE);
      if (! dataFile) {
      Serial.println("error opening datalog.txt");
      // Wait forever since we cant write data
      while (1) ;
    }
    Serial.println("Hum  , Temperatura(C), Edo Comp"); //imprime los encabezados 
    dataFile.println("Humedad, Temp, Edo Comp,  Hora,       Fecha  ");   
}

Actualmente la tarjeta esta usando una fuente de poder swichada... que compre por ahi... 220-110V a 2A de a cuerdo a lo que dice en su etiqueta... Para que estos titulos se imprimieran , me imagino seria necesario que la fuente se apagara... Sera que no tiene capacitores para superar esos pequeños lapsos en los que el voltaje es muy alto o muy bajo para mantener encendida la tablilla... en ese caso... Que tamaño sería el adecuado para una fuente asi?

Gracias. !!!!

Hola, pues si,la bateria del RTC esta mala y no mantiene la fecha ni la hora correctamente.

el detalle es que estoy utilizando una libreria

#include <virtuabotixRTC.h>

y quiero usar alarmas …

#include <Time.h>
#include <TimeAlarms.h>

Y no me reconoce los segundos, incluso intente extraerlos en una variable aparte;

segundos = my.RTC.seconds;

lo imprime efectivamente 5, 10, 15, 20…

y al hacer las comparaciones if(segundos == 15){}

no lo toma en cuenta, espero alguíen sepa que hacer.

Gracias.

Ahora no recuerdo bien tu código pero para comparar con segundos usando == debes tener un código que no registra frenos por ejemplo por delays. A ver si me explico.
esto no esta permitido para comparar segundos

  dataFile.flush();
  delay(2000);
  
}

Además en tu caso usas la tarjeta SD.
Esa operación genera demoras hasta completarse, esas demoras no se de cuantos segundos son pero imagina que solo sea 1 segundo y tu comparas if(segundos == 15){} no podrá hacerlo.
Probaste poniendo >= con la salvedad que ejecutada una vez la comparación le digas a la misma que ya fue hecha y que no la considere mas, por ejemplo con un flag que este en la misma comparación y luego cambie cuando toda la condición se cumpla
Algo asi…

if (horas == 20 && minutos ==30 && segundos >= 15 && flag) {
    // haces lo que tienes que hacer
    flag = false; 
}

obviamente flag se define como boolean flag = true;
también tendras que buscar la maneera de volver a preparar el flag para que sea realizado al dia siguiente.