Sampling maximum analogRead data to SD card

Hi guys,

Im using potentiometer with arduino uno. I want to sample the maximum possible analogread data rate from the arduino to the SD card. I know that this topic been mentioned quite a lot, but it is not clear for me why it is not working for me.

Kind regards

It is not clear to me either, but then I have not seen your code

Do you see what I am hinting at ?

#include <SPI.h>          // This is for SD card.
#include <SD.h>          // This is for SD card 
File mySensorData;

int analogInPin = A0;                     
int analogOutPin = 9;                       
volatile unsigned long starttime;

int sensorValue = 0;                          
int outputValue = 0;                        
int chipSelect=4;


void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
     // initialize serial communications at 9600 bps: 
pinMode(10,OUTPUT); // reserve pin 10 as output, don't use it
SD.begin(chipSelect);
}

void loop() {
  // put your main code here, to run repeatedly:
 // read the analog in value:
  sensorValue = analogRead(analogInPin);
  if (sensorValue != 1023){
    starttime = micros();
    if (sensorValue == 0)
    exit(0);
  }
  
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, 0, 255);
 
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);
  
  // print the results to the Serial Monitor:
  mySensorData= SD.open("PTData.txt",FILE_WRITE); 
  if (mySensorData) {
  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t");
  Serial.print("output = ");
  Serial.print(outputValue);
  Serial.print("\t");
  Serial.print("Timestart = ");
  Serial.println(starttime);
  mySensorData.print(sensorValue);
  mySensorData.print(",");
  mySensorData.print(outputValue);
  mySensorData.print(",");
  mySensorData.println(starttime);
  mySensorData.close(); // Close the file
  }
}

Thank you for posting the code but you have not described the problem that you are have with it

If you want to save data at the maximum possible rate then do not open and close the file for every reading you save and don't print data to the Serial monitor either

Thank you for replaying so fast.

I think you just answered my problem, i really appreciate it. Since Im new to arduino I spent 2 hours to write this code and testing it. My question is which part of the code should I remove.

Kind regards

The first thing you need to do is get rid of the SD.open() and SD.close() statements in the loop() function, as those slow down the data collection process drastically, and increase the read/write error rate.

Open the file once in setup() and close it when you are done collecting data.

Thank you for your replay, so if I move open the file to the setup(), where should I close it after collecting the data?

Kind regards

Hi,

@UKHeliBob meant the Serial.print lines. If you would like to use them later, then comment them for the test like this:

//Serial.print("sensor = ");
//Serial.print(sensorValue);
//Serial.print("\t");
//Serial.print("output = ");
//Serial.print(outputValue);
//Serial.print("\t");
//Serial.print("Timestart = ");
//Serial.println(starttime);

This is the file open command, put this in the end of the setup block (after SD.begin).

  mySensorData= SD.open("PTData.txt",FILE_WRITE); 

I don't know why exit(0) is used, but you can close the file there for example.
You stop data gathering by grounding the A0 pin?

So your loop can be something like this:

void loop() {
 // read the analog in value:
  sensorValue = analogRead(analogInPin);

  if (sensorValue != 1023){
    starttime = micros();
    if (sensorValue == 0) {
      mySensorData.close(); // Close the file
      exit(0);
    }
  }
  
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, 0, 255);
 
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);
  
  // print the results to the Serial Monitor:
  mySensorData= SD.open("PTData.txt",FILE_WRITE); 
  if (mySensorData) {
  //Serial.print("sensor = ");
  //Serial.print(sensorValue);
  //Serial.print("\t");
  //Serial.print("output = ");
  //Serial.print(outputValue);
  //Serial.print("\t");
  //Serial.print("Timestart = ");
  //Serial.println(starttime);
  mySensorData.print(sensorValue);
  mySensorData.print(",");
  mySensorData.print(outputValue);
  mySensorData.print(",");
  mySensorData.println(starttime);
  }
}

What rate are you aiming at? I'm pretty sure, that SD write would be faster this way (instead of separate mySensorData.print() calls):

char dataToPrint[32];
snprintf(dataToPrint, 32, "%u,%u,%lu\r\n", sensorValue, outputValue, starttime);
mySensorData.print(dataToPrint);

Anywhere you like. You need to implement some orderly way to stop data collection and close the file, like a button, a loop counter, or a timer.

Thank you very much guy's. So basically Im trying to sample the data from a potiometer. The potiometer starts from 1023 bits and ends by 0. When it hit 0 the code should stop and sampling the data to the SD card. That's why I used exit(0) So basiclly with this code I want to map out the Bits, voltages and the time for each one of them and sample the data in SD card when the potiometer hits 0.

What if the potentiometer never "hits 0"?

Good point. :slight_smile:

And also @fahooodi you could implement a less permanent solution. Flip a bool which disables data sampling for example. This could have the advantage of starting everything over without the need to reset the uC.

Never thought about that to be honest with you! :face_with_peeking_eye:

@amazed, I really appreciate your effort. But Im not that much of experienced with arduino. I just start learning it so if you can explain me more, I would really appreciate it :face_holding_back_tears:

The, why do you think you need to collect data "as fast as possible", and why does it need to be written to an SD card?

If you use a PC terminal program (Putty, Teraterm, etc.) instead of the serial monitor, anything that is printed can be logged to a file on the PC. Much more convenient!

As you wish. For example you could stop/start reading by sending a character through the Serial Monitor. Sample code:

bool readPot = true;
...
void loop()
{
  if (readPot)
  {
    //read analog pin and do other stuff here
  }

  if (Serial.available())
  {
    char rc = Serial.read();
    if (rc == 'r')
    {
      if (readPot)
      {
        //stop data gather and close the file;
        readPot = false;
        mySensorData.close();  // Close the file
      }
      else
      {
        //re-open the file and start data gather again
        readPot = true;
        SD.open("PTData.txt", FILE_WRITE);  // Re-open the file
      }
    }
  }
}
1 Like

Im trying to determine that changes of potiometer bits, voltage, time by using the analogread . So how more data I have how more accurate my analsis gonna be. But since Im new to coding/arduino and I don't have that much of experiance I tried to keep the code very simple because things can get very complicated and I will get lost. You have the ability to understand the code by just looking at it. But for me I have to read it line by line and check each variable before I can understand what is going on. :smiling_face_with_tear:

Hi @amazed, I have modified the code according to your advice but for some reason it is still not working! Can you maybe take a look at it and point to me what Im doing wrong.

Kind regards

Hi, it would be easier, if I could see it. :slight_smile:

#include <SPI.h>          // This is for SD card.
#include <SD.h>          // This is for SD card 
File mySensorData;

int analogInPin = A0;                        
int analogOutPin = 9;                       
volatile unsigned long starttime;

int sensorValue = 0;                           
int outputValue = 0;                         
int chipSelect=4;

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
     // initialize serial communications at 9600 bps: 
pinMode(10,OUTPUT); // reserve pin 10 as output, don't use it
SD.begin(chipSelect);
bool analogInPin = true;
}

void loop()
{
  if (analogInPin)
  {
    sensorValue = analogRead(analogInPin);
  if (sensorValue != 1023){
    starttime = micros();
    if (sensorValue == 0)
    exit(0);
  }

  if (Serial.available())
  {
    char rc = Serial.read();
    if (rc == 'r')
    {
      if (analogInPin)
      {
        //stop data gather and close the file;
        analogInPin = false;
        mySensorData.close();  // Close the file
      }
      else
      {
        //re-open the file and start data gather again
        analogInPin = true;
        SD.open("PTData.txt", FILE_WRITE);  // Re-open the file
      }
    }
  }
}
}