Contatore + logger

Buongiorno a tutti,

Sto cercando di realizzare un lettore/contatore di impulsi per il contatore dell' ENEL. Per farlo sfrutto una fotoresistenza, un trigger 74hc14, conto il tutto con il contatore hardware di arduino e ogni tot tempo scrivo sulla sd card con lo shield apposito, l'ora, il numero di impulsi nell'intervallo di tempo e gli impulsi totali. Per testare il tutto utilizzo un'altro arduino che mi fa lampeggiare un led.
Il problema e' questo:
Fin tanto che conto semplicemente gli impulsi con il contatore ottengo una lettura precisa, mentre quando introduco lo stadio "logger" al momento della scrittura sulla sd card mi perdo diversi lampeggi sfalsandomi la lettura. Sono arrivato ad affermare che l'errore avviene nel momento della scrittura sulla SD perche un led che replica il lampeggi letti del contatore sull'arduino rilevatore al momento della scrittura sulla SD sembra inciampare perdendosi i lampeggi incriminati.

Qualcuno e' gia incorso in questo tipo di inconveniente?
di seguito posto il codice che ho assemblato scopiazzando parti qua e la

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

#define redLEDpin 2
#define greenLEDpin 3

uint32_t syncTime = 0;      // time of last sync()
RTC_DS1307 RTC;             // define the Real Time Clock object
const int chipSelect = 10;  // for the data logging shield, we use digital pin 10 for the SD cs line
File logfile;               // the logging file

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);  
  digitalWrite(redLEDpin, HIGH);  // red LED indicates error
  while(1);
}



unsigned int count;
unsigned int getCount()

{
  TCCR1B=0;
  count=TCNT1;
  TCNT1=0;
  
  bitSet(TCCR1B ,CS12);
  bitSet(TCCR1B ,CS11);
  bitSet(TCCR1B ,CS10);
  
 return count;
  }
  
unsigned int getCountPrev;
unsigned int getCountTotal;
unsigned int getCountPartial;


  void setup()
  

  {
    pinMode(redLEDpin, OUTPUT);
    pinMode(greenLEDpin, OUTPUT);
    Serial.begin(9600);
    
    #if WAIT_TO_START
     Serial.println("Type any character to start");
     while (!Serial.available());
    #endif //WAIT_TO_START
    
   
  Serial.print("Initializing SD card...");   // initialize the SD card
  pinMode(10, OUTPUT); // make sure that the default chip select pin is set to output, even if you don't use it:
  
  if (!SD.begin(chipSelect))
  {
    error("Card failed, or not present");  // see if the card is present and can be initialized: 
  }
  
  Serial.println("card initialized.");
  
   // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  
  if (! logfile) {
    error("couldnt create file");
  }
  
  Serial.print("Logging to: ");
  Serial.println(filename);
  
  
  
   // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println("RTC failed");
#endif  //ECHO_TO_SERIAL
  }
  
#if ECHO_TO_SERIAL
  Serial.println("millis,stamp,datetime,light,temp,vcc");
#endif //ECHO_TO_SERIAL
  
    
    
    digitalWrite(5, HIGH);
    TCCR1A=0;
    getCount();
  }
  
  void loop()
  {
    delay(15000);
    DateTime now;
    now = RTC.now();
//    Serial.print(getCount());
//    Serial.print(" ");        
    getCountTotal=getCount()+ getCountPrev;
//    Serial.print(getCountTotal);
//    Serial.print(" ");
//    Serial.print(getCountPrev);
    getCountPartial = getCountTotal - getCountPrev;
//    Serial.print(" ");
//    Serial.println(getCountPartial);
    
    
    
    
////    getCountPrev = getCountTotal;
//    
     logfile.print('"');
     logfile.print(now.year(), DEC);
     logfile.print("/");
     logfile.print(now.month(), DEC);
     logfile.print("/");
     logfile.print(now.day(), DEC);
     logfile.print(" ");
     logfile.print(now.hour(), DEC);
     logfile.print(":");
     logfile.print(now.minute(), DEC);
     logfile.print(":");
     logfile.print(now.second(), DEC);
     logfile.print('"');
     logfile.print(" Pulses ");
     logfile.print(getCountPartial);
     logfile.print(" PulsesToT ");
     logfile.print(getCountTotal);
     logfile.println();
////  
     Serial.print('"');
     Serial.print(now.year(), DEC);
     Serial.print("/");
     Serial.print(now.month(), DEC);
     Serial.print("/");
     Serial.print(now.day(), DEC);
     Serial.print(" ");
     Serial.print(now.hour(), DEC);
     Serial.print(":");
     Serial.print(now.minute(), DEC);
     Serial.print(":");
     Serial.print(now.second(), DEC);
     Serial.print('"');
     Serial.print(" Pulses ");
     Serial.print(getCountPartial);
     Serial.print(" PulsesToT ");
     Serial.print(getCountTotal);
     Serial.println();
  
  
   getCountPrev = getCountTotal;

  
    
    
    
    
    
    
  }

Bisognerebbe vedere se la SD interagisce con interrupt e timer vari.

Sto utilizzando l' "adafruit data logging shield"....la mia impressione e' che nel momento in cui i dati vengono scritti sulla SD ci sia una pausa generale. Pensavo che sfruttando il contatore hardware avrei potuto evitare questo "stop" di conteggio.
Il mio primo esperimento contava gli impulsi semplicemente collegando la fotoresistenza all'ingresso analogico.
Il tutto sembrava funzionare bene....inserendo il "data logger" nel mio progetto ho iniziato ad avere questo "lag" durante la scrittura...allora ho pensato di contare gli impulsi in modo hardware ma il problema mi si ripresenta.
Avendo anche 10 impulsi al secondo posso perderne tranquillamente 12-13.
Cosa potrei fare per stabilire esattamente la causa del problema ed aggirarlo???

Bisognerebbe studiare la libreria SD, come ti ho detto, e vedere se interferisce con i timer.
Una soluzione alternativa sarebbe quella di usare un interrupt di cambio di stato sul pin della fotoresistenza e far contare gli impulsi alla routine associata.

leo72:
Bisognerebbe studiare la libreria SD, come ti ho detto, e vedere se interferisce con i timer.
Una soluzione alternativa sarebbe quella di usare un interrupt di cambio di stato sul pin della fotoresistenza e far contare gli impulsi alla routine associata.

Ti ringrazio per lo spunto. Anche se il mio livello di conoscenze e di 100 passi indietro.

Vorrei dare un aggiornamento:

Pensavo che contando hardware le istruzioni di delay fossero ininfluenti.
Sostituendo le istruzioni di delay con millis il contatore sembra non perdere un colpo
Sto contando impulsi a 10 hz ogni 10 secondi.

paowow:
Vorrei dare un aggiornamento:

Pensavo che contando hardware le istruzioni di delay fossero ininfluenti.
Sostituendo le istruzioni di delay con millis il contatore sembra non perdere un colpo
Sto contando impulsi a 10 hz ogni 10 secondi.

Mi suona strano, il delay altro non è che un loop in cui viene letto il valore del contatore usato come misuratore del passare del tempo e confrontato con il valore passato alla funzione.
Quindi il contatore HW non dovrebbe essere influenzato. Solo lo sketch dovrebbe essere bloccato.

Puoi anche registrare 100 dati in un array e poi scaricarlo ogni 2-3 minuti, ma che senso ha registrare tutti gli impulsi?
Se vuoi sapere quanto stai ciucciando basta contare il tempo tra un impulso e un altro e non puoi farlo in nessun altro modo che con un millis

ciao

pablos71:
e non puoi farlo in nessun altro modo che con un millis

Beh, pulseIn() è fatto apposta.

ok .. anche con pulse in :grin: :grin: :grin:

metti un carico di 1000w ... prendi il tempo di riferimento tra un impulso e l'altro, da li ti crei la formula

ciao

leo72:

paowow:
Vorrei dare un aggiornamento:

Pensavo che contando hardware le istruzioni di delay fossero ininfluenti.
Sostituendo le istruzioni di delay con millis il contatore sembra non perdere un colpo
Sto contando impulsi a 10 hz ogni 10 secondi.

Mi suona strano, il delay altro non è che un loop in cui viene letto il valore del contatore usato come misuratore del passare del tempo e confrontato con il valore passato alla funzione.
Quindi il contatore HW non dovrebbe essere influenzato. Solo lo sketch dovrebbe essere bloccato.

Infatti, conoscevo la teoria in questo senso...ma qualcosa evidentemente mi influisce nella pratica: il delay utilizzato per leggere dopo tot tempo gli impulsi, mi fa sballare la lettura degli stessi.

pablos71:
ok .. anche con pulse in :grin: :grin: :grin:

metti un carico di 1000w ... prendi il tempo di riferimento tra un impulso e l'altro, da li ti crei la formula

ciao

Se prendo il tempo tra un impulso e l'altro posso vedere il consumo istantaneo (giusto?)
Invece per me e' sufficiente sapere quanto ho consumato in un ora o in un giorno, calcolando il numero di impulsi ogni tot minuti.

leo72:

pablos71:
e non puoi farlo in nessun altro modo che con un millis

Beh, pulseIn() è fatto apposta.

PulseIn() non l'avevo ancora preso in considerazione, non conosco ancora tutte le possibilità di Arduino. Grazie per l'idea!.

E' grazie a tutti per i consigli e i suggerimenti!

Ciao,
anch'io mi sono imbattuto in problemi di registrazione su SD, rilevando una perdita di tempo (per la registrazione) insospettata (per me).

Così girando un po' ho trovato questo
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293975555

in pratica, anch'io ho aperto il file come hai fatto tu, poi leggendo ho modificato l'apertura come segue
File dataFile = SD.open(NomeFile_C, O_CREAT | O_WRITE | O_APPEND);

in questo modo le scritture
dataFile.print("bla bla bla");

non sono delle reali scritture su file fin quando non si arriva all'istruzione
dataFile.flush();

... appena leggi l'argomento del link comprenderai meglio di quanto io possa aver fatto.

Un saluto,
Tredipunta.