passing parameters to tm struct - aggregate incomplete type error

Hello all,

I have started to use Time.h and DS1307RTC.h libraries for time management.

According to this page it wanted to creat a tm struct to convert a costum time to epoch:
https://www.epochconverter.com/programming/c

I have this function with the tm struct (epochNow is: time_t epochNow=now()):

byte interval(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second, const unsigned int &duration)
{
  struct tm startTime;
  time_t t_of_day;

  startTime.tm_year = year(epochNow) - 1900;
  startTime.tm_mon = month(epochNow);
  startTime.tm__mday = day(epochNow);
  startTime.tm_hour = start_hour;
  startTime.tm_min = start_minute;
  startTime.tm_sec = start_second;
  startTime.tm_isdst = -1;
  t_of_day = mktime(&startTime);

  unsigned int time_on = now() - t_of_day;
  if ( time_on < (duration*60)) return 1; //within interval
  return 0; //not within interval
}

The parameters are all ints to define the time. Declared like this:

#define MORNING_START_HOUR 9
#define MORNING_START_MINUTE 54
#define MORNING_START_SECOND 0
#define MORNING_DURATION 1//minutes

Unfortunately this gives me the “aggregate has incomplete type and cannot be defined” error.

Are the parameters incompatible with the tm struct? How do I have to declare them in order for it to work? Or is there some other error?

Thank you for your help!

moses

Show us your full code the the line number where the error occurs.

Thank you boylesg

There is a lot of code not linked to timing and the function in question.

Here is all the code treating timing (Time.h, DS1307RTC.h):

#include <TimeLib.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
/*Function prototypes*/
bool getTime(const char);
bool getDate(const char);
time_t epochNow = 0;
tmElements_t tm;

#define SUNRISE_START_HOUR 8
#define SUNRISE_START_MINUTE 53
#define SUNRISE_START_SECOND 0
#define MORNING_START_HOUR 8
#define MORNING_START_MINUTE 54
#define MORNING_START_SECOND 0
#define MORNING_DURATION 1//minutes
#define NOON_START_HOUR 8
#define NOON_START_MINUTE 55
#define NOON_START_SECOND 0
#define NOON_DURATION 1//minutes
#define AFTERNOON_START_HOUR 8
#define AFTERNOON_START_MINUTE 56
#define AFTERNOON_START_SECOND 0
#define AFTERNOON_DURATION 1//minutes
#define NIGHT_START_HOUR 8
#define NIGHT_START_MINUTE 57
#define NIGHT_START_SECOND 0
#define NIGHT_DURATION 1//minutes

void setup()
{
Serial.begin(9600); // for debugging
bool parse=false;
bool config=false;
/*get the date and time the compiler was run*/
if (getDate(__DATE__) && getTime(__TIME__)) {
parse = true;
}
/*and configure the RTC with this info*/
if (RTC.write(tm)) {
    config = true;
    Serial.println("RTC ok");
}   else if (RTC.chipPresent()) {
            Serial.println("The DS1307 is stopped");
            Serial.println("Setting the RTC...");
            getDate(__DATE__) && getTime(__TIME__);
            if (getDate(__DATE__) && getTime(__TIME__))
            {
                Serial.println("RTC set");
            }
            Serial.println();
    } else {
            Serial.println("DS1307 read error!  Please check the circuitry.");
            Serial.println();
      }

setSyncProvider(RTC.get);   // the function to get the time from the RTC
if(timeStatus()!= timeSet) 
    Serial.println("Unable to sync with the RTC");
else
     Serial.println("RTC has set the system time");      
}

void loop()
{

/*---Get Time from RTC---*/
epochNow = now();
/*Now minutes*/
nowMinutes = hour(epochNow)*60 + minute(epochNow); // from an older version of the code
}

bool getTime(const char *str)
{
  int Hour, Min, Sec;

  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec;
  return true;
}

bool getDate(const char *str)
{
  char Month[12];
  int Day, Year;
  uint8_t monthIndex;

  if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
  for (monthIndex = 0; monthIndex < 12; monthIndex++) {
    if (strcmp(Month, monthName[monthIndex]) == 0) break;
  }
  if (monthIndex >= 12) return false;
  tm.Day = Day;
  tm.Month = monthIndex + 1;
  tm.Year = CalendarYrToTm(Year);
  return true;
}

The first function is calling the two others:

/*Function calling*/
        if ( (secondsToStart(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND) < elapsedSecsToday(now()))
                && interval(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND, MORNING_DURATION)
                  && grLEDControl[idxLED].state == SUNUPLOW_AM )

/*Functions called*/
time_t secondsToStart(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second)  //, const unsigned int &now) {
{
    time_t start = start_hour*3600 + start_minute*60 + start_second;
    return start;
}

byte interval(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second, const unsigned int &duration)
{
  struct tm startTime;
  time_t t_of_day;

  startTime.tm_year = year(epochNow) - 1900;
  startTime.tm_mon = month(epochNow);
  startTime.tm__mday = day(epochNow);
  startTime.tm_hour = start_hour;
  startTime.tm_min = start_minute;
  startTime.tm_sec = start_second;
  startTime.tm_isdst = -1;
  t_of_day = mktime(&startTime);

  unsigned int time_on = now() - t_of_day;
  if ( time_on < (duration*60)) return 1; //within interval
  return 0; //not within interval
}

Hope this is all the code relevevant. The first sniplet is in a tap preceding the code called. The calling code is in a tap following the code called.

Thank you very much.

moses

Please post the complete error message.

Hello gfvalvo

This is what it says:

Arduino: 1.8.9 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

R:\Arduino\Terrarium\1_TerrariumSteuerung_PuttingItTogether_RTC_Time_h\b_Functions.ino: In function 'byte interval(const unsigned int&, const unsigned int&, const unsigned int&, const unsigned int&)':

b_Functions:23:13: error: aggregate 'interval(const unsigned int&, const unsigned int&, const unsigned int&, const unsigned int&)::tm startTime' has incomplete type and cannot be defined

   struct tm startTime;

             ^

b_Functions:33:31: error: 'mktime' was not declared in this scope

   t_of_day = mktime(&startTime);

                               ^

exit status 1
aggregate 'interval(const unsigned int&, const unsigned int&, const unsigned int&, const unsigned int&)::tm startTime' has incomplete type and cannot be defined

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

BTW - how come "mktime was not declared in this scope. If I include the Time.h library...?

Thank you!

moses

Where is ‘struct tm’ defined?

Hello gfvalvo,

I put this as global variable:
tmElements_t tm;

Is my second struct definition wrong?
struct tm startTime;

Would I have to put?
tmElements_t startTime;

Cheers,

moses

After having had another look at Timelib.h. I now changed my code to the following:

  tmElements_t startTime;
  time_t t_of_day;

  startTime.Year = year(epochNow);
  startTime.Month = month(epochNow);
  startTime.Day = day(epochNow);
  startTime.Hour = start_hour;
  startTime.Minute = start_minute;
  startTime.Second = start_second;
//  startTime.Isdst = -1;
  t_of_day = makeTime(&startTime);

The compiler isn't happy about the last line. The coding must be wrong. Here the error message:

Arduino: 1.8.9 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

R:\Arduino\Terrarium\1_TerrariumSteuerung_PuttingItTogether_RTC_Time_h\b_Functions.ino: In function 'byte interval(const unsigned int&, const unsigned int&, const unsigned int&, const unsigned int&)':

b_Functions:33:33: error: invalid initialization of reference of type 'const tmElements_t&' from expression of type 'tmElements_t*'

   t_of_day = makeTime(&startTime);

                                 ^

In file included from R:\Arduino\Terrarium\1_TerrariumSteuerung_PuttingItTogether_RTC_Time_h\1_TerrariumSteuerung_PuttingItTogether_RTC_Time_h.ino:16:0:

R:\Arduino\IDE\libraries\Time-master/TimeLib.h:139:8: note: in passing argument 1 of 'time_t makeTime(const tmElements_t&)'

 time_t makeTime(const tmElements_t &tm);  // convert time elements into time_t

        ^

exit status 1
invalid initialization of reference of type 'const tmElements_t&' from expression of type 'tmElements_t*'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Thank you.

t_of_day = makeTime(&startTime);

Try

t_of_day = makeTime(startTime);

In my version of TimeLib.h, the 'makeTime()' function takes a reference to a tmElements_t object, not a pointer.

time_t makeTime(tmElements_t &tm);

Use:

t_of_day = makeTime(startTime);

Thank you all!

gfvalvo:
In my version of TimeLib.h, the ‘makeTime()’ function takes a reference to a tmElements_t object, not a pointer.

time_t makeTime(tmElements_t &tm);

Use:

t_of_day = makeTime(startTime);

@gfvalvo: I thought the & in (tmElements_t &tm) means to use a pointer

The syntax of the code should be ok now. The compiler accepts it. But for some reason the timing doesnt work anymore. Before it would at least start the processes, but they would run eternally because the interval code didn’t work yet. But now the processes dont start anymore.

Does anyone have an idea why?

Here are the relevant codes again:

Code calling function for single start event:

if ( grLEDControl[idxLED].valPWM == grLEDControl[idxLED].minPWM
    && (secondsToStart(SUNRISE_START_HOUR, SUNRISE_START_MINUTE, SUNRISE_START_SECOND) == elapsedSecsToday(now())))

The first part just means that all the lights are out. My serial monitor shows “0” for all three lights so the first condition is fullfilled.

Code calling function for event with a specific duration:

        if ( (secondsToStart(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND) < elapsedSecsToday(now()))
                && interval(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND, MORNING_DURATION)
                  && grLEDControl[idxLED].state == SUNUPLOW_AM )

I use this code to debug, but not event this part reacts, which it did before:

if ( (secondsToStart(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND) < elapsedSecsToday(now())) && interval(MORNING_START_HOUR, MORNING_START_MINUTE, MORNING_START_SECOND, MORNING_DURATION) )
  Serial.println("ItsMorning");

if ( (secondsToStart(NOON_START_HOUR, NOON_START_MINUTE, NOON_START_SECOND) < elapsedSecsToday(now())) && interval(NOON_START_HOUR, NOON_START_MINUTE, NOON_START_SECOND, NOON_DURATION) )
  Serial.println("ItsNoon");

if ( (secondsToStart(AFTERNOON_START_HOUR, AFTERNOON_START_MINUTE, AFTERNOON_START_SECOND) < elapsedSecsToday(now())) && interval(AFTERNOON_START_HOUR, AFTERNOON_START_MINUTE, AFTERNOON_START_SECOND, AFTERNOON_DURATION) )
  Serial.println("ItsAfternoon");

if ( (secondsToStart(NIGHT_START_HOUR, NIGHT_START_MINUTE, NIGHT_START_SECOND) < elapsedSecsToday(now())) && interval(NIGHT_START_HOUR, NIGHT_START_MINUTE, NIGHT_START_SECOND, NIGHT_DURATION) )
  Serial.println("ItsNight");

Here are the functions called again:

time_t secondsToStart(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second)
{
    time_t start = start_hour*3600 + start_minute*60 + start_second;
    return start;
}

byte interval(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second, const unsigned int &duration)
{
  tmElements_t startTime;
  time_t t_of_day;

  startTime.Year = year(epochNow);
  startTime.Month = month(epochNow);
  startTime.Day = day(epochNow);
  startTime.Hour = start_hour;
  startTime.Minute = start_minute;
  startTime.Second = start_second;
//  startTime.Isdst = -1;
  t_of_day = makeTime(startTime);

  unsigned int time_on = now() - t_of_day;
  if ( time_on < (duration*60)) return 1; //within interval
  return 0; //not within interval
}

This is the declaration of the global variables:

time_t epochNow = 0;
tmElements_t tm;

There seems to be a conflict somewhere, but I dont understand where it might lie.

Thank you.

moses

Can you please provide an MCVE (minimal complete verifiable example) which demonstrates your problem.

Since I can't find function interval in your code what I would do is the following.

Comment all your include files and all your code except for the stubs of loop() and setup().

Re-instate all your code one line at a time until the compile error occurs.

Then you will have a better idea of what is causing it.

It could be a problem in one of the libraries you have included and you need to find another library.

Thank you cattledog and boylesg

@cattledog: I tried to write a MCVE but it has the opposite problem (instead of not turning the time depending processes on at all they are now on all the time).

@boylesg: there aren't any compile errors anymore at the moment. But with the new interval function the code works not as good a before anymore. The time depending processes dont turn on any more.

I will run some tests and come back with more information hopefully.

Thank you

Roger

Hello all

I found the error, but I dont understand why it occurs.

Here is my code

/*Variables*/
#define SUNRISE_START_HOUR 18
#define SUNRISE_START_MINUTE 00
#define SUNRISE_START_SECOND 0

/*Calling the function*/
secondsToStart(SUNRISE_START_HOUR, SUNRISE_START_MINUTE, SUNRISE_START_SECOND) == elapsedSecsToday(now())

/*Calculating epoch*/
time_t secondsToStart(const unsigned int &start_hour, const unsigned int &start_minute, const unsigned int &start_second)
{
    time_t start = start_hour*3600 + start_minute*60 + start_second;
    return start;
}

If I use unsigned int as data type for the variable SUNRISE_START_HOUR the calculation is correct until SUNRISE_START_HOUR reaces 18 (183600 = 64800) if I go to 19 (193600 the result turns out to be 2864)

If I change unsigned int to unsigned long the result is calculated correctly. The rest of the variables dont have to be changed. And the result is time_t.

Even though:
unsigned int 4bytes 0 to 4294967295

Could anyone tell me what is happening? Thank you!

moses

An int on some arduinos is only 16bits

Hello again

One more piece of code I tested which gives me a bad result which I dont understand:

  tmElements_t startTime;
  time_t t_of_day;

  startTime.Year = year(now());
  startTime.Month = month(now());
  startTime.Day = day(now());
  startTime.Hour = hour(now());
  startTime.Minute = minute(now());
  startTime.Second = second(now());
  t_of_day = makeTime(startTime);

Serial.print("t_of_day: ");
Serial.println(t_of_day);
Serial.print("epoch: ");
Serial.println(now());

All the individual compontents of startTime give me the correct result. t_of_day how ever is almost twice as high as epoch.

Once again the question: what is happening?

Thank you!

moses

ps: I think I got it. I might just have to substract 1970 from the current year. I will try it later on.

arduino_new:
An int on some arduinos is only 16bits

Thank you.

Does this apply to the nano? How to know about this fact (datasheet?)? And how come the size of ints may be different?

https://www.arduino.cc/en/Reference.Int