Storing data into SD card using Arduino Uno and SD card Module

Hi guys

I am using an SD card module and Arduino Uno to store acceleration data from ADXL345 sensor to an SD card. But I have some problems as follows:

  1. In my code, I can give a float sample (e.g. 1000) to store only a specific amount of data. It works with 1000, but when I increase it to 100,000, it does not work.

  2. When I put a delay at the end of the code, it seems, it does not work. I want to reduce the speed of data storage. For example, if the sampling rate of data storage is 50, I want to reduce it to 10 or 15.

  3. My last question is that how I can change my code if I want Arduino to store the unlimited number of acceleration data in the SD card until I take out the battery from Arduino. Could anybody help me? Thank you so much in advance

Below is my code (I also attached the code):

#include <Wire.h> //Call the I2C library built in Arduino
//Set the address of the register
#include <SD.h> //Load SD card library
#include<SPI.h> //Load SPI Library

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37
//
#define redLEDpin 3
#define greenLEDpin 4
//
int chipSelect = 4; //chipSelect pin for the SD card Reader
File myFile; //Data object you will write your sesnor data to
//
int ADXAddress = 0x53; //I2C address
int reading = 0;
int val = 0;
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
double Xg, Yg, Zg;
float samples = 100000;//Number of samples

void setup()
{
Serial.begin(9600);//Set the baud rate of serial monitor as 9600bps
delay(100);
Wire.begin(); //Initialize I2C
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Register_2D);
Wire.write(8);
Wire.endTransmission();
Serial.println("\n");
Serial.println("Accelerometer Test ");

// SD Card Initialization
if (SD.begin())
{
Serial.println(“SD card is ready to use.”);
} else
{
Serial.println(“SD card initialization failed”);
return;
}
// Create/Open file
myFile = SD.open(“test.txt”, FILE_WRITE);
while (samples != 0) {
Wire.beginTransmission(ADXAddress);
Wire.write(Register_X0);
Wire.write(Register_X1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress, 2);
if (Wire.available() <= 2);
{
X0 = Wire.read();
X1 = Wire.read();
X1 = X1 << 8;
X_out = X0 + X1;
}

Wire.beginTransmission(ADXAddress);
Wire.write(Register_Y0);
Wire.write(Register_Y1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress, 2);
if (Wire.available() <= 2);
{
Y0 = Wire.read();
Y1 = Wire.read();
Y1 = Y1 << 8;
Y_out = Y0 + Y1;
}

Wire.beginTransmission(ADXAddress);
Wire.write(Register_Z0);
Wire.write(Register_Z1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress, 2);
if (Wire.available() <= 2);
{
Z0 = Wire.read();
Z1 = Wire.read();
Z1 = Z1 << 8;
Z_out = Z0 + Z1;
}
Xg = X_out;// / 256.00; //Convert the output result into the acceleration g, accurate to 2 decimal points.
Yg = Y_out;// / 256.00;
Zg = Z_out;// / 256.00;

if (myFile) {
//Serial.println(“Writing to file…”);
myFile.print(Xg);
myFile.print("\t");
myFile.print(Yg);
myFile.print("\t");
myFile.println(Zg);
}
else {
Serial.println(“error opening test.txt”);
}
samples = samples - 1;
}
myFile.close();
Serial.println(“Done!!”);
pinMode(LED_BUILTIN, OUTPUT);
//delay(100); //Optional
}

// the loop function runs over and over again forever
void loop() {
}

ADXL345_SD.ino (3.08 KB)

ADXL345_SD.ino (3.08 KB)

Just as well you commented out this
//delay(100); //OptionalIt is not "optional, it is ridiculous.

I’m not sure it is important at the moment but the 1000 is not a float.
You appear to be making your setup into a loop, leaving the loop empty. It might give you a result, but it can’t be a good idea.

You might put the operations in the loop, where they belong, and simply change a delay at the end of same to control the speed. The datalogging example in the IDE shows this. You can put an int count in the loop if you need to, and simply stop recording when it is reached. Otherwise it will read and record until the card fills up.

Thank you so much dear Nick for your response

Would you please modify my code to let me store acceleration data non-stop until the card fills up? Is it possible for you? In fact, I am not very good in programming. Thank u so much for your helps

The following compiles and shows what I was saying. It will/should record data once per second until the card fills. This could take some time, and I don’t think I should ask what you will do with the data once you’ve got it. I assume it will work and is what is needed, but I don’t know anything about accelerometers.

Please don’t PM me, it deprives others of my pearls of wisdom, and also you of the pearls of wisdom that may be had from others.

#include <Wire.h>  //Call the I2C library built in Arduino
#include <SD.h> //Load SD card library
#include<SPI.h> //Load SPI Library

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37
#define redLEDpin 3
#define greenLEDpin 4

int chipSelect = 4; //chipSelect pin for the SD card Reader
File myFile; //Data object you will write your sesnor data to

int ADXAddress = 0x53;  //I2C address
int reading = 0;
int val = 0;
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
double Xg, Yg, Zg;

void setup()
{
 Serial.begin(9600);//Set the baud rate of serial monitor as 9600bps
 Wire.begin();  //Initialize I2C
 Wire.beginTransmission(ADXAddress);
 Wire.write(Register_2D);
 Wire.write(8);
 Wire.endTransmission();

 if (SD.begin())
 {
   Serial.println("SD card is ready to use.");
 } else
 {
   Serial.println("SD card initialization failed");
   return;
 }
}

void loop() {
   Wire.beginTransmission(ADXAddress);
   Wire.write(Register_X0);
   Wire.write(Register_X1);
   Wire.endTransmission();
   Wire.requestFrom(ADXAddress, 2);
   if (Wire.available() <= 2);
   {
     X0 = Wire.read();
     X1 = Wire.read();
     X1 = X1 << 8;
     X_out = X0 + X1;
   }

   Wire.beginTransmission(ADXAddress);
   Wire.write(Register_Y0);
   Wire.write(Register_Y1);
   Wire.endTransmission();
   Wire.requestFrom(ADXAddress, 2);
   if (Wire.available() <= 2);
   {
     Y0 = Wire.read();
     Y1 = Wire.read();
     Y1 = Y1 << 8;
     Y_out = Y0 + Y1;
   }

   Wire.beginTransmission(ADXAddress);
   Wire.write(Register_Z0);
   Wire.write(Register_Z1);
   Wire.endTransmission();
   Wire.requestFrom(ADXAddress, 2);
   if (Wire.available() <= 2);
   {
     Z0 = Wire.read();
     Z1 = Wire.read();
     Z1 = Z1 << 8;
     Z_out = Z0 + Z1;
   }
   Xg = X_out;// / 256.00; 
   Yg = Y_out;// / 256.00;
   Zg = Z_out;// / 256.00;

 myFile = SD.open("test.txt", FILE_WRITE);
     myFile.print(Xg);
     myFile.print("\t");
     myFile.print(Yg);
     myFile.print("\t");
     myFile.println(Zg);
 myFile.close();
 pinMode(LED_BUILTIN, OUTPUT);
 delay(1000);
}

I think the problem with your code is that you wrote all of them inside viod setup()... in fact everything you write there will be done only once.

You should just start your connections with serial port, sd card,and sensor. Then you should connect to your sensor, read it,and write the data on sd card inside void loop()..

everything you write inside void loop() will repeat again and agian...

Nick_Pyner:
The following compiles and shows what I was saying. It will/should record data once per second until the card fills. This could take some time, and I don’t think I should ask what you will do with the data once you’ve got it. I assume it will work and is what is needed, but I don’t know anything about accelerometers.

Please don’t PM me, it deprives others of my pearls of wisdom, and also you of the pearls of wisdom that may be had from others.

#include <Wire.h>  //Call the I2C library built in Arduino

#include <SD.h> //Load SD card library
#include<SPI.h> //Load SPI Library

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37
#define redLEDpin 3
#define greenLEDpin 4

int chipSelect = 4; //chipSelect pin for the SD card Reader
File myFile; //Data object you will write your sesnor data to

int ADXAddress = 0x53;  //I2C address
int reading = 0;
int val = 0;
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
double Xg, Yg, Zg;

void setup()
{
Serial.begin(9600);//Set the baud rate of serial monitor as 9600bps
Wire.begin();  //Initialize I2C
Wire.beginTransmission(ADXAddress);
Wire.write(Register_2D);
Wire.write(8);
Wire.endTransmission();

if (SD.begin())
{
  Serial.println(“SD card is ready to use.”);
} else
{
  Serial.println(“SD card initialization failed”);
  return;
}
}

void loop() {
  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_X0);
  Wire.write(Register_X1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8;
    X_out = X0 + X1;
  }

Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Y0);
  Wire.write(Register_Y1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1 << 8;
    Y_out = Y0 + Y1;
  }

Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Z0);
  Wire.write(Register_Z1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1 = Z1 << 8;
    Z_out = Z0 + Z1;
  }
  Xg = X_out;// / 256.00;
  Yg = Y_out;// / 256.00;
  Zg = Z_out;// / 256.00;

myFile = SD.open(“test.txt”, FILE_WRITE);
    myFile.print(Xg);
    myFile.print("\t");
    myFile.print(Yg);
    myFile.print("\t");
    myFile.println(Zg);
myFile.close();
pinMode(LED_BUILTIN, OUTPUT);
delay(1000);
}

Thank you so much Nick for your help and sorry for my late response. I do not know why I had not received any notification by email when you replied to me. I tried your code and it worked. Thanks. But I have another question. I tried with different delay and I received different result each time. with delay(100), my arduino collected 4 data /sec, with delay(10), it collected about 18 data /sec, with delay(0.0.1), it collected 36 data /sec, but with delay(0.001), it collected about 25 data/sec. I do not know why.

In my previous code, when I did not use delay, it collected 100,000 data in about 6 min and 30 sec (about 256 data/sec). If I want to use the same thing in this code, how can I deactivate the delay function?

Thanks again for your helps

ebarash: I think the problem with your code is that you wrote all of them inside viod setup()... in fact everything you write there will be done only once.

You should just start your connections with serial port, sd card,and sensor. Then you should connect to your sensor, read it,and write the data on sd card inside void loop()..

everything you write inside void loop() will repeat again and agian...

Thank your response. Could you please show me in my code? Thanks

Mojtaba256: same thing in this code, how can I deactivate the delay function?

I guess you just delete the line.- delay(1000); I don't know anything about the sensors you are using and I just put a delay in because I thought it was a reasonable thing to do.

If you have no delay, the timing of the loop is solely down to the time taken to do things. I would have thought that was a bad idea, hence the delay. I imagine the time of the loop would be determined by the time taken to send the data to SD, which is small but finite. I think you need to check the time to record the data you need, and base the loop on that. This may require a more sophisticated means of timing the loop - with millis.

@mojtaba256 Can you please help me explaining the respective boards and their pin connections? Thank you in advance.