I'm developing a test system and storing the data on a SD card. Every time a new test is started a new data file is created. All works fine except getting the date stamp on the file name. I have done this before on a similar project. Actually someone a couple of years ago on this forum helped me to get that to work. As far as I can tell I have duplicated everything from the first sketch into this one but obviously there is something missing.
I use this statement "SdFile::dateTimeCallback(dateTime); // sets file date"
calling this function prior to opening the file:
void dateTime(uint16_t* date, uint16_t* time)
{
Serial.println("datetime");
SDyear = now.year();
SDmonth = now.month();
SDday = now.day();
SDhour = now.hour();
SDminute = now.minute();
SDsecond = now.second();
*date = FAT_DATE(SDyear, SDmonth, SDday);
*time = FAT_TIME(SDhour, SDminute, SDsecond);
} // end void datetime
I am using a Uno with a RTC and SD card reader.
Below is the complete sketch, (Sorry couldn't figure out how to post a sketch with the new forum)
******************************* Start of sketch *****************************
// EoFlow stepper motor control code
// Enter cycle values, number of steps, dwell time between steps, and number of increments on serial monitor
// Comands to control test also entered on serial monitor, s = start, p = pause, r = resume, e = end, or use pushbutton to start cycle
// Added a purge cycle, when the purge pushbutton is pressed the pump will go 1 revolution in 1 minute
// Added 2 pressure sensors, RTC and SD card for data logging
// Copyright Process Services 2020
#include <AccelStepper.h>
#include <SPI.h>
#include <SdFat.h> // SD card & FAT filesystem library
#include <Wire.h>
#include "RTClib.h"
// RTC variables
RTC_DS3231 realClock; // Establishes the chipset of the Real Time Clock
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// SD Variables
SdFat SD; // SD card filesystem
unsigned int SDyear = 2019;
byte SDmonth = 11;
byte SDday = 15;
byte SDhour = 6;
byte SDminute = 11;
byte SDsecond = 00;
char logFileName[20] = " "; // current log file name
File logfile; // the logging file
DateTime now ;
int errorNumb = 0; // system error number to display message
const int chipSelect = 10;
#define HALFSTEP 8
// Motor pin definitions
// Blue - 28BYJ48 pin 1
// Pink - 28BYJ48 pin 2
// Yellow - 28BYJ48 pin 3
// Orange - 28BYJ48 pin 4
// Red - 28BYJ48 pin 5 (VCC)
#define motorPin1 3 // IN1 on the ULN2003 driver 1
#define motorPin2 4 // IN2 on the ULN2003 driver 1
#define motorPin3 5 // IN3 on the ULN2003 driver 1
#define motorPin4 6 // IN4 on the ULN2003 driver 1
#define repeatPb 8 // Repeat cycle pushbutton
#define purgePb 9 // purge cycle pushbutton
int led = 13; // set led to pin 13
String dataIn; // string from operator
char d1; // character from string
String x; // String from operator
// Pressure Sensors
int InPrssPin = A0; // Inlet pressure to A0
int OutPrssPin = A1; // Outlet pressure to A1
int InPrssRaw = 0; // Inlet Pressure raw value
int OutPrssRaw = 0; // Outlet Pressure raw value
float InPrssScld = 0.0; // Inlet pressure scaled
float OutPrssScld = 0.0; // Outlet pressure scaled
float InPrssPeak = 0.0; // Inlet Pressure Peak
float OutPrssPeak = 0.0; // Outlet Pressure Peak
int InatPeak = 0;
// temporary array for use when parsing
const byte numChars = 64;
char receivedChars[numChars];
char tempChars[numChars];
char dataInChars[numChars];
boolean newData = false;
char startMarker = '<';
char endMarker = '>';
char comma = ',';
// variables for test cycle
int incr = 0; // number of poles per increment
int poles = 0; // total poles incremented
int dwell = 0; // dwell time between steps
int totSteps = 0; // total number of steps
int runCycle = 0; // run cycle enable
int stepCount = 0; // current step counts
int i = 0;
int purgeMode = 0; // purge mode run bit
int purgeSteps = 0;
float purgeDwell = 0.014; // Purge dwell time between steps
int purgeIncr = 0; // purge step counter
int totalPurgeSteps = 4096; // number of steps in purge cycle 1 revolution
// Purge variables
int purgeDist = 4096; // distance pump goes during Purge, 4096 = 1 revolution
int purgeSpd = 70; // speed of pump during purge, 75 = 1 minute for a revolution
// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
AccelStepper stepMotor(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4); // AccelStepper::FULL4WIRE
void setup() {
Serial.begin(9600);
// stepper.setSpeed(64); // 1 min//64 1rpm //128 2rpm //ENTER 4100 FOR 1 rev OF THE ROLLER
// Set some constraints on the stepper motor
stepMotor.setMaxSpeed(500.0);
stepMotor.setAcceleration(100.0);
// stepMotor.setSpeed(50);
pinMode(led, OUTPUT); // set led pin to an output
pinMode(repeatPb, INPUT_PULLUP); // input for repeat pushbutton
pinMode(purgePb, INPUT_PULLUP); // input for purge pushbutton
// Start realClock
Wire.begin(); // Starts the Wire library allows I2C communication to the Real Time Clock
realClock.begin(); // Starts communications to the RTC
// initialize the SD card
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
errorNumb = 1;
error("Card failed, or not present");
}
Serial.println("card initialized.");
Serial.println("Enter number of steps");
while (Serial.available() == 0) {} // wait for number of steps to be entered
poles = Serial.parseInt(); // set steps to entered value
incr = poles; // set for first step
Serial.read(); // clear serial buffer
Serial.println("Enter Dwell Time in milliseconds");
while (Serial.available() == 0) {} // wait for Dwell Time to be entered
dwell = Serial.parseInt(); // set steps to entered value
Serial.read(); // clear serial buffer
Serial.println("Enter Total Number of Increments");
while (Serial.available() == 0) {} // wait for Dwell Time to be entered
totSteps = Serial.parseInt(); // set total number of steps to entered value
Serial.read(); // clear serial buffer
} // end Setup
void loop() {
// Read Pressure Sensors
InPrssRaw = analogRead(InPrssPin);
//InPrssScld = (InPrssRaw * (15.00/1024.00));
OutPrssRaw = analogRead(OutPrssPin);
//OutPrssScld = (OutPrssRaw * (15.00/1024.00));
DateTime now = realClock.now(); // Fetches the time from RTC
/*
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
*/
// repeat cycle from pushbutton control
if (digitalRead(repeatPb) == LOW) {
stepMotor.setCurrentPosition(0);
runCycle = 1;
}
// end if(digitalRead(repeatPb)
// run purge cycle from pushbutton control
if (digitalRead(purgePb) == LOW) {
purgeMode = 1;
stepMotor.setCurrentPosition(0);
stepMotor.moveTo(purgeDist); // 4096 = 1 revolution
} // end if(digitalRead(purgePb)
// Run Purge Mode
if (purgeMode == 1) {
stepMotor.enableOutputs(); // turn on stepper motor
stepMotor.setSpeed(purgeSpd); // 70 = 1 minute for a revolution
stepMotor.runSpeed();
if (stepMotor.distanceToGo() <= 0) { //stop stepper when at entered distance
stepMotor.stop();
stepMotor.disableOutputs();
stepMotor.setCurrentPosition(0);
purgeMode = 0;
}
} // end if(purgeMode == 1)
if (Serial.available()) {
dataIn = Serial.readString();
d1 = dataIn.charAt(0);
switch (d1) { //cases based on 1st char of dataIn
case 's': // start cycle with low case s
stepMotor.setCurrentPosition(0);
runCycle = 1;
SdFile::dateTimeCallback(dateTime); // sets file date
// create a new data logging file
Serial.println("Create file");
char filename[] = "LogFile00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[7] = i / 10 + '0';
filename[8] = i % 10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
strcpy(logFileName, filename);
break; // leave the loop!
} // end if (! SD.exist)
} // end for (uint8_t i = 0; i < 100; i++)
// fetch the time
now = realClock.now();
logfile.print("Date ");
logfile.print(", ");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print("/");
logfile.print(now.year(), DEC);
logfile.print(" ");
logfile.print(", ");
logfile.print("Time ");
logfile.print(", ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
logfile.print(" ");
logfile.println();
logfile.println();
if (! logfile) { // checks that logfile created
errorNumb = 2;
error("couldnt create file");
} // end (! logfile)
break;
case 'S': // start cycle with upper case S
stepMotor.setCurrentPosition(0);
runCycle = 1;
break;
case 'e': // // end cycle with lower case e
runCycle = 0;
totSteps = 0;
break;
case 'E': // // end cycle with lower case E
runCycle = 0;
break;
case 'R': // // resume cycle with upper case R
runCycle = 1;
break;
totSteps = 0;
break;
case 'p': // // pause cycle with lower case p
runCycle = 0;
break;
case 'P': // // pause cycle with upper case P
runCycle = 0;
break;
case 'r': // //resume cycle with lower case r
runCycle = 1;
break;
case 'g': // //Read Steps Value
x = dataIn.substring(1);
poles = x.toInt();
break;
case 'd': // //Read Steps Value
x = dataIn.substring(1);
dwell = x.toInt();
break;
case 't': // //Read Steps Value
// x = dataIn.substring(1);
// totSteps = x.toInt();
recvWithStartEndMarkers(); // Read data from Visual Studio
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData(); // Split data into separate variables
newData = false;
} //end if (newData == true)
break;
} // end switch (d1)
} // end if(Serial.available)
if (runCycle == 1 && purgeMode == 0) {
stepMotor.enableOutputs(); // turn on stepper motor
stepMotor.run();
while (stepMotor.isRunning()) {
stepMotor.run();
// capture peak pressure values for each increment
if (InPrssScld > InPrssPeak) {
InPrssPeak = InPrssScld;
}
if (OutPrssScld > OutPrssPeak) {
OutPrssPeak = OutPrssScld;
}
} // end while (stepMotor.isRunning())
if (stepCount <= totSteps) {
stepMotor.moveTo(incr); // move stepper to new position
Serial.print("Increment = ");
Serial.print("\t");
Serial.print(stepCount);
Serial.print("\t");
Serial.print("Inlet Peak = ");
Serial.print("\t");
Serial.print(InPrssPeak);
Serial.print("\t ");
Serial.print("Outlet Peak = ");
Serial.print("\t");
Serial.println(OutPrssPeak);
// data to logfile
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
logfile.print(" ");
logfile.print(", ");
logfile.print(" ");
logfile.print(", ");
logfile.print("Increment = ");
logfile.print(", ");
logfile.print(stepCount);
logfile.print(", ");
logfile.print("Inlet Pressure = ");
logfile.print(", ");
logfile.print(InPrssScld);
logfile.print(", ");
logfile.print("Outlet Pressure = ");
logfile.print(", ");
logfile.print(OutPrssScld);
logfile.println();
digitalWrite(led, HIGH);
incr = incr + poles;
stepCount = stepCount + 1;
digitalWrite(led, LOW);
delay(dwell);
InPrssScld = 0;
OutPrssScld = 0;
InPrssPeak = 0.0;
InatPeak = 0;
} // end if(stepCount <= totSteps;)
if (stepCount > totSteps) {
runCycle = 0;
stepCount = 0;
incr = poles;
stepMotor.disableOutputs();
Serial.println("Stepper Motor OFF");
logfile.close(); // Close file
} // end if(i > totSteps)
} // end if(runCycle == 1)
} // end loop
void recvWithStartEndMarkers() { // reads variables from controller
static boolean recvInProgress = false;
static byte ndx = 0;
// char startMarker = '<';
// char endMarker = '>';
char rc;
// while (Serial1.available() > 0 && newData == false) {
// rc = Serial1.read();
dataIn.toCharArray(dataInChars, 64);
// rc = Serial.read();
if (recvInProgress == true) {
if (dataInChars != endMarker) {
receivedChars[ndx] = dataInChars;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (dataInChars == startMarker) {
recvInProgress = true;
}
// } // end while (Serial1.available()
} // end void recvWithStartEndMarkers()
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ","); // get the first part - the string
poles = atoi(strtokIndx); // step value
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
dwell = atoi(strtokIndx); // dwell time
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
totSteps = atoi(strtokIndx); // total number of steps
} // end void parseData()
void dateTime(uint16_t* date, uint16_t* time)
{
Serial.println("datetime");
SDyear = now.year();
SDmonth = now.month();
SDday = now.day();
SDhour = now.hour();
SDminute = now.minute();
SDsecond = now.second();
*date = FAT_DATE(SDyear, SDmonth, SDday);
*time = FAT_TIME(SDhour, SDminute, SDsecond);
} // end void datetime
void error(char *str)
{
Serial.print("error: ");
Serial.println(str);
Serial.println(errorNumb);
// red LED indicates error
// digitalWrite(redLEDpin, HIGH);
// display fault on screen
if (errorNumb == 1) {
Serial.println("Insert SD Card");
}
else if (errorNumb == 2) {
Serial.println("Failed to Create File");
Serial.println("Insert SD Card");
}
while (1);
} // end void error
****************************** end of sketch *****************************
Thanks for any help
John