Problem using an *Array of Char Arrays

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
*/

@rflamm
I'll add to what @Delta_G said - in C you can't assign arrays, so even when you fix the array type, this line still won't work.

You have to copy one array to another char by char.

need to allocate space for each string
an array of 20 char strings

output:

05:46:00 04/14/2024
05:46:01 04/14/2024
05:46:02 04/14/2024
05:46:03 04/14/2024
05:46:04 04/14/2024
05:46:05 04/14/2024
05:46:06 04/14/2024
05:46:07 04/14/2024
05:46:08 04/14/2024
05:46:09 04/14/2024
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 () {
}

I get it now! I just have to figure out the correct syntax. I replaced these lines in the posted code. Got rid of array timeDate altogether.

char logTimeDate[9][18];

  // initialize logTimeDate array
  i = 0;
  while (i < 10) {
    logTimeDate[i][18] = "                 ";
    i += 1;
  }

sprintf(logTimeDate[i], "%02d:%02d:%02d %02d/%02d/%02d", rcHour, rcMinute, rcSecond, month, day, year);

Serial.println(logTimeDate[i]);

It seems to work.
Thanks for your help!

Perfect!
Thanks gcjr

I don't think that it is correct. C language not allowed you to assign one array to another,

The correct syntax could be:

strcpy( logTimeDate[i], "                      ");

this isn't correct. it won't compile with warnings treated as errors.

logTimeDate [i][18] is a char and " " is a string. this command attempts to set the the value of the char to the address of " ".

there's also no need to initialize the array of strings. by default it is set to zero, an empty string, the first char is null

I wrote that before I saw you previous post. I'm now using the correct syntax and everything works well!

Thanks again.

Should be
logTimeDate[10][18];

Also: read about for loops...

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

2 Likes

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.

Thanks for the input!
RFlamm

When is the data logged to the SD card ? That’s when you would convert the number into text.

If you log directly, why do you need the 2D array at all?

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!

Thanks!
RFlamm

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.

Why not?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.