Go Down

Topic: Inconveniente con datalogger usando RTC DS1307, Memoria SD (Solucionado) (Read 1 time) previous topic - next topic

noter

¿Probaste a quitar el detachInterrupt y attachInterrupt que pusiste en el loop? Como te dije, a ver si ese propio proceso es el que hace que salte a veces una interrupción. En el primer código que pusiste en este hilo tienes puesto un detach, pero no el attach posterior, así que probablemente, a partir de la primera grabación no es que no hubiera disparos de interrupción fantasmas, sino que no los habría ni aunque pulsaras.

Tato84

En el setup esta  el attach pero nunca coloque un detach en mi codigo original. Luego  se desactivan las interrupciones cuando guarda datos cosas que debe hacerse y se activa de nuevo una vez que termina el proceso. Como dije anteriormente el codigo original se sometio a pruebas durante mucho tiempo y he verificado hasta con monitor serial que las interrupciones se generan de forma perfecta incrementando sensor, la unica falla que presentaba el codigo era que no registraba en el archivo .txt una o cuatro lineas como maximo de las 288 a lo largo del dia, de resto si no hacia nada registraba puros 0 durante dias sin ningun error y si pulsaba solo registraba las pulsaciones que realizaba en ese dia, y creo que lo que hace que pierda lineas es el for pero ahora  implemente solo esta condicion
a ver que tal se comporta.

Code: [Select]
if ( ((now.minute()%5)==0) && now.second==0)
{
}
delay(1000);
 


Con el uso del booleano es que empezo el inconveniente de datos fantasmas del sensor y considero que quizas es algo que se desborda por usar ese tipo de control. Estoy utilizando el atmega328 con cristal interno a 8 MHz y el bootloader breadboard-1-6-x


surbyte

Si me permites no puedes tener una rutina que chequea segundos y luego estamparle un
Code: [Select]
delay(1000);

Comprometes todo.
No importa si lo probaste 5 millones de veces.

Segundos con delay(1000) no esa bien.
Lo pones al limite al código para detectar algo.


Tato84

Si Surbyte comprendo lo que dices sin duda lo ideal es utilizar una condicion booleana pero desde que utilice esa condicion empezo el problema del sensor (pulsador) y es una falla a la que no le encuentro sentido alguno, quizas sea un bug.

noter

¿Puedes poner el código que no te daba pulsaciones fantasma, aunque perdiera grabaciones, y el que te está haciendo pulsaciones fantasma? Lo digo, porque igual partimos de supuestos de código diferentes.
Por otra parte, reitero. ¿Has intentado quitar el detach/attach en el loop?

Tato84

No aun no he hecho lo de quitar detach y attach del loop, hare una prueba con el protoboard y el codigo con tu modificacion para ver como se comporta, para descartar errores de todo tipo, si vuelve a generar falsas pulsaciones ya no tendre ninguna duda que es el codigo.

Aqui coloco el codigo original:

Code: [Select]

#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include "RTClib.h"
RTC_DS1307 rtc;
File myFile;

volatile unsigned int sensor;
unsigned long T0 = 0;
char filename[13];
char registro[30];
byte min_registro[12]={0,5,10,15,20,25,30,35,40,45,50,55};


void interrupcion_sensor()
{
  if (millis() > T0 + 250)
  { sensor++;
    T0 = millis();
  }
}


void setup()
{
  Serial.begin(9600);
  delay(3000);
  pinMode(10, OUTPUT);//MEMORIA SD
  pinMode(3,OUTPUT); //LED
  attachInterrupt(0, interrupcion_sensor, FALLING);
  Wire.begin();
  rtc.begin();

  digitalWrite(3,HIGH); ///////////////////////////
  delay(500);           // DISPOSITIVO ENCENDIDO //
  digitalWrite(3,LOW);  //////////////////////////


  if (!SD.begin(10)) {
   Serial.println(F("Se ha producido un fallo al iniciar la comunicacion con la memoria SD"));
   digitalWrite(3,HIGH); //Led se mantiene encendido indicando un error
   while(1);
  }

  Serial.println(F("Se ha iniciado la comunicacion correctamente con la memoria SD"));
 
 
  if (!rtc.isrunning())
  {
      myFile = SD.open("cfg.txt");
      if (myFile) {
      Serial.println(F("Abriendo archivo cfg.txt"));
      if (myFile.available()) {
        byte day = myFile.parseInt();
        byte month = myFile.parseInt();
        int year = myFile.parseInt();
        byte hour = myFile.parseInt();
        byte minute = myFile.parseInt();
        byte second = myFile.parseInt();
        rtc.adjust(DateTime(year, month, day, hour, minute, second));
        }
        myFile.close();
        Serial.println(F("Datos cargados correctamente al reloj en tiempo real"));
        digitalWrite(3,HIGH); //Led titila indicando que ha sido exitoso el proceso.
        delay(500);
        digitalWrite(3,LOW);
        delay(500);
        digitalWrite(3,HIGH);
        delay(500);
        digitalWrite(3,LOW);
        delay(500);
        digitalWrite(3,HIGH);
        delay(500);
        digitalWrite(3,LOW);
      }
      else
      {
    Serial.println(F("Error abriendo archivo cfg.txt"));
    digitalWrite(3,HIGH); //Led se mantiene encendido indicando un error
    while(1);
    }
  }
}//FIN SETUP


void loop()
{

DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

snprintf(filename, sizeof(filename), "%02d%02d%04d.txt", now.day(), now.month(), now.year());   

 
  for (byte i = 0; i < 12; i++)
  {
    if ((now.minute() == min_registro[i]) && (now.second() == 0)) // Compara la hora del RTC con el ciclo de medicion
    {
      digitalWrite(3,HIGH); //inicia proceso de registro
      //Serial.println(F("Iniciando registro de datos en la memoria SD"));
      SD.begin(10); // se inicializa SD por si se retiro
      //Serial.println(F("Inicializar memoria SD"));
      delay(20);
      myFile = SD.open(filename, FILE_WRITE);
      if (myFile)
      {
        detachInterrupt(0);
        snprintf(registro, sizeof(registro), "%02d/%02d/%04d  %02d:%02d:%02d   %d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), sensor);
        myFile.println(registro);
        myFile.close(); // cerrar archivo .txt
        sensor = 0;
       }
     attachInterrupt(0, interrupcion_sensor, FALLING); 
    }
    }
    delay(1000);
    digitalWrite(3,LOW);//finaliza proceso de registro
} // fin de bucle



Codigo falsas pulsaciones:

Code: [Select]

#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include "RTClib.h"
RTC_DS1307 rtc;
File myFile;

volatile unsigned int sensor;
unsigned long T0 = 0;
char filename[13];
char registro[30];
bool flag=false;

void interrupcion_sensor()
{
  if (millis() - T0 > 250)
  { sensor++;
    T0 = millis();
  }
}


void setup()
{
 
  pinMode(10, OUTPUT);//MEMORIA SD
  pinMode(3,OUTPUT); //LED
  digitalWrite(3,HIGH); ///////////////////////////
  delay(500);           // DISPOSITIVO ENCENDIDO //
  digitalWrite(3,LOW);  //////////////////////////
  Serial.begin(9600);
  delay(3000);
  attachInterrupt(0, interrupcion_sensor, FALLING);
  Wire.begin();
  rtc.begin();

 
  if (!SD.begin(10)) {
   Serial.println(F("Se ha producido un fallo al iniciar la comunicacion con la memoria SD"));
   digitalWrite(3,HIGH); //Led se mantiene encendido indicando un error
   while(1);
  }

  Serial.println(F("Se ha iniciado la comunicacion correctamente con la memoria SD"));
 
 
  if (!rtc.isrunning())
  {
      myFile = SD.open("cfg.txt");
      if (myFile) {
      Serial.println(F("Abriendo archivo cfg.txt"));
      if (myFile.available()) {
        byte day = myFile.parseInt();
        byte month = myFile.parseInt();
        int year = myFile.parseInt();
        byte hour = myFile.parseInt();
        byte minute = myFile.parseInt();
        byte second = myFile.parseInt();
        rtc.adjust(DateTime(year, month, day, hour, minute, second));
        }
        myFile.close();
        Serial.println(F("Datos cargados correctamente al reloj en tiempo real"));
        digitalWrite(3,HIGH); //Led titila indicando que ha sido exitoso el proceso.
        delay(500);
        digitalWrite(3,LOW);
        delay(500);
        digitalWrite(3,HIGH);
        delay(500);
        digitalWrite(3,LOW);
        delay(500);
        digitalWrite(3,HIGH);
        delay(500);
        digitalWrite(3,LOW);
      }
      else
      {
    Serial.println(F("Error abriendo archivo cfg.txt"));
    digitalWrite(3,HIGH); //Led se mantiene encendido indicando un error
    while(1);
    }
  }
}//FIN SETUP


void loop()
{

DateTime now = rtc.now(); // Obtiene la fecha y hora del RTC

snprintf(filename, sizeof(filename), "%02d%02d%04d.txt", now.day(), now.month(), now.year());   

if (flag) {
    if( (now.minute()%5)>0 ) {
      flag=false; // Si el resto de minuto/5 no es cero, "armamos" siguente flag
    }
  }
  else {
    if ( ((now.minute()%5)==0) && (now.second()<3) ) {
      digitalWrite(3,HIGH); //inicia proceso de registro
      //Serial.println(F("Iniciando registro de datos en la memoria SD"));
      SD.begin(10); // se inicializa SD por si se retiro
      //Serial.println(F("Inicializar memoria SD"));
      delay(20);
      myFile = SD.open(filename, FILE_WRITE);
      if (myFile)
      {
        detachInterrupt(0);
        snprintf(registro, sizeof(registro), "%02d/%02d/%04d  %02d:%02d:%02d   %d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), sensor);
        myFile.println(registro);
        myFile.close(); // cerrar archivo .txt
        sensor = 0;
       }
    flag=true; // y desarmamos flag para evitar guardar más veces
    attachInterrupt(0, interrupcion_sensor, FALLING); 
    }
  }
  delay(500);
  digitalWrite(3,LOW);//finaliza proceso de registro
} // fin de bucle

Tato84

He estado leyendo sobre falsas interrupciones y aparentemente limpiar la bandera de interrupciones antes de attachInterrupt lo soluciona.

Code: [Select]
EIFR |= (1 << INTF0); // clear any outstanding interrupt 0

surbyte

y lo hizo? debes hacer la prueba de los 288  registros, okay!!

Tato84

Ok ya hice la prueba en protoboard y no registro ningun dato adicional el booleano no causa conflicto si no lo uso con codigo adicional de envio de datos, entonces la falla esta en el codigo de envio de datos o algun componente de la PCB que este generando una interferencia.


En la PCB hice una prueba con un nuevo arreglo de %5 y se registraron dos en el sensor tan solo en una linea de 286 que se registraron y deben ser 288.  (En esta incluyo codigo de envio de datos)

Code: [Select]
if ( ((now.minute()%5)==0) && (now.second()==0))

Cuando uso con el for y sin %5 (se registran 287 lineas y cero falsa interrupcion en sensor)
En esta incluyo codigo de envio de datos y uso la PCB.

Code: [Select]
for (byte i = 0; i < 12; i++)
  {
    if ((now.minute() == min_registro[i]) && (now.second() == 0)) // Compara la hora del RTC con el ciclo de medicion






surbyte

que pasa si aceleras la prueba y en lugar de hacerlo cada 5 min lo haces cada 1 minuto solo para probar.

No puedo creer que la opción %5 te genere errores adicionales.
Hazlo por 288 minutos para tener una comparación mas o menos similar.
Son 4:48 hs

Tato84

Bueno el codigo lo he forzado hasta registrando cada segundo en veces anteriores y no mostraba falsa interrupcion o quizas en las lineas que se perdia de las 288 ocurria una falsa interrupcion, aunque con el codigo con booleano como indico noter solo fueron solo 4 lineas con falsa interrupcion. Ahorita estoy forzando el codigo para que tambien envie los datos cada 5 minutos, y esta registrando y enviando los datos sin problema cada 5 minutos y por los momentos cero falsa interrupcion. Estoy usando booleano, (now.minute()%5)==0  y agregue el codigo para borrar cualquier interrupcion pendiente antes del arrachInterrupt y creo que quizas si desactivo la interrupcion justo despues del if que controla el tiempo de registro habra menos riesgo de falsa interrupcion. Ahora empezare a forzarlo a registrar cada minuto.

surbyte

Explica un poco que es tu sensor? Si ya lo dijiste dime que post# porque no me acuerdo

Tato84

Para el sensor ahorita estoy usando un pulsador, pero de forma definitiva sera el reed switch.

surbyte

Un pulsador te esta dando interrupciones fallidas? No puedo creerlo!!
Como esta conectado ese interruptor?
Busca un esquema que lo describa o dibuja algo le tomas una foto y lo posteas debidamente.

Repito.. no podemos llevar 42 post con un tema que luce como simple y como de costumbre estamos obviando algo. Lo digo en tu beneficio no porque no se puedan tener 100 post. Yo busco que tu problema se resuelva como todos en el foro a la brevedad.

Ademas no entiendo para que quieres una interrupción para ver un pulsador.
Es un evento LENTO, que puedes controlar solo con millis() y un debounce sin usar interrupciones y sin estar sujeto a situaciones que no controlas.

Cada 5 min quieres saber el estado del pulsador. No hace falta una interrupcion.
El concepto de la interrupcion es para cosas que se registran a alta velocidad no al revés.

El pulsador esta conectado con PULL-UP porque la interrupción está definida x FALLING.
Una R conectada entre 5V y el pin que va a GND.



O sea de este modo, por favor confirma esto?

Tato84

Exactamente asi esta configurado, con resistencia pull-up, pero ya aclare que el codigo esta perfecto ya realice pruebas en un protobard y registra sin problemas y cero falsa interrucion.

Considero que el problema esta en un codigo de envio de datos que le agregue o quizas en la PCB alguna interferencia pero dudo que un mosfet o un dispositivo inalambrico sea capaz de generar falsas interrupciones pero no lo descarto y la primera prueba que hice con el booleano tan solo ocurrieron de 1 a 2 falsas interrupciones en unos 4 registros de un total de 288 registros como se ve en el archivo .txt

Estoy haciendo otra prueba con bandera iniciada en true y solo deje el booleano con (minute()%5)==0, tambien agregue lo de limpiar interrupciones pendientes antes de volver a activar las interrupciones, ya en pocas horas verifico si esta registrando sin falsa interrupcion. Pero ya se puede dar por concluido el inconveniente en la memoria SD con la perdida de lineas y las falsas interrupciones, ya que estan siendo ocasionadas por el codigo de comunicacion o la PCB.






Go Up