Go Down

Topic: Help increasing Write speed to the SD card (Read 482 times) previous topic - next topic

GaryRH

Hi,

I'm new here and to Arduinos & coding, so please excuse my lack of knowledge as I'm still learning.

I have created a datalogger logging accelerator and temp & humidity data. I'm looking to log data at around 50Hz, which I can get no problem if I'm not writing to the SD card and just writing to the serial monitor. As soon as I ask it to write to the SD card I can only get around 25Hz.

I've put my code together using various tutorials and although it may not be the most efficient it works, except the write speed.

Can anyone suggest anything to help increase the write speed to 50Hz or beyond if possible??

Thank you

I'm using:-

Nano
Adafruit SD Module
Adafruit LIS3DH Accelerometer
DHT22 Temp & Humidity Sensor
DS2321 RTC


Here is the code I'm using, as I've said I haven't been doing this for long (about 1 month or so) so please excuse any glaring errors, inefficiencies and housekeeping.

I have removed all the print.serial to try and help speed things up but I don't think it's helped too much.

Thank you

Code: [Select]


#include <SD.h> //SD Card Module
#include <DS3231.h> //RTC
#include <Adafruit_LIS3DH.h> //Accelerometer
#include <dht.h> //Temp Sensor
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>


//Temp Sensor
#define dataPin 4 // Defines pin number to which the sensor is connected
dht DHT;

//SD Card Module
File sdcard_file;
int CS_pin = 10; // Pin 10 on Arduino Uno


//RTC
DS3231  rtc(SDA, SCL);


//Accelerometer Module
Adafruit_LIS3DH lis = Adafruit_LIS3DH();


//Millis() function
#define Accelerometer_Intival 20 //Accelerometer reading intival in milliseconds
#define Tempertaure_Intival 60000 //Temperature reading intival in milliseconds


unsigned long currentMillis;
unsigned long Acc_Time;
unsigned long Temp_Time;



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

  Acc_Time = millis(); //initial start time
  Temp_Time = millis(); //initial start time

  rtc.begin(); //Start RCT

  lis.begin(); //Start Accelerometer

  lis.setRange(LIS3DH_RANGE_4_G);   // 2, 4, 8 or 16 G!

 
  //Temp Sensor Setup
  int readData = DHT.read22(dataPin); // DHT22/AM2302

  float temp = DHT.temperature; // Gets the values of the temperature
  float humid = DHT.humidity; // Gets the values of the humidity

 
 
  // SD Card Initialization - called once on initial power up
  if (SD.begin())
   
  sdcard_file = SD.open("data1.txt", FILE_WRITE);
  if (sdcard_file) {
  sdcard_file.println("### NEW EVENT  ###"); //Denotes new event
  sdcard_file.close(); // close the file
  }
}

void loop() {

  currentMillis = millis();
  accel();
  temp();
}

void accel() //Read accelerometer and write to SD card
{
if(currentMillis > Acc_Time + Accelerometer_Intival)
{

//Accelerometer Read (normalised m/s^2)
  sensors_event_t event;
  lis.getEvent(&event);

//Write to SD Card
  sdcard_file = SD.open("data1.txt", FILE_WRITE);
  if (sdcard_file) {   
    sdcard_file.print(rtc.getDateStr());
    sdcard_file.print("\t");   
    sdcard_file.print(rtc.getTimeStr());
    sdcard_file.print("\t");
    sdcard_file.print(event.acceleration.x);
    sdcard_file.print("\t");
    sdcard_file.print(event.acceleration.y);
    sdcard_file.print("\t");
    sdcard_file.println(event.acceleration.z);
    sdcard_file.close(); // close the file

  Acc_Time = currentMillis;
   
  }
 }
}

void temp() //Read Teamp and Humidity and wirte to SD card
{
  if(currentMillis > Temp_Time + Tempertaure_Intival)
  {

//Temp Read
int readData = DHT.read22(dataPin); // DHT22/AM2302

  float temp = DHT.temperature; // Gets the values of the temperature
  float humid = DHT.humidity; // Gets the values of the humidity

//Write to SD Card

  sdcard_file = SD.open("data1.txt", FILE_WRITE);
  if (sdcard_file) {
  sdcard_file.print(rtc.getDateStr());
  sdcard_file.print("\t");
  sdcard_file.print(rtc.getTimeStr());
  sdcard_file.print("\t");
    sdcard_file.print("\t");
      sdcard_file.print("\t");
       sdcard_file.print("\t");
  sdcard_file.print((float)humid, 2);
  sdcard_file.print("\t");
  sdcard_file.println((float)temp, 2);
  sdcard_file.close(); // close the file
  }

 
Temp_Time = currentMillis;
 
}
}



The reason for the several tabs in the temp & humidity is so they're in separate columns in the csv when I copy the data from the SD card.

Thanks again

:)

ieee488

You are opening and closing the file every iteration of the loop.
BAD.


GaryRH

Thanks for your reply. I have removed the unnecessary file.close lines and things have improved slightly, maybe getting around 35Hz now. Still no where near the 50Hz I'm looking for though, but definitely an improvement.

GaryRH

By removing the close.file in all but the last instance it will not print to file. So I get a good speed on the serial but a blank SD.

wildbill

I'd use micros to see what's taking the time. How long does it take to read the clock, read the accelerometer, print to file.

Don't forget too, that the SD library is buffering - it only actually writes to the file every 512 bytes, so you may see a hiccup in your data rate at that time.

gilshultz

 Have you considered FRAM (Feroresemot Random Access Memory)  It's similar to Static random-access memory, only with a ferroelectric layer instead of a dielectric layer. This gives it stable handling (the bytes you write are non-volatile) with dynamic responsiveness (you can write them very fast!). Some of the advantages I see in FRAM are high speed reading and writing, non-volatile storage (it remembers its contents without needing power or battery backup), virtually unlimited read / write cycles - you can't wear it out unlike some other types of non-volatile memory. To get started  try this link: https://www.adafruit.com/product/1897  There board has a write enable input so you can lock it down and read it on another machine without worry about trashing the date or transfer it to a SD card when you are not time critical.
Good Luck & Have Fun!
Gil

GaryRH

#6
Nov 30, 2019, 10:47 am Last Edit: Nov 30, 2019, 01:20 pm by GaryRH
Have you considered FRAM (Feroresemot Random Access Memory)  It's similar to Static random-access memory, only with a ferroelectric layer instead of a dielectric layer. This gives it stable handling (the bytes you write are non-volatile) with dynamic responsiveness (you can write them very fast!). Some of the advantages I see in FRAM are high speed reading and writing, non-volatile storage (it remembers its contents without needing power or battery backup), virtually unlimited read / write cycles - you can't wear it out unlike some other types of non-volatile memory. To get started  try this link: https://www.adafruit.com/product/1897  There board has a write enable input so you can lock it down and read it on another machine without worry about trashing the date or transfer it to a SD card when you are not time critical.
Good Luck & Have Fun!
Gil
Thanks for the info, Gil. This seems like quite an interesting option. The problem I see with this is the small storage size, however if I could get it writing to an SD card periodically then that might be a good solution. Its perhaps a little outside of my ability and scope at the moment but I will definitely keep it in mind for further studies.


What I have done this morning was swapped the standard SD library for the SDFAT library and it has improved things and I now get the 50Hz. This makes me think I could push this further just for the sake of trying more than anything. The weird thing is I'm only getting the 50Hz by luck more than anything.

If I set the millis() for the accelerometer at 20ms then I get around 42Hz (instead of 50Hz) however if I set it at 10ms I get around 52Hz (instead of 100Hz). So while I am getting what I want.....its not because its behaving as I would like. It's due a mix of me not understanding what is going on and luck.


Go Up