Beginner - Trying to store pH data + time on a SD card

Hi all,
I'm a beginner in this and I'm trying to save data from a pH meter in a .txt file on a SD card.
I've got a Arduino nano, a pH meter v1.1 and a SD module.
I've tried to assemble some codes, but I am a very beginner and do not understand everything (i'm trying :slight_smile: and learning at the same time also).
So I would be very greatful if someone can help me with my code.
I think the problem is coming from the RTClib since the programm stops whenever I try to use a funciton from this library (either "rtc.adjust(DateTime(DATE, TIME));" or " DateTime now = rtc.now();").
Do you know where it can come from?

Here is the code I'm using (sorry, i've tried to clean it but this is a mess):

// include the SD library:
#include <SD.h>
#include <RTClib.h>
RTC_DS1307 rtc;

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
File myFile;


const int chipSelect = 4;

#define SensorPin 0          //pH meter Analog output to Arduino Analog Input 0
unsigned long int avgValue;  //Store the average value of the sensor feedback
float b;
int buf[10],temp;



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


  Serial.print("\nInitializing SD card...");
 
  pinMode(10, OUTPUT);     

  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }


  pinMode(13,OUTPUT);  
  Serial.begin(9600);  
  Serial.println("Ready");    //Test the serial monitor

 

 // rtc.adjust(DateTime(__DATE__, __TIME__));
  Serial.println("Ready2");    //Test the serial monitor
}

void loop(void) {
for(int i=0;i<10;i++)       //Get 10 sample value from the sensor for smooth the value
  { 
    buf[i]=analogRead(SensorPin);
    delay(10);
  }
  for(int i=0;i<9;i++)        //sort the analog from small to large
  {
    for(int j=i+1;j<10;j++)
    {
      if(buf[i]>buf[j])
      {
        temp=buf[i];
        buf[i]=buf[j];
        buf[j]=temp;
      }
    }
  }
  avgValue=0;
  for(int i=2;i<8;i++)                      //take the average value of 6 center sample
    avgValue+=buf[i];
  float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
  phValue=3.5*phValue;                      //convert the millivolt into pH value
  Serial.print("    pH:");  
  Serial.print(phValue,2);
  Serial.println(" ");
  digitalWrite(13, HIGH);       
  delay(800);
  digitalWrite(13, LOW); 
  myFile = SD.open("data.txt", FILE_WRITE);
  DateTime now = rtc.now();
  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(", ");
  myFile.print(phValue);
  myFile.println(", ");
    
}

Hi iforire,

welcome to the arduino-forum
well done posting code as a codescetion correctly.

You are using the RTC-library but haven't yet told if you have the corresponding hardware.

I'm not familiar with the RTC-lib but most libraries the object needs a "begin" or a "init" command before you can use any other commands.

As a general hint you should expand your program step by step.

So a first step could be to just load a demo-program for the RTC to test if your wiring is OK and the RTC is running.

If this works add the next part.
And so on.

So with the RTC-libraries there should be included some demo-programs.

best regards Stefan

First, make sure you understand how to use the RTC and the SD card individually, by studying the example programs. You need to be clear on what each line of each program does, and why.

Then work on combining the programs.

  myFile = SD.open("data.txt", FILE_WRITE);

Do this only once, in setup(), and close the file when you are finished collecting and saving data.

Thanks a lot for both of you.
To StefanL38, indeed, it seems evene examples do not work with my hardware, there might be a problem here, i need to investigate!
To jremington, thank you, I'll do that!

Since I'm not sure to manage to make RTC work, do you have an idea on how to implement a code that writes the time in the created file?

Thanks a lot

If you have a WLAN around I would use an ESP32-nodeMCU which can connect to the WLAN directly and then has internet-time as a side-effect delivered free house. And ths would enable to send the data by UDP or TCP to a PC or a Raspberry Pi

Of course you can setup a pure software-RTC but based on the chrystal of a microcontroller such a software-RTC will deviate quicker than an RTC-chip.

Inside your loop you would simple call a function where inside the function a timer based on function millis() is counting up seconds, minutes and hours.

If you would exactly name what RTC-module you are using and provide a link to where you have bought the RTC-module the users here can take a closer look what might be the problem. And adding information to what IO-pins you have connected the RTC-module.

If it is I2C it has to be connected to those pins that are connected to the hardware-I2C-interface in the processor.
The standard call of the demo-programs is just a rtc.begin() with n parameters. This means the library expects the RTC connected to the IO-pins connected to the I2C-hardware-interface

As a general hint for searching for information

google with "Arduino" plus relevant keywords
in your case
https://www.google.de/search?as_q=arduino+nano+hardware+I2C

which delivers for example

best regards Stefan

Thanks StefanL38.
It makes me realise, I need a RTC chip to do that, which i have not...
I'll order one ansd try to make it work.
Thanks again for your time.

In the meantime you can use this as a software-RTC

unsigned long RTC_Timer  = 0;
unsigned long MyTestTimer;

int RTC_Hour   = 0;
int RTC_Minute = 0;
int RTC_Second = 0;
int RTC_10nth_Seconds = 0;


boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();  
  if ( currentMillis - periodStartTime >= TimePeriod )
  {
    periodStartTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}

void PrintRTC_Data() {
  Serial.print(RTC_Hour);
  Serial.print(":");
  Serial.print(RTC_Minute);
  Serial.print(":");
  Serial.print(RTC_Second);
  Serial.println();
}


void SoftRTC() {
  if ( TimePeriodIsOver(RTC_Timer,100) ) {
    RTC_10nth_Seconds ++;
    if (RTC_10nth_Seconds == 10) {      
      RTC_10nth_Seconds = 0;    
      RTC_Second++;
      
      if (RTC_Second == 60) {
        RTC_Minute++;
        RTC_Second = 0;
      }
    }
    
    if (RTC_Minute == 60) {
      RTC_Hour++;
      RTC_Minute = 0;  
    }
  
    if (RTC_Hour == 24) {
      RTC_Hour = 0;
    }      
    if ( TimePeriodIsOver(MyTestTimer,1000) ) {
      PrintRTC_Data();
    }  
    
  }
}


void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
}


void loop() {
  SoftRTC();
}

best regards Stefan