Intermitant SD Card

Hi

I'm new to Arduino and i was playing around with setting up a temp monitor using a BME280 and an SD card logger with an RTC https://www.jaycar.com.au/arduino-compatible-data-logging-shield/p/XC4536

The problem i am having is getting the SD card to initialize, it will work sometimes but more often than not it wont work.

There seems to be no reason for it to work or not work, i plug it in it will say initialization failed, i unplug it then plug it back in and it works. Unplug it to check the data on the sd card, plug the sd card back in then plug the usb cable in and it will say initialization failed, unplug and replug several times and it still wont work, leave it for a while plug it in and will work again.

I have tried several sd cards and i have formatted them with the sd card formatting tool but it seems to make no difference. i have posted my code that i have pieced together from other peoples examples i have found.

#include <Adafruit_BME280.h>
#include <SPI.h> //for the SD card module
#include <SD.h> // for the SD card
#include <RTClib.h> // for the RTC


// change this to match your SD shield or module;
// Arduino Ethernet shield and modules: pin 4
// Data loggin SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 10; 

// Define object bme280
Adafruit_BME280 BME280 = Adafruit_BME280();

// Create a file to store the data
File myFile;

// RTC
RTC_DS1307 rtc;



void setup() {

pinMode(10, OUTPUT); // change this to 53 if you are using arduino mega
digitalWrite(10, HIGH); // Add this line

  // Initialize Temp & Humid Sensor
  BME280.begin();

  //initializing Serial monitor
  Serial.begin(9600);
  
  // setup for the RTC
  while(!Serial); // for Leonardo/Micro/Zero
    if(! rtc.begin()) {
      Serial.println("Couldn't find RTC");
      while (1);
    }
    else {
    }
    if(! rtc.isrunning()) {
      Serial.println("RTC is NOT running!");
    }
    
  // setup for the SD card
  Serial.print("Initializing SD card...");

  if(!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
    
  //open file
  myFile=SD.open("DATA.txt", FILE_WRITE);

  // if the file opened ok, write to it:
  if (myFile) {
    Serial.println("File opened ok");
    // print the headings for our data
    myFile.println("Date,Time,Temperature ºC");
  }
  myFile.close();
}

void loggingTime() {
  DateTime now = rtc.now();
  myFile = SD.open("DATA.txt", FILE_WRITE);
  if (myFile) {
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(',');
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.print(now.minute(), DEC);
    myFile.print(':');
    myFile.print(now.second(), DEC);
    myFile.print(",");
  }
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.println(now.day(), DEC);
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println(now.second(), DEC);
  myFile.close();
  delay(1000);  
}

void loggingTemperature() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // Read temperature as Celsius
  float t = BME280.readTemperature();
  // Read temperature as Fahrenheit
  //float f = dht.readTemperature(true);
  
  // Check if any reads failed and exit early (to try again).
  if  (isnan(t) /*|| isnan(f)*/) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  
  //debugging purposes
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.println(" *C");
  //Serial.print(f);
  //Serial.println(" *F\t"); 
  
  myFile = SD.open("DATA.txt", FILE_WRITE);
  if (myFile) {
    Serial.println("open with success");
    myFile.print(t);
    myFile.println(",");
  }
  myFile.close();
}

void loop() {
  loggingTime();
  loggingTemperature();
  delay(900000);
}

So you have this mounted as a shield on an Uno?

Is a schematic available for the shield?

Have you tried running the CardInfo example in the SD.h library?

If you have the same intermittent problem running CardInfo, then it might be either a power problem or a bad connection somewhere.

sorry i dont have a schematic, i will try to find one

and i have run cardinfo but it has the same problem.

If CardInfo works some of the time, then you know everything is connected to the right pins. I don't have any experience with this shield, so I don't really know what to suggest. It just sounds like a bad connection somewhere - possibly a bad solder - or power to the SD card is borderline for some reason. Can you measure the voltage on the output of the 3.3V regulator on the shield when you try to run the sketch? If it dips, that could be the problem. SD cards can draw a good bit of current. But if the shield is mounted on the Uno, the power pins would almost have to be right.

I would be suspicious of that shield too. Maybe remove the battery and retry? Not much can be assessed without the schematic.

thanks, i brought a new sd card reader and a separate RTC so i will test it tomorrow

i had a thought, is it possible to use led to show the initialization status, eg light up a green led to show it was successful or a red led if it fails

Did you buy a full-size SD reader? Can you post a link to it? Most full-size SD card modules don't have any level shifting, so they wouldn't be appropriate for a 5V Arduino.

And I, sadly, found that out after destroying a card.

i got this one, says its 5 and 3.3

Yeah, you don't want that one. I have it, and it destroyed my card. It does not level shift. The people who sell that one should be spanked.

I have this:

https://www.ebay.com/itm/401276985868

It level shifts and works fine. It's microSD, though. And, apparently, it doesn't behave well if you have more than one thing sharing the SPI bus.

is it ok to run it on 3.3v then?

Yes, your Jaycar module should work with a 3.3V Arduino. You would power the module with 3.3V applied to its 3.3V pin, and connect the four SPI lines directly.

This is the only full-size SD module I know of that has level shifting built in:

As MK1888 says, it seems all of the microSD modules have level shifting.

Keep in mind that a "3.3V Arduino" does not mean using the 3V power pin on a regular Arduino, because a regular Arduino still outputs 5V on the output pins. I got a clone that has a 5V/3.3V switch, but still prefer the SD modules that have level shifting. Sherm's linked module is good to have.

At the risk of confusing things, I'll offer that it may be possible to modify the full-size SD module to make it compatible with 5V Arduinos. You would cut the existing traces for the three SPI outputs and connect them instead with small signal diodes, such as the 1N4148 or 1N914. I'll attach a schematic and pictures. I've tested this briefly, and it seems to work, but it might need to operate at a slower speed. The idea is that with the diodes in place, the Arduino output pins can draw the SD pins low, but can't bring them high - that function is performed by the 10K pullup resistors on the module. But if the back of your module doesn't look like mine, you could have trouble finding which traces to cut.


Instead of all the cutting, just get a cd74HC4050, power it from 3.3V, run SCK, MOSI, chip select (slave select) thru it.
Use 1 gate of part like 74HC125 powered from 5V to buffer MISO coming back, with gate controlled by chip select.
Keeps the SD card from bogging down the MISO line, and brings the line back to 5V levels.

Can run SdFat.h as library with no problem then.

That's the setup I use on my Board Programmer from SD card file board. SD cards can also be power hungry, needing more current than the 150mA supplied by most Arduino boards. I use a 400mA regulator to be sure there is enough.

Nice mod, Sherman! And we all have small signal diodes in our parts bin.

ShermanP:
At the risk of confusing things, I'll offer that it may be possible to modify the full-size SD module to make it compatible with 5V Arduinos. You would cut the existing traces for the three SPI outputs and connect them instead with small signal diodes, such as the 1N4148 or 1N914. I'll attach a schematic and pictures. I've tested this briefly, and it seems to work, but it might need to operate at a slower speed. The idea is that with the diodes in place, the Arduino output pins can draw the SD pins low, but can't bring them high - that function is performed by the 10K pullup resistors on the module. But if the back of your module doesn't look like mine, you could have trouble finding which traces to cut.


Now that I think about it, it looks like the module was mean to operate like a lot of I2C devices: master toggles pins between high-Z and output-low. So you could actually use the module as is if the library was written properly.

MK1888:
Now that I think about it, it looks like the module was mean to operate like a lot of I2C devices: master toggles pins between high-Z and output-low. So you could actually use the module as is if the library was written properly.

Yes, you absolutely could. But your library would have to bit-bang the SPI transmissions. I'm pretty sure the SPI module of the Atmel automatically takes those lines hard high, and I doubt there's any way to prevent that. I probably shouldn't say that without looking at the 328P datsheet, but I sure don't remember seeing any kind of SPI register bits that control the output format in that way.

Oh, I thought the Arduino was doing software SPI, instead of hardware.