I'm kind of new to Arduino & C++. I have developed a water well pump controller with 3 modes of control. Pressure Transducer, Pressure or Float Switch and Timer based on interval and time of day.
I'm using an Arduino Mega 2560 with a [HiLetgo DS3231 High Precision RTC Real Time Clock Module 3.3V/5V.
My problem comes as I'm trying to log how long the pump ran, along with the Time & Date. To do this, I'm trying to use an *Array to store a char array of the Time & Date. Even though it seems like the individual time data is stored in the Array, it loads the complete Array with the last reading. The attached code demonstrates the issue.
Thanks in advance for any help you can provide.
#include "Arduino.h"
#include "uRTCLib.h"
uRTCLib rtc(0x68);
int month = 0;
int day = 0;
int year = 0;
int rcHour = 0;
int rcMinute = 0;
int rcSecond = 0;
int rcSecond1 = 0;
int i = 0;
char timeDate[18] = "00:00:00 00/00/00";
char *logTimeDate[18];
void setup() {
Serial.begin(9600);
// RT Clock
URTCLIB_WIRE.begin();
// initialize logTimeDate array
i = 0;
while (i < 10) {
logTimeDate[i] = " ";
i += 1;
}
i = 0;
while (i < 10) {
// refreash rtclock
rtc.refresh();
rcSecond = rtc.second();
if (rcSecond != rcSecond1) {
rcSecond1 = rcSecond;
month = rtc.month();
day = rtc.day();
year = rtc.year();
rcHour = rtc.hour();
rcMinute = rtc.minute();
sprintf(timeDate, "%02d:%02d:%02d %02d/%02d/%02d", rcHour, rcMinute, rcSecond, month, day, year);
logTimeDate[i] = timeDate;
//delay(500);
// logging time & date every second
Serial.println(logTimeDate[i]);
i += 1;
}
}
Serial.println(" "); // skip a line
// why are all the elements filled with the last Time & Date?
Serial.println(logTimeDate[0]);
Serial.println(logTimeDate[1]);
Serial.println(logTimeDate[2]);
Serial.println(logTimeDate[3]);
Serial.println(logTimeDate[4]);
Serial.println(logTimeDate[5]);
Serial.println(logTimeDate[6]);
Serial.println(logTimeDate[7]);
Serial.println(logTimeDate[8]);
Serial.println(logTimeDate[9]);
}
void loop() {
}
/* Output from the Serial.println() above
12:07:54 04/14/24
12:07:55 04/14/24
12:07:56 04/14/24
12:07:57 04/14/24
12:07:58 04/14/24
12:07:59 04/14/24
12:08:00 04/14/24
12:08:01 04/14/24
12:08:02 04/14/24
12:08:03 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
12:08:04 04/14/24
*/
int month = 4;
int day = 14;
int year = 2024;
int rcHour = 5;
int rcMinute = 46;
const int N = 10;
char logTimeDate [N][20];
void setup ()
{
Serial.begin (9600);
for (int i = 0; i < N; i++)
sprintf (& logTimeDate [i][0], "%02d:%02d:%02d %02d/%02d/%02d",
rcHour, rcMinute, i , month, day, year);
for (int i = 0; i < N; i++)
Serial.println (logTimeDate[i]);
}
void loop () {
}
Of course it would be much easier to store the time as a unsigned long (the one you get from the RTC which represents the number of seconds since a given epoch) and only translate that into text when needed. No more messing around with strcpy() and 2D arrays, it’s a straight assignment then and you save lots of RAM which means more space for more records
That would certainly use up less memory but the design calls for storing the log on a SD card in a .cvs file. The user will be able to access the .cvs file via bluetooth directly into a spreadsheet for analysis. (android or pc).
I don't want to have to process the data after it's been logged.
if each string is written directly to the SD, can they be written as a continuous string of ASCII char (like any file ) with a \n terminating each string
The project is unfolding in phases. The current version only stores the last ten log entries for on demand display. The future state will include the SD card storage with Bluetooth interface.
The main reason for the SD card storage is because when the controller is used in a solar well pump application, the 12vdc powering the controller is off at night. No batteries are involved as I get the 12vdc from the 160vdc solar array via a dc to dc power supply.
Unfortunately, I'm having problems getting the SD card to work. That's for a different post if I can't figure it out!
Why don't you store the timestamps internally in epoch format, as @J-M-L suggested, and then convert them to ASCII on the fly (one at a time) only when needed? You would only need need to do the conversion either for on-demand display or when writing to the SD card. In those cases you only need to do one at a time rather than saving the entire list in ASCII.