Adding millis() to a data string for loop

I'm working on a data logging project and using the Datalogger example as a starting point. I want to use the millis() function to record the time every sample is taken as the first entry in the data string. But i'm not exactly sure how to do this with the for loop that's already in place. Is there an easy way to do this or do I need to get rid of the for loop and write each entry to the data string separately? The code is below, thanks.

void loop() {
// make a string for assembling the data to log:
String dataString = "";

// read three sensors and append to the string:
for (int analogPin = 0; analogPin < 3; analogPin++) {
int sensor = analogRead(analogPin);
dataString += String(sensor);
if (analogPin < 2) {
dataString += ",";
}
}

What does a line in the log look like now and what do you want it to look like?

Right now it just prints the values of the three analog pins like 1023,1023,1023 for example. I'd like to add the time as the first entry using millis(), so the first line of data would look like 0,1023,1023,1023. Then one second later it would be 1,1023,1023,1023.

jbarber19:
Right now it just prints the values of the three analog pins like 1023,1023,1023 for example. I'd like to add the time as the first entry using millis(), so the first line of data would look like 0,1023,1023,1023. Then one second later it would be 1,1023,1023,1023.

So you want to add a number and a comma before the other data.

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

  dataString += String(millis());
  dataString += ',';

  // read three sensors and append to the string:

Yes, but 'String(millis()/1000))'...

millis() will overflow (go back to zero), after approximately 50 days.
I suggest to do as follow:

[size=0.8em]Code: [url=https://arduinogetstarted.com/tools/arduino-code-highlighter]see how to post code[/url] [/size]

---



```
[size=0.8em]unsigned long time_sec = 0;
unsigned long last_time_ms;
String dataString;

void [color=#5E6D03]setup/color {
  Serial.[color=#D35400]begin/color;
  last_time_ms = [color=#D35400]millis/color;
  dataString.reserve(20);
}
void [color=#5E6D03]loop/color {

if(([color=#D35400]millis/color - last_time_ms)> 1000)
  {
    time_sec++;
    last_time_ms = [color=#D35400]millis/color;
  }

Serial.[color=#D35400]println/color; //prints time in second since program started
  dataString = "";

dataString += [color=#00979C]String/color;
  dataString += ',';

// read three sensors and append to the string:
}[/size]
```

|

Thanks! Worked like a charm. The data logger will only run for 30 minutes max so I don't have to worry about millis() resetting. Now i'm trying to get the data logger to open a new file every time it's powered on. I found a bit of code from a forum post that i'm trying to implement in my code. After the for loop that increments the file name, I don't think i'm calling the file to open correctly. Before it was just SD.open('datalogger.txt', FILE_WRITE), with this new code I changed it to SD.open(fileName, FILE_WRITE). Like this it opens 99 files named (LOG00.01T - LOG00.99T) and there's one LOG00.TXT file with only one line of data in it. I'm not sure if i'm supposed to use the variable fileName when calling for the file to open.

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

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

const int chipSelect = 10;

void setup() {
  // Open serial communications and wait for port to open:
  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:
    while (1);
  }
  Serial.println("card initialized.");
}

void loop() {
  // make a string for assembling the data to log:
  String dataString = "";
  
  dataString += String(millis());
  dataString += ',';

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

 char fileName[] = "LOG00.TXT";  // Base filename for logging.

  // Construct the filename to be the next incrementally indexed filename in the set [00-99].
  for (byte i = 1; i <= 99; i++)
  {
    // check before modifying target filename.
    if (SD.exists(fileName))
    {
      // the filename exists so increment the 2 digit filename index.
      fileName[6] = i/10 + '0';
      fileName[7] = i%10 + '0';
    } else {
      break;  // the filename doesn't exist so break out of the for loop.
    }
  }

 
  // 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(fileName, 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");
  }
}
      fileName[6] = i/10 + '0';
      fileName[7] = i%10 + '0';

You want to replace characters 3 and 4, not 6 and 7.

That fixed part of it, I changed the name of the base file and then forgot to change the characters that were incremented. But it's still opening a file named LOG00.TXT, writing one line of data to it (442,406,372,1023), then the error message 'error opening LOG00.TXT' prints repeatedly on the serial monitor. If you turn the data logger off then back on it doesn't open a new file, it just prints the same error message on the serial monitor.

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

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

const int chipSelect = 10;

void setup() {
  // Open serial communications and wait for port to open:
  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:
    while (1);
  }
  Serial.println("card initialized.");
}

void loop() {
  // make a string for assembling the data to log:
  String dataString = "";
  
  dataString += String(millis());
  dataString += ',';

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

 char fileName[] = "LOG00.TXT";  // Base filename for logging.

  // Construct the filename to be the next incrementally indexed filename in the set [00-99].
  for (byte i = 1; i <= 99; i++)
  {
    // check before modifying target filename.
    if (SD.exists(fileName))
    {
      // the filename exists so increment the 2 digit filename index.
      fileName[4] = i/10 + '0';
      fileName[5] = i%10 + '0';
    } else {
      break;  // the filename doesn't exist so break out of the for loop.
    }
  }

 
  // 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(fileName, 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 LOG00.txt");
  }
}
      // the filename exists so increment the 2 digit filename index.
      fileName[4] = i / 10 + '0';
      fileName[5] = i % 10 + '0';

What part of "You want to replace characters 3 and 4" did you not understand?

You will get a more useful message if you replace:

    Serial.println("error opening LOG00.txt");

with:

    Serial.print("error opening ");
    Serial.println(filename);

My apologies, I guess i'm not familiar with how the characters are counted. The more I mess with this arduino stuff the dumber I feel lol. I changed it to 3 and 4 and now it's opening a new file for every new line of data, which i'm guessing is due to the file naming convention being placed inside of the loop. I moved the naming convention into the setup and tried to upload it but the sketch never runs.

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

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

const int chipSelect = 10;

char fileName[] = "LOG00.TXT";  // Base filename for logging.

void setup() {
  // Open serial communications and wait for port to open:
  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:
    while (1);
  }
  Serial.println("card initialized.");

  // Construct the filename to be the next incrementally indexed filename in the set [00-99].
  for (byte i = 1; i <= 99; i++)
  {
    // check before modifying target filename.
    if (SD.exists(fileName))
    {
      // the filename exists so increment the 2 digit filename index.
      fileName[3] = i/10 + '0';
      fileName[4] = i%10 + '0';
    } else {
      break;  // the filename doesn't exist so break out of the for loop.
    }
  }
 
}


void loop() {
  // make a string for assembling the data to log:
  String dataString = "";
  
  dataString += String(millis());
  dataString += ',';

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

 
  // 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(fileName, 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.print("error opening ");
    Serial.println(fileName);
  }
}

Made a little more progress, I changed the structure of the sketch a little bit to align with the format of an Adafruit data logging example. I moved the file naming convention outside of the loop to stop it opening new files, but in the loop section now it doesn't recognize the 'fileName' variable when I try to open the file in the loop giving me a 'fileName not declared in this scope error'. I'm not sure how to fix that unless I can move the file naming convention outside of setup to make it a global variable? In the Adafruit example they never open the file in the loop, they just print straight to it from what I can tell. If I try to do that it logs one line of data then gives an error opening file.

Adafruit example: Code Walkthrough | Adafruit Data Logger Shield | Adafruit Learning System

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

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

const int chipSelect = 10;

File dataFile; // the logging file

void setup() {
  // Open serial communications and wait for port to open:
  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:
    while (1);
  }
  Serial.println("card initialized.");

   // create a new file
  char fileName[] = "LOG00.TXT";
  for (uint8_t i = 0; i < 100; i++) {
    fileName[3] = i/10 + '0';
    fileName[4] = i%10 + '0';
    if (! SD.exists(fileName)) {
      // only open a new file if it doesn't exist
      dataFile = SD.open(fileName, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  Serial.print("Logging to: ");
  Serial.println(fileName);
 
}


void loop() {
  // make a string for assembling the data to log:
  String dataString = "";
  
  dataString += String(millis());
  dataString += ',';

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

 
  // 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(fileName, 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.print("error opening ");
    Serial.println(fileName);
  }
}

jbarber19:
I moved the file naming convention outside of the loop to stop it opening new files, but in the loop section now it doesn't recognize the 'fileName' variable when I try to open the file in the loop giving me a 'fileName not declared in this scope error'. I'm not sure how to fix that unless I can move the file naming convention outside of setup to make it a global variable?

Exactly! To have a variable that is shared by setup() and loop(), make it global.
When you create your own functions, another option is to pass values as arguments and return a value from a function. You can't do that with setup() and loop() because they are called from code that is not under your control so you can't just add arguments or return values.