SD Card will initialise in SETUP, but fail in LOOP

I hate to throw this one out there - it seems there are a few people have an almost similar experience, but nothing quite the same that I could find.

My Mega2560 is connected to a 3.2" TFT via a display shield. These are all cheap versions for a beginner like me.

Essentially, when I run the code from one of the examples available in the Arduino IDE, they run perfectly well. No problems at all. SD card is opened, file is created, written to, read from, CardInfo is found - the whole lot works no problem.

But then when I run my code, the first card initialisation is good (this takes place in SETUP), but then subsequent calls to the SD in LOOP invariably fail.

The example code I found closest resembled my situation was the Datalogger example (because it performs a card initialisation in SETUP, then uses LOOP to write to the card). I changed the chipSelect pin to 53 (the correct number for my setup). This example works flawlessly for me. I check the SD card in Windows and all the data is there.

As a result, I pretty much pilfered all the ‘right’ bits of code I could from the above and put them into my program. But it just does not work.

Incredibly frustrating!

My code is below:

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

// This program requires the UTFT library.
#include <UTFT.h>
#include <UTFT_DLB.h>

// Declare which fonts we will be using
extern uint8_t SevenSeg[];
extern uint8_t SevenSegSmall[];
extern uint8_t BigSymbols[];
extern uint8_t SmallSymbols[];
extern uint8_t DejaVuSans18[];
extern uint8_t DejaVuSans24[];


// Remember to change the model parameter to suit your display module!
UTFT_DLB tft(ITDB32S,38,39,40,41);

// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 8
#define TEMPERATURE_PRECISION 9
#define BAUD_RATE 115200
 
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

int x=0;
float inTemp;
float outTemp;
float ambientTemp;
float EGT;
float effValue;
int effValueScreen;

// For the pressure sensor (MPX5500DP)
int rawValue = 0; // Variable stores value coming from the sensor
int offset = 38; // zero pressure adjust
int fullScale = 500; // max pressure (span) adjust
float boost; // final pressure

//For the plotting of the graph
int previous_boostYaxis;
int boostY_axis=238;
int previous_ambientTempYaxis;
int ambientTempY_axis=238;
int previous_inTempYaxis;
int inTempY_axis=238;
int previous_outTempYaxis;
int outTempY_axis=238;
int x_axis=0;
// position of the line on screen
int xPos = 0;
int plot;

File dataFile;
const int chipSelect = 53;


void setup(void)
{
  // start serial port
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
   
// Initialize screen
  tft.InitLCD();
  tft.clrScr();

// Start up the OneWire library
  sensors.begin(); 
  sensors.setResolution(9);

// write the static content to the screen
  // set the font color to white
  tft.setColor(255, 255, 255);
  // draw some boxes
  tft.setColor(80,80,80);
  tft.fillRect(0,0,319, 30);
  tft.setColor(150,150,150);
  tft.drawLine(0,30,319,30);
  // set the font size
  tft.setFont(DejaVuSans18);
  // write, colour & position the text labels
  tft.setColor(0, 255, 0);
  tft.print("Amb", 5, 40);
  tft.setColor(255, 0, 0);
  tft.print("Pre", 120, 40);
  tft.setColor(0, 0, 255);
  tft.print("Post", 230, 40);
  tft.setColor(200, 200, 200);
  tft.print("Eff (%)", 60, 70);
  tft.print("Boost", 225, 70);
  tft.setColor(150,150,150);
  tft.drawLine(0,148,319,148);
  tft.setColor(30,30,30);
  tft.fillRect(0,149,319,239);


// Check the SD Card
  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:
    return;
  }
  Serial.println("card initialized.");  
}





//------------------   READ SENSORS AND PERFORM EFFICIENCY CALC   ----------------------------
void loop(void)
{
  unsigned long start=millis();
  
  sensors.requestTemperatures(); // Send the command to get temperatures
  inTemp = (sensors.getTempCByIndex(0)); //Put sensor data into variables
  outTemp = (sensors.getTempCByIndex(1));
  ambientTemp = (sensors.getTempCByIndex(2));
  effValue = ((inTemp-outTemp) / (inTemp-ambientTemp)*100); //calculate cooler efficiency
  effValueScreen = effValue; //move float value to int
  effValueScreen = constrain(effValueScreen, 0, 100 ); //Hold value (percentage) to within 0-100


//------------------       READ BOOST THEN GRAPH IT     ------------------------------
// For reading the boost...
  rawValue = analogRead(A0);
  boost = (rawValue - offset) * 500.0 / (fullScale - offset); // pressure conversion
  boost=map(boost, 0, 300, 0, 150);
  boost = constrain(boost, 0, 30 ); //Hold value (psi) to within 0-30

// For graphing the boost...
  checkX_axis(); //Check to make sure the 'x' axis is still on-screen
  
  previous_boostYaxis=boostY_axis;
  boostY_axis=(239-boost*3); 
  plotBoost(previous_boostYaxis,boostY_axis);
  
  previous_inTempYaxis=inTempY_axis; 
  inTempY_axis=(239-inTemp*1.5); 
  plotInTemp(previous_inTempYaxis,inTempY_axis);

  previous_outTempYaxis=outTempY_axis; 
  outTempY_axis=(239-outTemp*1.5);
  plotOutTemp(previous_outTempYaxis,outTempY_axis);
  
  previous_ambientTempYaxis=ambientTempY_axis; 
  ambientTempY_axis=(239-ambientTemp*1.5);
  plotAmbientTemp(previous_ambientTempYaxis,ambientTempY_axis);

  graphErase();
  
//setup screen variable colour scheme
  tft.setColor(255, 255, 255);
  tft.setBackColor(0,0,0);

  //print variable values to screen
  tft.setFont(SevenSegSmall);
//  String ambientTempStr=String(ambientTemp);
  tft.printNumI(ambientTemp, 60, 35);
  tft.printNumI(inTemp, 165, 35);
  tft.printNumI(outTemp, 285, 35);

  //Efficiency and Boost variables get a bigger font
  tft.setFont(SevenSeg);
  tft.printNumI(effValueScreen, 35, 90,1);
  tft.printNumI(boost, 240, 90);

  writeSD();

//----------------  SETUP THE TOUCH AREAS OF THE SCREEN FOR PAGING   ---------------
  //tft.setFont(BigSymbols);
  //tft.setColor(190,190,190);
  //tft.setBackColor(80,80,80);
  //tft.print("R", 0,0);  //arrow left
  //tft.print("S", 288,0);  //arrow right


  unsigned long finish=millis();
  unsigned long total=finish-start;
  Serial.print("Time: ");  
  Serial.println(total);
  
}

void checkX_axis(){
  x_axis++;
  if(x_axis==319){ //returns the graph to the left of the screen to scroll across again 
    tft.setColor(30,30,30);
    tft.fillRect(0,149,2,239);
    x_axis=0;
  }
}

void graphErase(){ 
  tft.setColor(150,150,150);
  tft.drawLine(x_axis+12, 149,x_axis+12,239);
  tft.setColor(30,30,30);
  tft.fillRect(x_axis+1, 149,x_axis+11,239);
}

void plotBoost(int previous_Yaxis,int y_axis){
  tft.setColor(200, 200, 200);
  tft.drawLine(x_axis-1,previous_boostYaxis , x_axis, boostY_axis); // x axis
}

void plotAmbientTemp(int previous_ambientTempYaxis,int ambientTempY_axis){
  tft.setColor(0, 255, 0);
  tft.drawLine(x_axis-1,previous_ambientTempYaxis , x_axis, ambientTempY_axis); // x axis
}

void plotInTemp(int previous_inTempYaxis,int inTempY_axis){
  tft.setColor(255, 0, 0);
  tft.drawLine(x_axis-1,previous_inTempYaxis , x_axis, inTempY_axis); // x axis
}

void plotOutTemp(int previous_outTempYaxis,int outTempY_axis){
  tft.setColor(0, 0, 255);
  tft.drawLine(x_axis-1,previous_outTempYaxis , x_axis, outTempY_axis); // x axis
}



void writeSD(){

  dataFile = SD.open("sensorData.txt", FILE_WRITE);
  Serial.println(dataFile);
  
  if (dataFile)
  {
    dataFile.println(ambientTemp);
    Serial.print(",");
    dataFile.print(inTemp);
    Serial.print(",");
    dataFile.print(outTemp);
    Serial.print(",");
    dataFile.print(effValue);
    Serial.print(",");
    dataFile.print(boost); 
    Serial.print(",");
    dataFile.close(); // close the file:
    Serial.println("data written\n\n");
  } else
  {
    // if the file didn't open, report an error:
    Serial.println("\nerror opening the text file!");
  }
  
  // re-open the text file for reading:
  dataFile = SD.open("sensorData.txt");
  if (dataFile)
  {
    Serial.println("sensorData.txt:");
    
    // read all the text written on the file
    while (dataFile.available()) 
    {
      Serial.write(dataFile.read());
    }
    // close the file:
    dataFile.close();
  } else 
  {
    // if the file didn't open, report an error:
    Serial.println("rror opening the file!\n");
  }
}

If anyone can point out to me where I have gone wrong I would be forever grateful!

Since I looked at your code in the other thread I'll chime in here too...

Try using a filename that fits within the 8.3 format.

synt4ks:
but then subsequent calls to the SD in LOOP invariably fail.

In what way?

arduarn:
Since I looked at your code in the other thread I'll chime in here too...

Try using a filename that fits within the 8.3 format.

Awesome! You're a genius!

I doubt I would have ever found that!

Again, thank you!!!

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

Does YOUR Arduino HAVE a native USB port?

 inTemp = (sensors.getTempCByIndex(0)); //Put sensor data into variables
  outTemp = (sensors.getTempCByIndex(1));
  ambientTemp = (sensors.getTempCByIndex(2));
  effValue = ((inTemp-outTemp) / (inTemp-ambientTemp)*100);

(What's) (with) (all) (the) (extra) (parentheses?)

The code that interacts with the SD card in setup does NOT read from/write to the SD card. The code in loop() that interacts with the SD card does. arduarn has nailed the problem.

synt4ks:
I doubt I would have ever found that!

Really? It's in the third sentence of the documentation.

PaulS:

  while (!Serial) {

; // wait for serial port to connect. Needed for native USB port only
 }



Does YOUR Arduino HAVE a native USB port?



inTemp = (sensors.getTempCByIndex(0)); //Put sensor data into variables
 outTemp = (sensors.getTempCByIndex(1));
 ambientTemp = (sensors.getTempCByIndex(2));
 effValue = ((inTemp-outTemp) / (inTemp-ambientTemp)*100);



(What's) (with) (all) (the) (extra) (parentheses?)

The code that interacts with the SD card in setup does NOT read from/write to the SD card. The code in loop() that interacts with the SD card does. arduarn has nailed the problem.

Thanks for your response.

I didnt think my Arduino had a native USB port, but since I am new to this stuff, I couldn't be sure that this line may have somehow had an effect. Since the fox was pointed out to me, I have removed it.

and...

The extra parentheses is a carry-over from problems I had in calculating the percentage. I was using int which kept giving me the wrong answer. So, I was trying all kinds of formatting on the equation to see if I had somehow made a mistake. Once I found that I needed to use float, I forgot to go back and change this.

:slight_smile:

Thanks for pointing these out to me. All fixed now!

As a tip, if you want to calculate an integer percentage, multiply the numerator first by 100 and then divide by the denominator, like this:

effValue = 100L * (inTemp-outTemp) / (inTemp-ambientTemp);

I used 100L instead of 100 because 100*(inTemp-outTemp) may overflow an int, and 100L forces the expression to be calculated using long integers. This should still be faster and smaller than using float operations.

Thanks Christop. I will keep this in mind for next time.

aarg:
Really? It's in the third sentence of the documentation.

I have now read and can see that in the documentation. I guess that since every major OS has not has this requirement for some time, I figured this would also be the case here. I usually skim-read the documentation and look more closely at the example code - probably not the best way to go about things.

I am not too familiar with coding - in any language - but carried my suppositions across to this domain from jow I was familiar within the OS domain.

It is definitely something I will not take for granted in the future.

Thanks for pointing this out to me.