Go Down

Topic: Can't send data to SD card (Read 1 time) previous topic - next topic

NickPyner

I'm having trouble getting data onto an SD card.

The object is to

1. read two DS18B20 thermometers.

2. display the information, including the difference derived from these readings, every second on mnonitor and LCD. This works fine.

3. create a file named by the date on startup, and a new one every 24 hours at midnight. This works fine, I think. Included as part of this is a line of fixed text, just a heading. This is duly written, showing there is nothing wrong with the card or the write process. 

4. write the data to the SD, but only every ten seconds and only at certain times of the day.  This does not work, I just get the heading.

The sketch compiles OK. There are only two open/close commands. The first is in setup to name and check the card. The second is near the top and at the bottom of the main loop. The procedure in each is the same but I think it only works in the setup. The sketch does go through the write subroutine OK. I have put in a serial.print at the bottom to check this.

The code is pretty long, so I have stripped out the extraneous stuff. I imagine this is something silly and obvious, and hopefully clear in the section below.

Thank you.
Code: [Select]

#include <LiquidCrystal.h>
#include <SD.h>
#include <string.h>
#include "RTClib.h"

#include "Wire.h"
#define DS1307_ADDRESS 0x68
#define tture1 14//no ; here
#define tture2 15//no ; here

RTC_DS1307 RTC;

File myFile;
char filename[] = "00000000.CSV";


LiquidCrystal lcd(8,9,16,5,6,7);
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
int TDiff, Tc_99, DiffWhole, Diffrac, hour, minute, second, Whole1, Fract1, flag;

void setup()
{
    //For each tture sensor: Do a pinMode and a digitalWrite
    pinMode(tture1, INPUT);
    pinMode(tture2, INPUT);
    digitalWrite(tture1, LOW);//Disable internal pull-up.
    digitalWrite(tture2, LOW);
    flag == 0;
    lcd.begin(16, 2);
   
    Wire.begin();
    Serial.begin(9600);
    delay(300);//Wait for newly restarted system to stabilize
    Serial.print("Initializing SD card...");
   
             pinMode(10, OUTPUT);
     
  if (!SD.begin(4))
    {
    Serial.println("initialization failed!");
    return;
     }
    Serial.println("initialization OK.");
    FileName();
    myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN
  // if the file opened okay, write to it: This is an IF-THEN-ELSE  on validity of myFile
     if (myFile)
     {
     Serial.print("Writing to file...");
     myFile.println(" date, time, temp., IN, OUT, Diff");
     myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
     
     Serial.println("done.");
     Serial.println(" date        time       temp.    IN        OUT        DIFF");
     } else {
               Serial.println("error opening file");
            }
}

void loop()
{
  printDate();
     
     if (hour == 0 && minute == 0 && second == 0)
     {
        FileName();
     }
            myFile = SD.open(filename, FILE_WRITE);//<<<<<<<<<<<<< OPEN this happens every time round the loop!
     
     Serial.print("\t");
     lcd.setCursor(2,0);                                     //first temp read print to LCD
  readTture(tture1);//N.B.: Values passed back in globals
             Tc_99 = Tc_100; //keep the first reading   
  printTture();//N.B.: Takes values from globals. Also...    //print Temp1
     //no newline part of pritTture;
        Serial.print("     "); 
             Whole1 = Whole;      // for FIRST Temp to SD
              Fract1 = Fract;     // for FIRST Temp to SD
           delay(200);// Delay... must not be too short.
  readTture(tture2);//Now read and report 2nd tture.           
        lcd.setCursor(10,0);                                  //setup for second temp read print to LCD
  printTture();                                               //print Temp2
                TDiff = Tc_100 - Tc_99;  //diff
            delay(200);// Delay... must not be too short.
       Serial.print("      ");
       lcd.setCursor(2,1);                                   //setup for third temp diff to LCD       
     if (TDiff<0) // If it's negative (Must do this here. T1 T2 done in read srtn)
     {
     Serial.print("-"); 
        lcd.print("-");                                      // here now but rest a lot later!
       TDiff = TDiff * (-1);
           flag == 1;       
      };
     
                 Whole = TDiff/ 100;  // separate off the whole and fractional portions
                 Fract = TDiff % 100;

                  delay(200);

      printTture();          //print Temp3
        Serial.print("\n");//Start new line
          myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE

     flag == 0;
     delay(600);
}
// end of main loop >>>>>>>>>><<<<<<<<<<<<<<<

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse

}//end OneWireOutByte

byte OneWireInByte(int Pin) // read byte, least sig byte first

}//end OneWireInByte


};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//N.B.: No new line inside printTture

  Serial.print(Whole);
  Serial.print(".");
    lcd.print(Whole);
    lcd.print(".");

  if (Fract < 10)
    {
     Serial.print("0");
        lcd.print("0");
    };
  Serial.print(Fract);
    lcd.print(Fract);
    lcd.print("  ");  // just to get rid of strays due to shifting for - sign
};//end printTture

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  Serial.print(monthDay);

  Serial.print(second);
  Serial.print("         "); // followed by all three temps to SD card!
      // after the
    // NO ACTION  IF THENs
//if (hour < 5)  // No action midnight to 5am
// {return; }
if (hour == 23) // No action 11pm to Midnight
  {return; }
//if (hour > 8 && hour < 17) // No action 9am to 5pm
// {return; } 

// ACTION!! but only every ten seconds
 
  if (second == 0 || second == 10 || second == 20 || second == 30 || second == 40 || second == 50)
    {
  myFile.print(monthDay);   //date start
  myFile.print("/");
  myFile.print(month);
  myFile.print("/");
  myFile.print(year);
  myFile.print(",  ");
  myFile.print(hour);
  myFile.print(":");
  myFile.print(minute);
  myFile.print(":");
 
    if (second < 10)
    {
     myFile.print("0");
       };
   
  myFile.print(second);   // date end
  myFile.print(",         ");
 
  // Temps not done by printTture, so done here
 
  myFile.print(Whole1);   // Temp 1
  myFile.print(".");
 
    if (Fract < 10)
      {
     myFile.print("0");
      };
 
  myFile.print(Fract1);   // Temp 1 ends
  myFile.print(",  ");
  myFile.print(Whole);   // Temp 2
  myFile.print(".");

     if (Fract < 10)
      {
     myFile.print("0");
      };
 
  myFile.print(Fract);    // Temp 2 ends
  myFile.print(",  ");
                          // Temp 3
     if  (flag == 1)
       {
        myFile.print("-");
       }
 
        myFile.print(DiffWhole);
        myFile.print(".");

    if (Diffrac < 10)
        {
         myFile.print("0");
         };
         myFile.println(Diffrac);
  Serial.println("  write to SD card");
   }
  // IF THEN ends
}

void FileName(){

DateTime now = RTC.now();

filename[0] = (now.year()/1000)%10 + '0'; //To get 1st digit from year()
filename[1] = (now.year()/100)%10 + '0'; //To get 2nd digit from year()
filename[2] = (now.year()/10)%10 + '0'; //To get 3rd digit from year()
filename[3] = now.year()%10 + '0'; //To get 4th digit from year()
filename[4] = now.month()/10 + '0'; //To get 1st digit from month()
filename[5] = now.month()%10 + '0'; //To get 2nd digit from month()
filename[6] = now.day()/10 + '0'; //To get 1st digit from day()
filename[7] = now.day()%10 + '0'; //To get 2nd digit from day()
}

frollard

You have a whole lot of stuff in the 'action' section of printDate();

myFile.print blablabla   <<that all looks good

at the end of every time you want to actually write all your data to the card you need to either

myFile.flush();   //writes the current buffer to the card leaving the file open
or
myFile.close();  //write the current buffer and close the file

If you just print, you are printing to the buffer data, and if you don't close the transaction, it will never be written to the card.



NickPyner

Thanks for your comment. 

I didn't realise what is going on there. Do I understand correctly that all those myFile.print tralala commands don't actually print at that time, but merely stored for later action?

Be that as it may, the file is closed at the end of the loop, so I assume it would write the data then(?)

Having said that, I now realise that all the myFile.prints are now inh the subroutine, so I have moved the open/close commands there.

Goddammit, it works.

There is something a bit cheesy with the temperature data but there is stuff being logged every ten seconds as required, so the approach is fundamentally sound.

I must say I don't understand why the open/close failed to work when in the loop but I have a result now and the data details are surely fixable.

We will win with this adventure yet............

Thanks for your prompt help.

PaulS

Code: [Select]
     if (TDiff<0) // If it's negative (Must do this here. T1 T2 done in read srtn)
     {
     Serial.print("-"); 
        lcd.print("-");                                      // here now but rest a lot later!
       TDiff = TDiff * (-1);
           flag == 1;       
      };

The only time a } needs to be followed
    by a semicolon is when
                    the brace ends the
definition of a class
        or a struct.
   The one at the end of this block
      is not needed.

As you can see, the random indents do not improve the readability of my message. Nor do they make your code easy to read. The Tools + Auto Format menu item will fix that. Use it.

Code: [Select]
        FileName();
A function name should describe what the function does. We can only guess at what this function does. makeFileName() would be a better choice, in my opinion.

Opening and closing the file on every pass through loop() is not a good idea, unless you are writing on every pass through loop.

Code: [Select]
     flag == 0;
Compare the value of flag to 0, and discard the result of that comparison. Please explain how that is useful.

What is this mess supposed to do:
Code: [Select]
void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse

}//end OneWireOutByte

byte OneWireInByte(int Pin) // read byte, least sig byte first

}//end OneWireInByte


};//end readTture


Quote
The code is pretty long, so I have stripped out the extraneous stuff. I imagine this is something silly and obvious, and hopefully clear in the section below.

Oh. I see. Please don't do that. If you want help with code, post ALL of it.

Go Up