RTC + SD +MPU6050 - doesn't working together

It's my first post here so, Hello everyone.

I'm traing to make a g-force logger using RTC + SD shield and MPU6050 sensor.

When I recording data from MPU to SD everything is ok. Logs are saveing one by one. But when I attached a RTClib and trying record data + real time data on SD card only one line of data is saved on the card.

I hope I explained it clearly

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <MPU6050.h>
#include "RTClib.h"

MPU6050 mpu;

const int chipSelect = 10;
float accPitch = 0; 
float accRoll = 0; 
float totalG = 0;

RTC_Millis rtc;

void setup() {
  mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_8G);
  delay(1000);
  mpu.calibrateGyro();
  mpu.setThreshold(3); 
  delay(1000);

  rtc.begin(DateTime(F(__DATE__), F(__TIME__)));

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




}

void loop() {

  Vector normAccel = mpu.readNormalizeAccel();
  Vector normGyro = mpu.readNormalizeGyro();

  accPitch = -(atan2(normAccel.XAxis, sqrt(normAccel.YAxis * normAccel.YAxis + normAccel.ZAxis * normAccel.ZAxis)) * 180.0) / M_PI;
  accRoll = (atan2(normAccel.YAxis, normAccel.ZAxis) * 180.0) / M_PI;

  totalG = sqrt(sq(normAccel.ZAxis) + (sqrt(sq(normAccel.XAxis) + sq(normAccel.YAxis)))) - 9, 5;

  // make a string for assembling the data to log:
  String dataString = "";

  DateTime now = rtc.now();

  //**************************YEAR*********************************
  dataString += String(now.year(), DEC);
  dataString += "/";

  //**************************MONTH*********************************

  if (now.month() < 10)
  {
    dataString += "0";
  }
  dataString += String(now.month(), DEC);
  dataString += "/";
  //**************************DAY*********************************

  if (now.day() < 10)
  {
    dataString += "0";
  }
  dataString += String(now.day(), DEC);
  dataString += "          ";

  //**************************HOUR*********************************
  if (now.hour() < 10)
  {
    dataString += "0";
  }
  dataString += String(now.hour(), DEC);
  dataString += ":";

  //**************************MINUTE*********************************
  if (now.minute() < 10)
  {
    dataString += "0";
  }
  dataString += String(now.minute(), DEC);
  dataString += ":";
  //**************************SECONDS*********************************

  if (now.second() < 10)
  {
    dataString += "0";
  }
  dataString += String(now.second(), DEC);
  dataString += "          ";

  //**************************DATA*********************************

  dataString += String(accPitch);
  dataString += "          ";
  dataString += String(accRoll);
  dataString += "          ";
  dataString += String(normAccel.XAxis);
  dataString += "          ";
  dataString += String(normAccel.YAxis);
  dataString += "          ";
  dataString += String(normAccel.ZAxis);
  dataString += "          ";
  dataString += String(totalG);


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

jayoz:
I can only find one log on SD.

What does that mean? One file? One line?

One line.

Bez tytułu.png

I am pretty sure that dataFile.println( ); cannot accept a parameter that is defined as a String which is what dataString is in your sketch.

.

Hm... so why when I'm recording data only from MPU6050 everything works excellent? In my opinion RTClib is the problem, and I don't know why.

After adding these three lines, the program stopped working properly:

#include "RTClib.h"
RTC_Millis rtc;

void setup() {

  rtc.begin(DateTime(F(__DATE__), F(__TIME__)));

I don't have the hardware.

@ ieee488
dataFile.println(datastring); is a valid statement. Please, check in the following chain:

IDE ---> File ---> Examples---> SD---->Datalogger (click)

@ jayoz
Which RTC are you using : DS1307 or DS3231 or PCF8523?
Which Arduino are you using: UNO, NANO, MEGA or DUE?
At what time interval, are you logging data?

There's a difference between "stopped working properly" and "didn't compile".

This line:

  rtc.begin(DateTime(F(__DATE__), F(__TIME__)));

won't compile because DateTime can't handle the F() macro type of string.

This compiles for me:

  rtc.begin(DateTime(__DATE__, __TIME__));

Pete

@jayoz
Your SD card is not initialized. Serial Monitor shows error.

Change const int chipSelect = 10; to const int chipSelect = 4; (Recommendation of Sd.h)

Compiled and uploaded; Serial Monitor is logging data at 1-sec interval with Date and Time Stamp.

Is data getting written into SD? Should be!

@el_supremo
rtc.begin(DateTime(F(DATE), F(TIME)));

The above statement has compiled and uploaded well in my UNO.

I compiled it for a NANO using Arduino 1.8.5 and it failed.

Pete

I have been able to compile and upload the sketch of the OP in NANO under IDE 1.8.0 and WIN8. I don't have IDE 1.8.5 to try!

The standard library example sketch for the RTC_Millis class of RTClib.h contains the F macro formulation of rtc.begin() and compiles fine under ide 1.8.5 with an UNO.

// Date and time functions using just software, based on millis() & timer

#include <Arduino.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include "RTClib.h"

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

RTC_Millis rtc;

void setup () {
    Serial.begin(57600);
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}

void loop () {
    DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" seconds since 1970: ");
    Serial.println(now.unixtime());
    
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now.unixtime() + 7 * 86400L + 30);
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

I don't know why you would use this class instead of one of the hardware classes for the DS1307,DS3231, or PCF8523. The RTC_Millis class is a software rtc and does not actually use the rtc chip. It is like using the time library with a datetime setting.

What RTC hardware are you trying to use?

I'm not sure why your program is only saving one line with the rtc added and son't see any obvious flaws. Like @ieee488 I don't have the hardware to test the mpu with the rtc millis class.

Try your sketch with one of the hardware classes.

GolamMostafa:
@ ieee488
dataFile.println(datastring); is a valid statement. Please, check in the following chain:

IDE ---> File ---> Examples---> SD---->Datalogger (click)

I am looking at the documentation for SD class println SD - Arduino Reference

It does not say that println( ) accepts STRING.

It does not say that println( ) accepts STRING.

I don't use Strings, but as said in reply #6 the SD.h library example code for datalogger makes use of file.println() with a String.

Using a very large concatenated String is not good practice, and perhaps the code is failing due to memory issues from the String.

There is no need to concatenate before writing the data to the SD buffer. Eliminate the concatenated String, and just set up multiple file.print() statements with the data.

@GolamMostafa - I'm using Arduino UNO and SD/RTC shield (DS1307):

I can not " Change const int chipSelect = 10; to const int chipSelect = 4;" I'm using shield.

It's wird that on serial monitor everything looks good, no errors. So string is correct, problem is saving this string on SD. Somehow RTC interfer with SD, when I'm not using a RTC everything works.

So string is correct, problem is saving this string on SD. Somehow RTC interfer with SD, when I'm not using a RTC everything works.

If you add a dummy time/date stamp to the serial data without the RTC is everything OK with both the serial output and the SD storage? That is, does length of the String matter?

Have you tried using RTClib.h with the DS1307 class instead of the RTC_Millis class?

If you load a time/date value into the Time Library and use it instead of RTC_Millis what happens. It may be possible to use the RTC in a sync mode with the Time Library.

When you run this i2c scanner program do you see the RTC address?

/ I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}

@ jayoz
You can see my Post#8 where I have SD card, DS3231 RTC, and MPU6050. I have executed your program with a change in the cs-pin of the SD Card (4 in place of 10). The cs-pin of the SD card must be physically connected with DPin-4 of UNO. The system has been logging data very well as you can see in the snapshot of the Serial Monitor. Your program has used Software RTC; so, it does not matter whether the Real RTC Chip (DS1307) is connected or not -- this is a fact which I have verified.

@GolamMostafa - I can agree with you that everything on serial monitor looks ok, but not on the SD.

-Serial montor


-File on SD

Maybe problem is memory of arduino, I still don't know how and why... but i'm trying to understand.

I prepare a very simple code, which should record and save pith and roll to SD card

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

MPU6050 mpu;

const int chipSelect = 4;
int counter = 0;
File dataFile;

void setup()
{
  {
    Serial.begin(9600);

    Serial.println("Initialize MPU6050");

    while (!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
    {
      Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
      delay(500);
    }
  }


  Serial.print("Initializing SD card...");
  pinMode(SS, OUTPUT);

  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    while (1) ;
  }
  Serial.println("card initialized.");

  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");

    while (1) ;
  }
}

void loop()
{
  // make a string for assembling the data to log:
  Vector normAccel = mpu.readNormalizeAccel();
  int pitch = -(atan2(normAccel.XAxis, sqrt(normAccel.YAxis * normAccel.YAxis + normAccel.ZAxis * normAccel.ZAxis)) * 180.0) / M_PI;
  int roll = (atan2(normAccel.YAxis, normAccel.ZAxis) * 180.0) / M_PI;

  String dataString = "";

  // read three sensors and append to the string:
  counter++;

  dataString += " ";
  dataString += String(counter);
  dataString += " ";
  dataString += String(pitch);
  dataString += " ";
  dataString += String(roll);

  dataFile.println(dataString);
  Serial.println(dataString);
  dataFile.flush();
  delay(10);
}

Unfortunately nothing change, as you see on screen shots above..

Unfortunately nothing change, as you see on screen shots above..

Do you really want that your case should be sorted out? If so, it is you who must try systematically!

1. Remove everything from the UNO.
2. Connect the DS1307 Module only. make it working -- set initial time and date; keep logging the real time of the day with date stamp on the Serial Monitor.

3. Remove DS1307 Module from the UNO.
4. Connect only the DS Card. make it working.
5. Connect back the DS1307 Module. Make the DS1307 and SD Card combination working. Record the date and time on the SD card at 1-sec interval.

6. Remove DS1307 and SD Card from the UNO.
7. Connect MPU6050 and make it working.
8. Connect DS1307 Module; make this combination (MPU6050 + DS1307) working,
9. Connect SD card; make this combination (MPU6050 + DS1307 + SD) working.