SD Modul

Hallo,

ich habe folgendes Problem:

Ich rufe die Funktion aus der Loop auf und versuche Werte auf einer SD KArte zu speichern. Das funktioniert super.

Wenn ich die SD Karte aus dem Slot nehme, schreibt er allerdings weiter "SD beschrieben". Er denkt also weiter das die Datei geöffnet ist und bringt nicht die Fehlermeldung aus der else Schleife.

Ich habe langsam keine Idee mehr.

void saveTempToSD() {
 
         String Tsensor1 = "";
         String Tsensor2 = "";
          Tsensor1 += String(Temperatur[0]);
          Tsensor2 += String(Temperatur[1]);  
          
          File dataFile = SD.open("datalog.csv", FILE_WRITE);
      
          //Schreibe Datum / Temp - Werte auf die SD Karte
          if (dataFile) {    
            dataFile.print(buf4);
            Serial.println(buf4);
            dataFile.print(";");      
            dataFile.print(buf1);
            Serial.println(buf1);
            dataFile.print(";"); 
            dataFile.print(Temperatur[0]);
            Serial.println(Tsensor1);
            dataFile.print(";");  
            dataFile.println(Temperatur[0]); 
            Serial.println(Tsensor2); 
            dataFile.close();
            Serial.println("SD beschrieben");
              }    
              else {
                Serial.println("error opening TempDataLog.csv");
              }
  }

Poste bitte einen Hyperlink deines SD-Kartenlesers und den kompletten Sketch.

Wenn ich in der Loop die Datei einmal vorab öffne, funktioniert es. Weshalb sollte ich die Datei allerdings in der Loop öffnen? Reicht doch sicher auch in der Funktion.

//RTC DS1307
#include "RTClib.h"
//TempSensor DS18B20
#include <OneWire.h> 
#include <DallasTemperature.h>
//SD SPI Modul 
#include <SD.h>
//OLED
#include <SPI.h>
#include <Wire.h>

//OLED
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C
// Define proper RST_PIN if required.
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
   
RTC_DS1307 rtc;

const int chipSelect = 10;
 
#define ONE_WIRE_BUS 3
#define DS18B20_Aufloesung 12
DeviceAddress DS18B20_Adressen;
 
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature myDS18B20(&oneWire); 
#define Anzahl_Sensoren_DS18B20  2 // Anzahl der angeschlossenen Sensoren - Mögliche Werte: '0','1','2'
 
const float No_Val = 999.99;
float Temperatur[2] = {No_Val,No_Val}; 

//DateTime now;
 
//String Tsensor1 = "";
//String Tsensor2 = "";

    char buf1[] = "hh:mm:ss";
    char buf4[] = "DD.MM.YYYY";

void setup() {
 Serial.begin(9600);
   //OLED
     #if RST_PIN >= 0
      oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);
    #else // RST_PIN >= 0
      oled.begin(&Adafruit128x32, I2C_ADDRESS);
    #endif // RST_PIN >= 0
      // Call oled.setI2cClock(frequency) to change from the default frequency.
    
      oled.setFont(Adafruit5x7);
    
      oled.clear();
      oled.setRow(1);
      oled.set2X();
      oled.println("Booting ...");
      delay(1000);
      
  Wire.begin();
  rtc.begin();
    
  //RTC
  if (! rtc.isrunning()) {
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
  else Serial.println("RTC is running");
      
      oled.clear();
      oled.setRow(0);
      oled.set1X();
      oled.println("RTC is running");
      delay(500);
      oled.setRow(1);
      oled.set1X();
      oled.println("Initializing SD card");
  Serial.print("Initializing SD ...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed / No Card");
      oled.setRow(2);
      oled.set1X();
      oled.println("Card failed / No Card");
      delay(1000);
    // Endlosschleife/Reset erforderlich
    while (1);
  }
  Serial.println("card initialized.");
      oled.setRow(2);
      oled.set1X();
      oled.println("card initialized.");
  delay(1000);
      oled.setRow(3);
      oled.set1X();
      oled.print("Counted DS18B20: ");
  delay(1000); 
  Serial.print("Anzahl aktivierter Sensoren: ");
  Serial.println(Anzahl_Sensoren_DS18B20);

 
  if ((Anzahl_Sensoren_DS18B20 > 0) and (Anzahl_Sensoren_DS18B20 < 3)) {
    myDS18B20.begin();
    Serial.print("Anzahl angeschlossener Sensoren: ");
    Serial.println(myDS18B20.getDeviceCount(), DEC);
    Serial.println();
      oled.setRow(3);
      oled.set1X();
      oled.print(myDS18B20.getDeviceCount(), DEC);
  delay(1000);
 
    for(byte i=0 ;i < myDS18B20.getDeviceCount(); i++) {
      if(myDS18B20.getAddress(DS18B20_Adressen, i)) {
        myDS18B20.setResolution(DS18B20_Adressen, DS18B20_Aufloesung);
      }
    }
  }
   delay(1000);
}


void saveTempToSD() {
 
          String Tsensor1 = "";
          String Tsensor2 = "";
          Tsensor1 += String(Temperatur[0]);
          Tsensor2 += String(Temperatur[1]);  
          
          File dataFile = SD.open("datalog.csv", FILE_WRITE);
      
          //Schreibe Datum / Temp - Werte auf die SD Karte
          if (dataFile) {    
            dataFile.print(buf4);
            Serial.println(buf4);
            dataFile.print(";");      
            dataFile.print(buf1);
            Serial.println(buf1);
            dataFile.print(";"); 
            dataFile.print(Tsensor1);
            Serial.println(Tsensor1);
            dataFile.print(";");  
            dataFile.println(Tsensor2); 
            Serial.println(Tsensor2); 
            dataFile.close();
            Serial.println("SD beschrieben");
              }    
              else {
                Serial.println("error opening TempDataLog.csv");
              }
  }

void measureTemp(){
  
         //Wieviel Sensoren sind angeschlossen   
        if ((Anzahl_Sensoren_DS18B20 > 0) and (Anzahl_Sensoren_DS18B20 < 3)) {
          myDS18B20.requestTemperatures();
          
          //Schleife für Messung aller Sensoren
          for(byte i=0 ;i < Anzahl_Sensoren_DS18B20; i++) {
            if (i < myDS18B20.getDeviceCount()) {
          
              Serial.print("Sensor ");
              Serial.print(i+1);
              Serial.print(": "); 
            
              Temperatur[i] = myDS18B20.getTempCByIndex(i);  
              
              if (Temperatur[i] == DEVICE_DISCONNECTED_C) {
                  Temperatur[i] = No_Val;
                Serial.println("Fehler");
                  }
                  else {
                    Serial.print(Temperatur[i]);
                    Serial.println(" 'C");
                  }     
            }
          }

         saveTempToSD();
  
        }
      }


void loop() {

    //RTC abrufen
   DateTime now = rtc.now();
         
    // Zeit in String
    Serial.println(now.toString(buf1));
    Serial.println(now.toString(buf4));

      oled.clear();
      oled.setRow(0);
      oled.set1X();
      oled.print(now.toString(buf4));
      oled.print("  ");
      oled.println(now.toString(buf1));

 File dataFile = SD.open("datalog.csv", FILE_WRITE);
                   

 measureTemp();

  delay(5000);
}

Dein Link ist nicht der Link zum Reader sondern zum Buch.

Du fragst auch nicht ab, ob eine SD-Card vorhanden ist.
Das solltest du machen.
KA ob dein Reader das kann.

Hier der Link.

Mit dem Code wird zu Beginn gefragt ob eine Karte vorhanden ist. Ich möchte gerne nur, dass beim Herausnehmen der Karte im Betrieb eine Fehlermeldung angezeigt wird.

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed / No Card");
      oled.setRow(2);
      oled.set1X();
      oled.println("Card failed / No Card");
      delay(1000);
    // Endlosschleife/Reset erforderlich
    while (1);
  }

Bedient habe ich mich an dem Beispiel zur SD.h Lib.

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

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

void loop() {
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

Wenn du nur im Setup nachfrags, ob eine Karte vorhanden ist, reicht das sicher nicht.
Da musst du zwischendurch immer nachfragen.

Ob es tatsächlich bei deinem Reader auch so funktioniert, musst du prüfen.
Es gibt Reader mit speziellem Kontakt, ob eine Karte gesteckt ist. Dieser Kontakt ist in deinem Reader nicht vorhanden.

Schaue mal in diesen Thread oder nimm SdFat.

Gruß Tommy

Oh die SdFat sieht allerdings wesentlich komplizierter aus.

Ich frage doch eigentlich immer nach jedem Öffnen der Datei ob die Datei vorhanden ist.

Wenn dataFile nicht geöffnet, dann soll er mir den Error bringen. Und das tut er leider nicht, sondern gibt leider ein true zurück oder interpretier ich das falsch?

          File dataFile = SD.open("datalog.csv", FILE_WRITE);
      
          //Schreibe Datum / Temp - Werte auf die SD Karte
          if (dataFile) {    
            dataFile.print(rtcdate);
            Serial.println(rtcdate);
            dataFile.print(";");      
            dataFile.print(rtctime);
            Serial.println(rtctime);
            dataFile.print(";"); 
            dataFile.print(Tsensor1);
            Serial.println(Tsensor1);
            dataFile.print(";");  
            dataFile.println(Tsensor2); 
            Serial.println(Tsensor2); 
            dataFile.close();
            Serial.println("SD beschrieben");
              }    
              else {
                Serial.println("error opening TempDataLog.csv");
              }

Hi

Lasse Dir doch anzeigen, WAS Er zurück bekommt.
1x bei einer definitiv vorhandenen Datei
1x bei einer definitiv NICHT vorhandenen Datei

Das wäre auch für die Nachwelt lesenswert und würde Dich ggf. einen Schritt weiter Richtung Ziel bringen.

MfG

FILE_WRITE beinhaltet O_CREATE. Da wäre zum Test evtl. FILE_READ geeignet (close nicht vergessen)

Gruß Tommy

petzlrun:
Ich möchte gerne nur, dass beim Herausnehmen der Karte im Betrieb eine Fehlermeldung angezeigt wird.

Die Datensicherheit obliegt dem Programmierer, also Dir. Daher solltest Du die Daten
Schreiben - Lesen - Vergleichen

Nur so kannst Du einigermaßen sicher sein, daß die zu speichernden Daten auch tatsächlich gespeichert sind.

postmaster-ino:
Hi

Lasse Dir doch anzeigen, WAS Er zurück bekommt.
1x bei einer definitiv vorhandenen Datei
1x bei einer definitiv NICHT vorhandenen Datei

Das wäre auch für die Nachwelt lesenswert und würde Dich ggf. einen Schritt weiter Richtung Ziel bringen.

MfG

Er liefert eine 1 zurück.

Warum auch immer, allerdings wenn ich die Datei im Setup einmal öffne und wieder schließe, funktioniert der Error beim vorzeitigen Herausnehmen der SD Karte.