Datenlogger soll jeden Tag eine neue Datei generieren.

Hallo,

Ich bin dabei mir einen Datenlogger zu programmieren, Das geht auch soweit schon.
Ich gebe die Zeit serial und auf SDKarte aus. Mein Problem wo Ich nicht weiterkomme ist, dass Ich jeden Tag eine neue Datei erstellen will (JJMMDD) und die alte behalten.
Ich habe einen UnoR3 mit einem SDKartenShield.

#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.

const int chipSelect = 10;
unsigned long previousMillis3 = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval3 = 2000;    // Interval zwischen zwei Änderungen

File dataFile;




//File filename;

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.println("DS1307RTC Read Test");
  Serial.println("-------------------");

  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.");




  //create a new file

}


void loop() {

  //Takt wie oft serial und auf SDKarte geschrieben wird

  if (millis() - previousMillis3 > interval3) {
    previousMillis3 = millis();   // aktuelle Zeit abspeichern

    char filename[8];
    int year = 2018;
    int month = 8;
    int day = 2;
    CreateLogfileName(filename, year, month, day);


    Serial.println(filename);


    dataFile = SD.open ("zaehlen.csv", FILE_WRITE); //open the file

    tmElements_t tm;

    if (RTC.read(tm)) {

      print2digits(tm.Hour);
      Serial.write(':');
      print2digits(tm.Minute);
      Serial.write(':');
      print2digits(tm.Second);
      Serial.print(", Date (D/M/Y) = ");
      Serial.print(tm.Day);
      Serial.write('/');
      Serial.print(tm.Month);
      Serial.write('/');
      Serial.print(tmYearToCalendar(tm.Year));
      Serial.println();
    } else {
      if (RTC.chipPresent()) {
        Serial.println("The DS1307 is stopped.  Please run the SetTime");
        Serial.println("example to initialize the time and begin running.");
        Serial.println();
      } else {
        Serial.println("DS1307 read error!  Please check the circuitry.");
        Serial.println();
      }
     // delay(9000);
    }
   // delay(1000);


    // Auf SDKarte schreiben

    if (dataFile)
    {
      dataFile.print(" Meter");
      dataFile.print(";");

      print3digits(tm.Hour);
      dataFile.write(':');
      print3digits(tm.Minute);
      dataFile.write(':');
      print3digits(tm.Second);
      dataFile.print(", Date (D/M/Y) = ");
      dataFile.print(tm.Day);
      dataFile.write('/');
      dataFile.print(tm.Month);
      dataFile.write('/');
      dataFile.print(tmYearToCalendar(tm.Year));
      dataFile.println();

      dataFile.close();

    }

  }
}

// Digits für Serial

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

// Digits für SD Karte


void print3digits(int number) {
  if (number >= 0 && number < 10) {
    dataFile.write('0');
  }
  dataFile.print(number);
}



void CreateLogfileName(char* buffer, int y, int m, int d)
{
  sprintf(buffer, "zaehlen.csv", y, m, d);

  //sprintf(buffer, "%04d%02d%02d.txt", y, m, d);
}

char filename[8];
char filename[8+1+3+1];
Die letzte 1 für das null Byte und zur Sicherheit snprintf() verwenden.

Hallo,

hatte mir vor Jahren auch einen Datalogger gebaut. Von den RTC Daten wird das aktuelle Datum verwendet und der Dateiname erstellt. Wenn der noch nicht existiert, wird eine neue Datei mit dem Datum im Namen angelegt. Für jeden Tag eine Datei. Gleichzeitig wird in jeder Datei eine Kopfzeile angelegt. Musst nur das DOS Namensformat 8+3 einhalten mit der Standard SD Lib. 8 Zeichen für den Namen und 3 für die Endung. Bei mir .csv wegen Excelweiterverarbeitung. 12 Zeichen + Nullterminator = 13 Byte Array

Es existiert ein globales ...

char _SD_Dateiname[13];           // aktueller Dateiname, "_Jahr+_Monat+_Tag.txt", Bsp. 20140719

Der Rest macht die Funktion

void refresh_SD_Dateiname ()
{
  static char old_SD_Dateiname[13];
  snprintf_P(_SD_Dateiname,13, PSTR("%04d%02d%02d.csv"), _Jahr, _Monat, _Tag);  // spart etwas RAM
  if (strcmp(old_SD_Dateiname, _SD_Dateiname) != 0)  {  // wenn der char array Vergleich "ungleich" ergibt, dann
    strcpy(old_SD_Dateiname, _SD_Dateiname);            // setze old_SD... mit _SD_Dateiname gleich    
    if (!SD.exists(_SD_Dateiname))  {   // prüfe dessen Existens, wenn Datei nicht vorhanden, erstelle sie und ...
      myFile = SD.open(_SD_Dateiname, FILE_WRITE);   // erzeuge Kopfzeile in der neuen Datei
      myFile.print(F("Datum ; Zeit ; ms_over ; ")); 
      myFile.write(181);  // ASCII Sonderzeichen µ
      //                C runtime ; 1.DS1820 ; 2.DS1820; 3.DS1820 ; RTC-Temp ; MCP3428-1 ; MCP3428-2 ; MCP3428-4 ; Arduino Ub
      myFile.println(F("C runtime ; 1.DS1820 ; 2.DS1820; 3.DS1820 ; RTC-Temp ; USB_Ub ; KFZ_Bat ; USB_Akku ; Arduino Ub")); 
      myFile.print(F(";  ;  ;  ; ")); 
      myFile.write(176); myFile.print(F("C ; ")); myFile.write(176); myFile.print(F("C ; ")); myFile.write(176); myFile.print(F("C ; ")); myFile.write(176); myFile.print(F("C ; "));  // ASCII Sonderzeichen °
      myFile.println(F("V ; V ; V ; V")); 
      myFile.close();     
    }  
  }
}

ich hoffe das hilft dir weiter

Danke voresrst mal,

werde es probieren und mich dann wieder melden.

Gruß

Hallo Doc_Arduino,

Ich bekomme es nicht eingebunden ins Programm, kannst du mir helfen was ich wo einfügen bzw. ändern muss?

Gruß

Hallo,

du kannst die Funktion entweder ständig in der loop oder nur vorm SD Zugriff aufrufen.

Wenn ich deinen Sketch richtig überblicke sollte das die Funktion "CreateLogfileName" bei dir machen. Diese kannste durch meine ersetzen. Meine Variablennamen _Jahr, _Monat und _Tag ersetzt du durch deine y, m und d. Den Objektnamen myFile ersetzt du durch deinen dataFile. Zudem brauchst du noch ein globales char Array für den aktuellen Dateinamen der am Tag gültig/aktuell ist. Siehe oben.

Voraussetzung ist aber das ein Bsp. Sketch mit SD Kartennutzung überhaupt läuft.

Nochwas. In der SD Lib ist seit Jahren ein kleiner Bug drin. Im Installationspfad
C:\Program Files (x86)\Arduino\libraries\SD\src
gibt es eine Datei SD.cpp, in diese muss eine Zeile eingefügt werden.
Ab Zeile 337 gibt es eine Funktion namens

bool SDClass::begin(uint8_t csPin) {

darin gibt es einen 3 Zeiler

return card.init(SPI_HALF_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);

direkt davor/darüber fügst du diese Zeile ein

if (root.isOpen()) root.close();      // allows repeated calls

Hi,

Ich alles mal so umgesetzt, bekomme jedoch folgende Fehlermeldung.

'_SD_Dateiname' was not declared in this scope

Gruß

bitte nochmal alles lesen

wie siehts aus? Ansonsten deinen aktuellen Sketch bitte zeigen. In Codetags, nach 1x Preview Button </>

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).

Gruß Tommy

Sorry, hab zu schnell geschrieben. Vergiss den vorigen Post.
Jetzt schreibt er auf die Karte jedoch die Datei nur als 00000.csv und in der Datei kein Datum und keine Zeit.

#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.

const int chipSelect = 10;
unsigned long previousMillis3 = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval3 = 2000;    // Interval zwischen zwei Änderungen

File dataFile;

//File filename;

//global

char _SD_Dateiname[13];           // aktueller Dateiname, "_Jahr+_Monat+_Tag.txt", Bsp. 20140719
int _Tag, _Monat, _Jahr;

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.println("DS1307RTC Read Test");
  Serial.println("-------------------");

  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.");




  //create a new file

}


void loop() {

  //Takt wie oft serial und auf SDKarte geschrieben wird

  if (millis() - previousMillis3 > interval3) {
    previousMillis3 = millis();   // aktuelle Zeit abspeichern
    /*
      char filename[13];
      int year = 2018;
      int month = 8;
      int day = 2;
      //CreateLogfileName(filename, year, month, day);
      refresh_SD_Dateiname (_SD_Dateiname, year, month, day);
    */

    refresh_SD_Dateiname ();

    //    Serial.println(_SD_Dateiname);


    //dataFile = SD.open ("zaehlen.csv", FILE_WRITE); //open the file

    tmElements_t tm;

    if (RTC.read(tm)) {

      print2digits(tm.Hour);
      Serial.write(':');
      print2digits(tm.Minute);
      Serial.write(':');
      print2digits(tm.Second);
      Serial.print(", Date (D/M/Y) = ");
      Serial.print(tm.Day);
      Serial.write('/');
      Serial.print(tm.Month);
      Serial.write('/');
      Serial.print(tmYearToCalendar(tm.Year));
      Serial.println();
    } else {
      if (RTC.chipPresent()) {
        Serial.println("The DS1307 is stopped.  Please run the SetTime");
        Serial.println("example to initialize the time and begin running.");
        Serial.println();
      } else {
        Serial.println("DS1307 read error!  Please check the circuitry.");
        Serial.println();
      }
      // delay(9000);
    }
    // delay(1000);


    // Auf SDKarte schreiben
/*
    if (dataFile)
    {
      dataFile.print(" Meter");
      dataFile.print(";");

      print3digits(tm.Hour);
      dataFile.write(':');
      print3digits(tm.Minute);
      dataFile.write(':');
      print3digits(tm.Second);
      dataFile.print(", Date (D/M/Y) = ");
      dataFile.print(tm.Day);
      dataFile.write('/');
      dataFile.print(tm.Month);
      dataFile.write('/');
      dataFile.print(tmYearToCalendar(tm.Year));
      dataFile.println();

      dataFile.close();

    }
*/
  }
}

// Digits für Serial

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

// Digits für SD Karte


void print3digits(int number) {
  if (number >= 0 && number < 10) {
    dataFile.write('0');
  }
  dataFile.print(number);
}


/*
  void CreateLogfileName(char* buffer, int y, int m, int d)
  {
  sprintf(buffer, "zaehlen.csv", y, m, d);

  //sprintf(buffer, "%04d%02d%02d.txt", y, m, d);
  }

*/

void refresh_SD_Dateiname ()
{
  static char old_SD_Dateiname[13];
  snprintf_P(_SD_Dateiname, 13, PSTR("%04d%02d%02d.csv"), _Tag, _Monat, _Jahr); // spart etwas RAM
  if (strcmp(old_SD_Dateiname, _SD_Dateiname) != 0)  {  // wenn der char array Vergleich "ungleich" ergibt, dann
    strcpy(old_SD_Dateiname, _SD_Dateiname);            // setze old_SD... mit _SD_Dateiname gleich
    if (!SD.exists(_SD_Dateiname))  {   // prüfe dessen Existens, wenn Datei nicht vorhanden, erstelle sie und ...
      dataFile = SD.open(_SD_Dateiname, FILE_WRITE);   // erzeuge Kopfzeile in der neuen Datei
             
      dataFile.print(F("Datum ; Zeit ; ms_over ; "));
      dataFile.write(181);  // ASCII Sonderzeichen µ
      //                C runtime ; 1.DS1820 ; 2.DS1820; 3.DS1820 ; RTC-Temp ; MCP3428-1 ; MCP3428-2 ; MCP3428-4 ; Arduino Ub
      dataFile.println(F("C runtime ; 1.DS1820 ; 2.DS1820; 3.DS1820 ; RTC-Temp ; USB_Ub ; KFZ_Bat ; USB_Akku ; Arduino Ub"));
      dataFile.print(F(";  ;  ;  ; "));
      dataFile.write(176); dataFile.print(F("C ; ")); dataFile.write(176); dataFile.print(F("C ; ")); dataFile.write(176); dataFile.print(F("C ; ")); dataFile.write(176); dataFile.print(F("C ; "));  // ASCII Sonderzeichen °
      dataFile.println(F("V ; V ; V ; V"));
      dataFile.close();
    }
  }
}

Hallo,

die globalen _Tag, _Monat, _Jahr brauchst du nicht.
Diese Werte stehen bei dir in tm.Day, tm.Month und tm.Year Bzw. hattest du y, m und d
Diese musste in der refresh Funktion anpassen. Sketch Zeile 164
Danach müsste bei dir eine Datei mit dem Tagesdatum und einer Kopfzeile darin erzeugt werden.
Alleine durch die refresh Funktion.

Hallo,
wenn ich es anpasse kommt die Fehlermeldung y ;was not declared in this scope

Hallo,

irgendwie drehen wir uns im Kreis.
"Diese Werte stehen bei dir in tm.Day, tm.Month und tm.Year ..."
Es sind die gleichen Variablen die du testweise mit Serial.print ausgibts. Die stammen von deiner RTC.
Mit diesen Werten, der Inhalt dieser Variablen, wird der Dateiname zusammengebaut.

Hi,
Ich bekomme es nicht hin. Jetzt hab ich den Code schon um alles gekürzt was geht. Trotzdem will er nicht. Ohne dass Ich die y,m,d als int setzte bringt er Fehler.

#include <Wire.h>
#include <TimeLib.h>
#include <SD.h>
#include <DS1307RTC.h>


// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.

const int chipSelect = 10;
unsigned long previousMillis3 = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval3 = 2000;    // Interval zwischen zwei Änderungen

File dataFile;

//File filename;

//global

char _SD_Dateiname[13];           // aktueller Dateiname, "_Jahr+_Monat+_Tag.txt", Bsp. 20140719

int _d;
int _m;
int _y;


//int y, m, d;

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
  Serial.println("DS1307RTC Read Test");
  Serial.println("-------------------");

  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.");

  //create a new file

}


void loop() {

refresh_SD_Dateiname();

  tmElements_t tm;

  // Auf SDKarte schreiben
  
  dataFile = SD.open(_SD_Dateiname, FILE_WRITE);   // erzeuge Kopfzeile in der neuen Datei  // am abend noch hinzugefügt.
 
  if (dataFile)
  {

    print3digits(tm.Hour);
    dataFile.write(':');
    print3digits(tm.Minute);
    dataFile.write(':');
    print3digits(tm.Second);
    dataFile.print(", Date (D/M/Y) = ");
    dataFile.print(tm.Day);
    dataFile.write('/');
    dataFile.print(tm.Month);
    dataFile.write('/');

    dataFile.close();
  }

}

// Digits für Serial

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

// Digits für SD Karte


void print3digits(int number) {
  if (number >= 0 && number < 10) {
    dataFile.write('0');
  }
  dataFile.print(number);
}


void refresh_SD_Dateiname ()
{
  static char old_SD_Dateiname[13];
  snprintf_P(_SD_Dateiname,13, PSTR("%04d%02d%02d.csv"), _y, _m, _d);  // spart etwas RAM
  if (strcmp(old_SD_Dateiname, _SD_Dateiname) != 0)  {  // wenn der char array Vergleich "ungleich" ergibt, dann
    strcpy(old_SD_Dateiname, _SD_Dateiname);            // setze old_SD... mit _SD_Dateiname gleich    
    if (!SD.exists(_SD_Dateiname))  {   // prüfe dessen Existens, wenn Datei nicht vorhanden, erstelle sie und ...
      dataFile = SD.open(_SD_Dateiname, FILE_WRITE);   // erzeuge Kopfzeile in der neuen Datei
      dataFile.close();     
    }
  }
}

Auf dem PC wird die Karte mit 00000000.csv 01.01.2000 00;00 angezeigt.
Ich hatte die Karte auch schon als FAT16 und FAT32 formatiert, brachte aber nichts.
Sie ist 128 MB groß.

Gruß Ralf

snprintf_P(_SD_Dateiname,13, PSTR("%04d%02d%02d.csv"), _y, _m, _d); // spart etwas RAM

Wo weist Du _y, _m, _d Werte zu?

in Zeile 26 bis 28

Hi

Du hast in Deinem Sketch funktionierende Variablen mit den Namen
tm.Hour
tm.Minute
tm.Second

und Du benutzt zum Generieren des Namen leere globale Variablen mit den Namen
y
m
d

Muß ich Das irgendwie verstehen?

Was, wenn Du - rein für den Spaß - knapp über der Zeile, wo Du y, m, d benutzt folgende Zeilen hinschusterst:

y=tm.year;
m=tm.month;
d=tm.day;

Wenn Du Dich jetzt immer noch wunderst, warum Das JETZT plötzlich funktioniert - such Dir bitte ein anderes Hobby oder fange das Denken an.
Nur mit C&P kommst Du hier echt nicht weiter, ein klein Wenig Eigenintelligenz ist hier zwingend erforderlich.

MfG

PS: Und nun liest Du Dir durch, was der Uwe Dir seit gefühlten zwei Wochen zu Erklären versucht!

wenn Ich das aber so mache kommt die Fehlermeldung:

tm was not declarded in this scope

Ich bin ja gerade noch am lernen, da ist nicht alles so selbstverständlich.

Geht also nicht

metallicar:
Geht also nicht

Falsch

Bitte durchlesen:
C++ Variablen (der Abschnitt "Geltungsbereich")
Geltungsbereich von Variablen in C++