Go Down

Topic: Memorizzare file con data e ora corretti (Read 1 time) previous topic - next topic

9six4

Salve a tutti,
uso Arduino uno e una SD shield con RTC DS1307. Ho scritto un codice per salvare dei file csv dentro una SD ma i file hanno sempre la stessa data e ora 01/01/2000 00:00 nonostante all'interno del file i dati siano corretti. Qualcuno ha idea di che comando posso usare per far si che il file venga salvato con la data e l'ora giusti? Ho visto quest'esempio funzionante ma non capisco questo linguaggio di programmazione e quindi non so come gestirlo:
Code: [Select]
// A simple data logger for the Arduino analog pins with optional DS1307
// uses RTClib from https://github.com/adafruit/RTClib
#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define CHIP_SELECT     SS  // SD chip select pin
#define USE_DS1307       0  // set nonzero to use DS1307 RTC
#define LOG_INTERVAL  1000  // mills between entries
#define SENSOR_COUNT     3  // number of analog pins to log
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero
#define WAIT_TO_START    1  // Wait for serial input in setup()
#define ADC_DELAY       10  // ADC delay for high impedence sensors

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];
//------------------------------------------------------------------------------
#if SENSOR_COUNT > 6
#error SENSOR_COUNT too large
#endif  // SENSOR_COUNT
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
#if USE_DS1307
// use RTClib from Adafruit
// https://github.com/adafruit/RTClib

// The Arduino IDE has a bug that causes Wire and RTClib to be loaded even
// if USE_DS1307 is false.

#error remove this line and uncomment the next two lines.
//#include <Wire.h>
//#include <RTClib.h>
RTC_DS1307 RTC;  // define the Real Time Clock object
//------------------------------------------------------------------------------
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
    DateTime now = RTC.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}
//------------------------------------------------------------------------------
// format date/time
ostream& operator << (ostream& os, DateTime& dt) {
  os << dt.year() << '/' << int(dt.month()) << '/' << int(dt.day()) << ',';
  os << int(dt.hour()) << ':' << setfill('0') << setw(2) << int(dt.minute());
  os << ':' << setw(2) << int(dt.second()) << setfill(' ');
  return os;
}
#endif  // USE_DS1307
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

#if WAIT_TO_START
  cout << pstr("Type any character to start\n");
  while (Serial.read() < 0) {}
#endif  // WAIT_TO_START

#if USE_DS1307
  // connect to RTC
  Wire.begin();
  if (!RTC.begin()) error("RTC failed");

  // set date time callback function
  SdFile::dateTimeCallback(dateTime);
  DateTime now = RTC.now();
  cout  << now << endl;
#endif  // USE_DS1307

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  if (!sd.begin(CHIP_SELECT, SPI_HALF_SPEED)) sd.initErrorHalt();

  // create a new file in root, the current working directory
  char name[] = "LOGGER00.CSV";

  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

  cout << pstr("Logging to: ") << name << endl;

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("millis");

#if USE_DS1307
  bout << pstr(",date,time");
#endif  // USE_DS1307

  for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
    bout << pstr(",sens") << int(i);
  }
  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}
//------------------------------------------------------------------------------
void loop() {
  uint32_t m;

  // wait for time to be a multiple of interval
  do {
    m = millis();
  } while (m % LOG_INTERVAL);

  // use buffer stream to format line
  obufstream bout(buf, sizeof(buf));

  // start with time in millis
  bout << m;

#if USE_DS1307
  DateTime now = RTC.now();
  bout << ',' << now;
#endif  // USE_DS1307

  // read analog pins and format data
  for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
#if ADC_DELAY
    analogRead(ia);
    delay(ADC_DELAY);
#endif  // ADC_DELAY
    bout << ',' << analogRead(ia);
  }
  bout << endl;

  // log data and flush to SD
  logfile << buf << flush;

  // check for error
  if (!logfile) error("write data failed");

#if ECHO_TO_SERIAL
  cout << buf;
#endif  // ECHO_TO_SERIAL

  // don't log two points in the same millis
  if (m == millis()) delay(1);
}

Grazie

tonid

Ciao ho dato un'occhiata ed anche io non capisco quel linguaggio mi unisco al tuo dolore......

leo72

Questo problema è già venuto fuori 1 mese o 2 fa. Cerca nei vecchi thread, non mi ricordo se chi aveva aperto la discussione ha poi risolto in qualche maniera (mi pareva di sì)

9six4

Leo forse ti riferisci a questo sempre aperto da me:

http://arduino.cc/forum/index.php/topic,104381.30.html

però non ho mai risolto. Non riesco ad integrare la parte del programma che mi serve nel mio codice

leo72

Ma in quella discussione ho trovato un link:
http://forums.adafruit.com/viewtopic.php?f=31&t=20355
a metà c'è uno sketch con l'uso del metodo timestamp della libreria SD per impostare il timestamp del file.

9six4

Si ho letto però sembrano tutti controlli:

Code: [Select]
if (!file.timestamp(T_WRITE,now.year(),now.month(),now.day(),now.hour(),
now.minute(),now.second() )) {
error("write time");
}


Sto cercando di capire qual'è la parte in cui si va a memorizzare data e ora sul file  :~

leo72

#6
Jun 01, 2012, 08:35 am Last Edit: Jun 01, 2012, 08:44 am by leo72 Reason: 1
Non mi pare un controllo. Invochi la funzione di cambio timestamp e controlli che il valore che restituisce non sia un errore.

EDIT:
ossia è un sistema contratto per evitare l'assegnazione ad una variabile del codice restituito dalla funzione ed il successivo controllo del valore contenuto nella variabile.

9six4

Io l'avevo interpretato come: "se non riesci ad eseguire la funzione timestamp allora dai messaggio d'errore"
Ora provo ad inserirlo nel mio codice, vediamo che combina.

PaoloP

#8
Jun 01, 2012, 11:48 am Last Edit: Jun 01, 2012, 11:52 am by PaoloP Reason: 1

Io l'avevo interpretato come: "se non riesci ad eseguire la funzione timestamp allora dai messaggio d'errore"
Ora provo ad inserirlo nel mio codice, vediamo che combina.

Che vuol dire che lui esegue la funzione timestamp e controlla che non dia errore.
Ma la funzione la esegue e il timestamp lo scrive.

Per quanto riguarda <<, è un operatore di flusso.
cout è definito come seriale.
il comando:
Code: [Select]
DateTime now = RTC.now();
 cout  << now << endl;

corrisponde a:
Code: [Select]
DateTime now = RTC.now();
serial.print(now);
serial.println();


mentre
Code: [Select]
cout << endl << pstr("FreeRam: ") << FreeRam() << endl;
è
Code: [Select]
serial.print("FreeRam: ");
serial.print(FreeRam());
serial.println();


mentre bout è definito come una stringa (più o meno)
Code: [Select]
 // format header in buffer
 obufstream bout(buf, sizeof(buf));

 bout << pstr("millis");

#if USE_DS1307
 bout << pstr(",date,time");
#endif  // USE_DS1307

 for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
   bout << pstr(",sens") << int(i);
 }
 logfile << buf << endl;

questo diventerebbe:
Code: [Select]
buf =+ "millis";
#if USE_DS1307
buf =+ ",date,time";
#endif  // USE_DS1307
for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
   buf =+ ",sens";
   buf =+ int(i);
 }
file.print(buf);
file.println();

Una cosa del genere.  :D

Secondo me, l'operatore di flusso è molto intuitivo invece di scrivere un sacco di linee di codice per concatenare stringhe.
Guarda questo codice:
Code: [Select]
// format date/time
ostream& operator << (ostream& os, DateTime& dt) {
  os << dt.year() << '/' << int(dt.month()) << '/' << int(dt.day()) << ',';
  os << int(dt.hour()) << ':' << setfill('0') << setw(2) << int(dt.minute());
  os << ':' << setw(2) << int(dt.second()) << setfill(' ');
  return os;
}

Secondo te dentro lo "stream" os, cosa viene scritto?

leo72

E' molto intuitivo forse su un PC, dove so che se dirotto qualcosa su cout quel qualcosa mi esce sul terminale.
Ma qui sto programmando un microcontrollore.... già l'idea di usare il paradigma del terminale con cout mi sembra un controsenso.  :smiley-sweat:

9six4

Quote
Secondo te dentro lo "stream" os, cosa viene scritto?

Ad occhio scrive anno, mese, giorno... ora e minuti... però con che sintassi non ne ho la minima idea.
file.timestamp ?


Go Up