Time Library - repeatedly creation with values from EEPROM

Hello,

I’m developing a night light led based on an Arduino Pro Mini (328), RTC (DS 3132).

The clock synchronization and alarm settings are defined (if necessary to change the defaults) by Processing. This part is less or more working. The biggest headache for my basic programming skills is to trigger the multiple alarms present in the EEPROM.

#include <Time.h>  // PJRC Time Library
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
#include <EEPROM.h>
#include <TimeAlarms.h>  // PJRC Alarm Library

//
String TIME_HEADER = "T"; // Serial Header Tag for Time synch.
String LED_REQUEST = "L"; // Serial Header Tag for LED Test
String STATUS_REQUEST = "S"; // Serial Header Tag for Settings
#define TIME_REQUEST  7 // Asking Proces. Time
#define LED_PIN  13 // Pin Out Nigh Light LED
int howmany = 1; // for the numbers of Alarm Settings - to be replace by count index from EEPROM
boolean writeEEPROM = true; // write protection EEPROM when false
 
void setup()  {
 
  pinMode(LED_PIN, OUTPUT); // Night Light LED
  Serial.begin(9600);
  while (!Serial) ; // Needed for Leonardo only
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet) // define RTC Situation
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");   
  EEPROMalarm(); //read out existing values on startup 
   
}

void loop()
{
  if(Serial.available()>0){ // Serial Control Tag 
   byte ser =  Serial.read();
  switch (ser){
     case 'T': // Go for Time Syncro.
       processSyncMessage();
       break;
     case 'L': // Test the LED
       turnLed();
       break;
     case 'S': // Publish the settings
       readstatus();  
       break;
     case 'W': // Write alarms to EEPROM
       EEPROMWrite();  
       break;      
    }
  }
  EEPROMalarm(); // continue to read out to be sure to don't miss one
  digitalClockDisplay();  
  Alarm.delay(1000);
  
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*  code to process time sync messages from the serial port   */
// Header tag for serial time sync message

void processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 
     Serial.println("Start to sync");
     pctime = Serial.parseInt();
     //return pctime;
     if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
       pctime = 0L; // return 0 to indicate that the time is not valid
     Serial.println("Parsing Time..."); // Debug Text
  }
   time_t t = pctime;
    if (t != 0) {
      RTC.set(t);   // set the RTC and the system time to the received value
      setTime(t);   
      Serial.print("Time was setted now!");  // Confirmation
  //return pctime;
  }
}

void turnLed(){ // Hardware Test Function LED
      digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toogle Pin
      delay(500);
      Serial.println("LED toggled");
}

void readstatus(){ // Print Alarm Times and LED  on Serial
     Serial.print('/n');
     Serial.print("LED"+digitalRead(LED_PIN)); // LED Read Out
     Serial.print('/n');
    EEPROMRead(); // Alarm Read Out
  //Serial.print(digitalClockDisplay()); // // RTC Clock Read Out
}

/* EEPROM */
typedef struct                    /**** EEPROM STORAGE STRUCTURE ****/
{
    //stuff in here gets stored to the EEPROM
    unsigned short count;         /* A count of values stored */
    long           sum;           /* A running total of values */
    //char           str[10];       /* A string label */
    int            ahour[20];   /* Array of values collected */
    int            aminute[20];
    int            aseconds[20];
    boolean        aPWM[20];
    boolean        complete;      /* a flag for whether gathering is finished */
} EEPROMSTORAGE;

// a class to manage the struct
class Permanent {
    private:
        // the actual eeprom gets stored here
        // the struct is overlayed onto this storage
        byte buffer[ sizeof(EEPROMSTORAGE) ];

    public:
        Permanent();   //constructor - reads the eeprom
        void write();  //a function to write to the eeprom
        
        //this pointer makes the buffer's contents easily accessed
        EEPROMSTORAGE * store;
};

//read the eeprom into the buffer
Permanent::Permanent() {
    for( int i = 0; i < sizeof(EEPROMSTORAGE); ++i ) {
        buffer[i] = EEPROM.read(i);
    }
    //overlay the pointer to the storage onto the buffer
    store = (EEPROMSTORAGE *) buffer;
}

//write the buffer into the eeprom
//be careful writting too often to the eeprom. It only has 100,000 writes
void Permanent::write() {
    for( int i = 0; i < sizeof(EEPROMSTORAGE); ++i ) {
        EEPROM.write(i, buffer[i]);
    }
}

//make an instance of the managing class called eeprom (in lower case!)
Permanent eeprom;

//Function to write the EEPROM
void EEPROMWrite(){     
     if (writeEEPROM){
         eeprom.store->count = 0;
         for(int i = 0; i < howmany; ++i ) {
         eeprom.store->ahour[i] = 1;//random(24);
         eeprom.store->aminute[i] = 12; //random(60);
         eeprom.store->aseconds[i] = 05;//random(60);
         eeprom.store->aPWM[i] = random(255);
         eeprom.store->count++;
     }
     eeprom.store->complete = true;
     //write the buffered data to the eeprom
     eeprom.write();
     EEPROMalarm(); //read out updated values
     }else
     { 
     //return false;
     }
}   

// Function to read the EEPROM
void EEPROMRead(){     
    for(int b = 0; b < eeprom.store->count; ++b)
     {
    Serial.print("HH : ");
    Serial.print(eeprom.store->ahour[b]);   /* Array of values collected */
    Serial.print("\t");
    Serial.print("MIN : ");
    Serial.print(eeprom.store->aminute[b]);
    Serial.print("\t");
    Serial.print("SEC : ");
    Serial.print(eeprom.store->aseconds[b]);
    Serial.print("\t");
    Serial.print("PWM : ");
    Serial.print(eeprom.store->aPWM[b]);
    Serial.print('\n');
    //Serial.println( eeprom.store->str );
    //Serial.println( eeprom.store->values[b]);
   }
    Serial.print( eeprom.store->count);
    Serial.print("="+howmany);
    Serial.print('\n');
    Serial.print("All elements are printed");
}

void EEPROMalarm(){
    for(int b = 0; b < eeprom.store->count; ++b){
      int hours = eeprom.store->ahour[b];
      int minutes = eeprom.store->aminute[b];
      int seconds = eeprom.store->aseconds[b];
      // boolean pwm = (eeprom.store->aPWM[b]); // 
      Alarm.alarmRepeat(hours,minutes,seconds,lightController);
      Serial.println("EEProm Read");
      Serial.println(hours + minutes + seconds); // Debugging (output 18 (eq. 12+1+5))
    }
}

void lightController(){
    int brightness = 233;    // brightness = aPWM ???
    Serial.println("Light Control triggered");
    analogWrite(LED_PIN, brightness);    
}

On Line 222-223 : How to pass the Parameter PWM to LightController (in order to avoid to create about 255 functions? or allow to change PIN, …)? Is this called callback or overloading? I tried to get a more clear idea about, but I didn’t succeed.
If I try to pass them, I get invalid use of void expression.

For the rest, there is any reaction (no execution of lightController) when the alarm should be triggered.

So, I started to understand the mechanism with the TimeAlarmExample.

 for(int i = 0; i < 30; ++i){  
    Alarm.alarmRepeat(8,30,i, MorningAlarm);  // 8:30:00- 8:30:30 every second
  }

void MorningAlarm(){
    
int brightness = 233;    // how bright the LED is
  Serial.println("Morn. Alarm Triggered");
  analogWrite(LED_PIN, brightness);    

  Serial.println("Alarm: - turn lights on");    
}

Regardless if I put this code, in void Setup or Loop, it’s only showing up about 3-4 times in Serial.

Thank you for your advice and help

String TIME_HEADER = "T"; // Serial Header Tag for Time synch.
String LED_REQUEST = "L"; // Serial Header Tag for LED Test
String STATUS_REQUEST = "S"; // Serial Header Tag for Settings

Which Arduino do you have that you can afford to uselessly piss away resources like this?

  EEPROMalarm(); //read out existing values on startup

Why doesn’t the function name suggest that, then? A meaningful name wouldn’t need a comment. You might as well call the function gasdgkm89().

  EEPROMalarm(); // continue to read out to be sure to don't miss one

You read them all, already. This doesn’t make sense.

     case 'W': // Write alarms to EEPROM
       EEPROMWrite();

This function should NOT hide information from the data structure, whatever it is, that the poorly named function writes to.

// a class to manage the struct
class Permanent {
    private:

The definition of the class has no place in an ino file.

//read the eeprom into the buffer
Permanent::Permanent() {
    for( int i = 0; i < sizeof(EEPROMSTORAGE); ++i ) {
        buffer[i] = EEPROM.read(i);
    }
    //overlay the pointer to the storage onto the buffer
    store = (EEPROMSTORAGE *) buffer;
}

Nor does the implementation.

    for(int b = 0; b < eeprom.store->count; ++b){

Where is the eeprom instance defined?

For sure, there are misstakes or bad programming practice in my code, well all the things you comment are working and I have any problems to understand my different names. In any case, I thought a forum was there to help to find answer and not to make new questions on things which are working and ignore the main issue (loop creation of alarm).

In any case, I thought a forum was there to help to find answer and not to make new questions on things which are working and ignore the main issue (loop creation of alarm).

If you go to the doctor complaining of a headache, and XRays show that you have a brain tumor, do you expect that doctor to say "take 2 aspirin and call me next week"? You have fundamental flaws in your code that should be addressed before we can get to your specific problem. If you don't want to fix them, that's your decision. Hope the aspirin helps.

Greetings All :slight_smile:

Ok first off @ PaulS and @bperrybap

What are you saying about the 1024 kilobytes thing ?
At no stage have I mentioned (in my earlier calculations) that EEPROM is 1MB ?

IF you are referring to the 1024KB (and yes I noted the CAPITAL letters here too ) then we

should go back to the OFFICIAL Arduino UNO reference page
http://arduino.cc/en/Main/arduinoBoardUno
which I just cut and pasted the text from @ 2AM with red code eyes :astonished:
If you take a careful look on the official page which I referenced you will see their typo

too …YIP… this is the direct quote , cap’s and all from the page it states (copy and

pasted for all to peruse) … :

Summary
Microcontroller ATmega328
Operating Voltage 5V
Input Voltage (recommended) 7-12V
Input Voltage (limits) 6-20V
Digital I/O Pins 14 (of which 6 provide PWM output)
Analog Input Pins 6
DC Current per I/O Pin 40 mA
DC Current for 3.3V Pin 50 mA
Flash Memory 32 KB (ATmega328) of which 0.5 KB used by bootloader
SRAM 2 KB (ATmega328)
EEPROM 1 KB (ATmega328)
Clock Speed 16 MHz

YES INDEED …
HAHA
I think perhaps that Verizon video clip should be re-directed/sent to the Arduino folks for
bloating the specifications,especially if ridicule is the intention !
And I too had to do a double take that night …
but I’m sure if you just re-read my earlier post here

You will indeed notice that I am using BYTES (Bytes) bytes and NOT KILOBYTES in my
calculations (which of course may well be way off the mark :-).

@PaulS

Why when the alarm goes off ??
You have 42 alarm clocks in your bedroom. Does it matter what they are for when they are all

quiet? When one goes off, and wakes you up, does it matter which one needs to STFU?

AAH…now here is a classic case of misinterpretation and confusion :slight_smile:
OFF ? as in alarm goes off aka TRIGGERED
OR
OFF ? as in switched OFF.

A very subtle subtle difference.
I must admit I was referring to SWITCHED OFF after it has completed triggering.

OK anyways , moving on.
@PaulS

Yes. It’s still not clear what you intend to do when an alarm goes off. Looking

through the array of structs to see if this alarm if the start alarm or the end alarm for

the device at this position will let you determine the device. But, then what? Clearly (to

me at least), the Arduino should actually do something when the alarm goes off. It should

turn a pin on or off. It should display a message somewhere. It should do something.

The information needed to do whatever needs to be done could be stored in the struct, too,

keeping all the related data together in one data structure.

Let’s use and LED (It’s actually an infrared right in my puppy box among other things)as a

device that we would like to switch on and off at the desired time and date.

think of the LED as device 465 aka devID 465

BEFORE I attempt to create the STRUCT to hold the follwing things:
AlarmID, start time, end time
(I hope this is what’s required inside it)

I would like to know the following(and again pardon the ignorance thus far):

1.Can the struct consist of already created time_t values ?

So assuming this is the partial code:
(and maybe I’m wrong in creating a time_ value for the start time (stm) and end time (etm)

…perhaps I could have one routine which just cets run twice for creating the two ?)

tmElements_t stm; // start time values go here
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
  Alarm.triggerOnce(makeTime(stm), OnceOnly) ;

tmElements_t etm; // end time values go here
  etm.Year = 2014 -1970;
  etm.Month = 9;
  etm.Day = 26;
  etm.Hour = 2;
  etm.Minute = 39;
  etm.Second = 30;
  Alarm.triggerOnce(makeTime(etm), OnceOnly) ;
 
}



// functions to be called when an alarm triggers:

void OnceOnly(){
  Serial.println("This timer only triggers once");
LED_ON;
  
}

Here goes with the STRUCT (Hold thumbs, Iknow it’s probably way off …eeeek!):

typedef struct{      
  uint8_t stm //start time                                      
  uint8_t etm //end time
  uint8_t AlarmID_t //The alarm ID
}devID;


devID[50]; // make an array of devID's which we can use an and index

Ok whew…! I think this is the start so far.

Now I just need to know what the format of the elements on the struct should be and which

part of the start and end time (namely stm and etm) should be stored in the struct,An issue

here is that when the start and end time alarms are created they are given a static name (in

this instance like stm and etm) can these be named dynamically as the devID is passed in via

serial ?
For example if I type in devID 465 at the serial console I would get prompted to type in a

start and end time.
So I guess I could grab the devID there and attach an s like 465stm and 465etm to the

Alarm.triggerOnce fucntion ?

[code] 
tmElements_t %stm ; // <<<<<<devID would get attached to start time value ..I know this 

isn't correct yet but will fix &stm
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
  Alarm.triggerOnce(makeTime(&stm), OnceOnly) ; //also not correct yet but will fix &stm

So am I on track so far ?

PS: On a side note I thought this might be of use to a few people here:
http://littlebirdelectronics.com.au/blogs/frontpage/6325536-tutorial-increase-your-arduinos-eeprom-capacity

Looking forward to replies and comments and thank you for all of the help thus far.
Kind regards

Joe4444

On a passing thought …
“To err is human; to forgive, divine.” Alexander Pope (1688-1744) English poet[/code]

If you take a careful look on the official page which I referenced you will see their typo

Would that be the "typo" where they say that there is ONE kilobyte of EEPROM? How does that make them wrong when YOU changed it to 1024 kilobytes?

1.Can the struct consist of already created time_t values ?

Of course.

tmElements_t stm; // start time values go here
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
  Alarm.triggerOnce(makeTime(stm), OnceOnly) ;

The alarm ID returned by the triggerOnce() method just hit the bit bucket.

I can't see that it makes any sense to save one-shot alarms in EEPROM. Certainly not ones that have already happened. Now, an alarm that is triggered once a day or once a week might make sense.

typedef struct{      
  uint8_t stm //start time                                      
  uint8_t etm //end time
  uint8_t AlarmID_t //The alarm ID
}devID;

You created two alarms, and discarded both IDs. Which one of the IDs are you planning on storing?

So am I on track so far ?

No. Look at your struct. Calling the struct devID doesn't make it a device ID. Where are you going to store 465 in that struct?

Hi PaulS

Apologies for the late reply on this...I wondered where my post had disappeared to ...for some reason I must have hit reply in the wrong topic and it ended up here instead of in timealarms help :-( , do you know how I could move it or get it moved or should I just continue here ?

I have spent the last week trying to get my head around structs by reading tutorials on the internet so I can at least try to grasp the concepts so I am at least better prepared to ask a question here ( I am definitely battling along and appreciate all the help from you and otheres here and I would just like to say thank you for all the help and direction so far, it certainly is a guiding light in a dark tunnel)

Just as a recap as to what I would like to achieve (quite simple I guess for many on here I'm sure but a daunting task for me, but I am grateful for the chance to learn and understand)

So here goes: Using the serial console as input I would like to enter a device id to set a specific ON and OFF time for. (I already have some very simple code to get the info to set a start and end time (see code below for the results which are stm and etm repectively)

I would like to have a start (stm) and end alarm (etm) time and date as well as the timelearms library alarmID linked to what I have called a device id(devID) , please consider the device as an LED.

The reason for this is so that I can somehow check the alarms and their alarm ID's against a device id for example; dev465 alarmID 12 START(ON) 10:00:05 10/08/2014 alarmID 14 END (OFF) 11:00:00 11/09/2014

So now the arduino will have a list of all devices and their start (ON) and end(OFF) times.

Eventually I would like to have these stored in EEPROM as these start and end times would disappear if there is a power failure.

@Pauls

1.Can the struct consist of already created time_t values ? Of course.

Thank you that clears that up :-) but have I declared the members in the struct correctly tohold the data required ?

Now regarding this:

tmElements_t stm; // start time values go here
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
  Alarm.triggerOnce(makeTime(stm), OnceOnly) ;

I use that to create the START (ON) time and then this to create the end time:

tmElements_t stm; // start time values go here
  etm.Year = 2014 -1970;
  etm.Month = 10;
  etm.Day = 10;
  etm.Hour = 2;
  etm.Minute = 15;
  etm.Second = 20;
  Alarm.triggerOnce(makeTime(etm), OnceOnly) ;

Ok so now I have two onceonly alarms namely stm and etm.

And I have already got a device id (devID) from a pre-defined or user aquired from serial console variable. for example : int devID = 465

So I had this in mind for a struct:

typedef struct{      
  uint8_t stm //start time                                      
  uint8_t etm //end time
  uint8_t AlarmID_t //The alarm ID
}devID;

@PaulS

So am I on track so far ? No. Look at your struct. Calling the struct devID doesn't make it a device ID. Where are you going to store 465 in that struct?

You're right I probably need to have the devID as a struct member as well, maybe like this ? (please correct me if I'm wrong)

typedef struct{      
  uint8_t stm //start time                                      
  uint8_t etm //end time
  uint8_t AlarmID_t //The alarm ID
  uint8_t devID
}devonoff;

Ok so now I have a struct called devonoff which I can use to set the members values like :

struct devonoff device;

device.devid = 465 //to set dev.id = 465

Is this correct so far ?

And then how do I set the start time(stm) and end time (etm) ? Is this the way ?

device.stm = ?????; //EEK HELP PLEASE
device.etm = ?????;

I'm lost as to how to put the time and date I get from here (makeTime(stm) into these members in the struct ,would it be device.stm = (maketime(stm) ??

Am I a little bit on track so far at least ?

Some fundamental questions here are how do I fetch/get the AlarmID_t and put it into the struct at the time of creating each alarm ?

@PaulS

You said :

You created two alarms, and discarded both IDs. Which one of the IDs are you planning on storing?

Where/how did I discard the ID's ?

Well I would like to store both especially if these are future events and they have not triggered yet. For example : Start/Switch devID 465 ON at 10:02:00 10/17/2014 and End/Switch devID 465 OFF at 15:00:00 11/26/2014

Again the reason might be if there is a power failure tonight then all the alarms are gone and have to be recreated not so ?

I really look forward to your replies and/or more help and guidance 'cos I sure am battling with this one.

Thanks again for the help and suggestions and corrections thus far :

Kind regards

Joe4444

Ok so now I have two onceonly alarms namely stm and etm.

You don't capture the alarm ID, so, really, you have nothing.

Where/how did I discard the ID's

? ALL of the Alarm methods return a value. Stop discarding it.

AlarmID_t startID = Alarm.triggerOnce(...);

Then, store startID in the struct.

I probably need to have the devID as a struct member as well, maybe like this ?

The alarm ID, which you discarded, knows what time it is supposed to go off. I see no reason to store that data. You need TWO alarm IDs - one for on and one for off, since you created two alarm instances.

Is this correct so far ?

You are on the right track.

And then how do I set the start time(stm) and end time (etm) ?

Why do you need to? If you insist,

device.stm = makeTime(stm);
device.etm = makeTime(etm);

But, of course your type in the struct definition is wrong. It needs to be whatever makeTime() returns.

Or, it needs to be tmElements_t, use this:

device.stm = stm;
device.etm = etm;

@PaulS

Thanks again for the reply ..WOW so FAST thank you kindly !

Ok is this more like it ? :

typedef struct{      
  uint8_t stm //start time element                                     
  uint8_t etm //end time element
  uint8_t startID //The alarm ID ON time and date
  uint8_t endID //The alarm ID OFF time and date
  uint8_t devID
}devonoff;

struct devonoff device;

device.devid = 465 //to set dev.id = 465

//build the time elements
tmElements_t device.stm; // start time values go here
  device.stm.Year = 2014 -1970;
  device.stm.Month = 9;
  device.stm.Day = 26;
  device.stm.Hour = 2;
  device.stm.Minute = 39;
  device.stm.Second = 0;
AlarmID_t startID Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;

tmElements_t device.etm; // end time values go here
  device.etm.Year = 2014 -1970;
  device.etm.Month = 9;
  device.etm.Day = 26;
  device.etm.Hour = 2;
  device.etm.Minute = 39;
  device.etm.Second = 30;
AlarmID_t endID Alarm.triggerOnce(makeTime(device.etm), OnceOnly) ;

I thought by using this code :

tmElements_t stm; // start time values go here
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
  Alarm.triggerOnce(makeTime(stm), OnceOnly) ;

The alarmID would be a random number between 0 and 255 and was not sure how to do a lookup for that number if it is linked to a devID like 465.

So OK ..if I now have all the elements in the struct how do I display/check the startID and endID etc attached/linked to devID 465 ? And does this mean that a new struct must be created to hold the elements of each devID? For example when I enter devID 2 then I capture the start and end times and startID and endID for it, must I create a new struct for the next device like devID 3 etc etc. ( Assuming that there are multiple devices (devID) and there are two alarms for each one (ON and OFF date and time)) ? is it possible (and maybe a good idea) to have startID and endID have the number 465(if this is the examnple devID) attached ...something like start465 and end465) as alarm ID's ?

So the steps so far are: 1. Request a devID from serial console (I left this out here to reduce clutter) Store the devID in struct. 2. Collect the data for and generate start time alarm. Store it in struct. 3 Collect the data for and generate end time alarm. Store it in struct.

NOTE : I am not sure how many devices I can have as a max . I'm guessing around 128 (0 to 127) since each will have two alarms and the max alarms is 0 to 255 . Is this correct thinking. ? Are more devices possible ? if so, how could I increase the number?

Am I correct in thinking that the on and off alarms would need to be stored in EEPROM so that if there is a power failure, once power is restored the values can be read and checked against the current time and date to see if anything should be ON as per the current time ? (of course I was thinking to only implement this once i have the code working but there's no harm in planning properly in the initial code)

As always I look forward to your reply

Thanks again

Joe4444

Ok is this more like it ? :

A typedef statement takes two names - the existing type and the name to be used as a synonym.

Therefore, this does not look right:

struct devonoff device;

You have an anonymous structure that you want to refer to as using the name devonoff - at least that’s what you said with the typedef and struct definition all in one. Therefore, you do not have anything whose type is struct devonoff. Loose the struct.

tmElements_t device.stm; // start time values go here

No. device.stm already has a type.

AlarmID_t startID = Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;

I thought by using this code :… The alarmID would be a random number between 0 and 255

It’s not a random number. It will be between 0 and the number of alarms supported.

and was not sure how to do a lookup for that number if it is linked to a devID like 465.

Unless you capture the alarm ID, you can’t. If you do, then when the alarm goes off, get it’s ID, and compare it to device.startID and/device.endID. If it matches, the device ID is the value in device.devID.

if I now have all the elements in the struct how do I display/check the startID and endID etc attached/linked to devID 465 ?

If you have a red coat and matching red gloves, how can you tell which coat goes with the glove that I point to? The red gloves and coat form a set, just as the elements in the struct. You look in the set to see if something in the set matches what you are looking for, and then you know which is the correct set. Because everything is in a set, you can get at the other stuff in the set.

And does this mean that a new struct must be created to hold the elements of each devID?

A new instance of the struct.

You can have an array of instances, just so you know. Iterating through the instances is then easy.

For example when I enter devID 2 then I capture the start and end times and startID and endID for it, must I create a new struct for the next device like devID 3 etc etc.

As I said, a new instance of the struct you have already defined is needed. You have one called device. You’d need another one called device2, and one called device3, etc. Of course an array of instances:

devonoff devices[10];

makes more sense.

is it possible (and maybe a good idea) to have startID and endID have the number 465(if this is the examnple devID) attached …something like start465 and end465) as alarm ID’s ?

No, and no. The struct definition is fixed. The instances can be named. The members are not named within each instance.

@ PaulS

Thanks a million for the prompt reply !

Yay… it slowly making sense(I think) thanks to your guidance.

This is what I have so far :

typedef struct{      
  uint8_t stm 		//start time element - will correct variable type for this                                    
  uint8_t etm 		//end time element -will correct variable type for this 
  uint8_t startID 	//The alarm ID ON time and date
  uint8_t endID 	//The alarm ID OFF time and date
  uint8_t devID 	//pre-populated to device ID 5 for now
}devonoff;

devonoff device[15];	//array for struct instances

//Then assuming code has been run to fetch devID(device ID eg 5)

device.devid = 5; 	//to set dev.id = 5
device [device.devid]; 	//aray positon matches devid ?? is this correct to name each instance?
startID();		//fetch time and generate alarm for start/on time and date
endID(); 		//fetch time and generate alarm for start/on time and date

startID(){
//build the time elements
tmElements_t device.stm; // start time values go here
  stm.Year = 2014 -1970;
  stm.Month = 9;
  stm.Day = 26;
  stm.Hour = 2;
  stm.Minute = 39;
  stm.Second = 0;
AlarmID_t startID Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;
}

endID(){
tmElements_t device.etm; // end time values go here
  etm.Year = 2014 -1970;
  etm.Month = 9;
  etm.Day = 26;
  etm.Hour = 2;
  etm.Minute = 39;
  etm.Second = 30;
AlarmID_t endID Alarm.triggerOnce(makeTime(device.etm), OnceOnly) ;
}

I have attempted to set each major task into functions (they are not yet tested nor have I put the code in it’s correct format for the arduino yet)

Here’s the rundown so far:
1.
devID would gets collected from serial console (code not shown here to reduce clutter)
2.
Use the devID to set the posistion in the array
Is this needed or should it just be dynamically assigned into any position in the array ?
I did pop some code in to try explain this , just don’t know if it’s correct :frowning:
3.
Run through collecting start and end dates for the alarm and then create the alarm ID called startID
(This is where I think there youdl be problems since each device will have the same alarms called startID - which is why I thought to try attach the devID to this name …what’s your feeeling about this ?)
Is each startID and endID unique to the struct instance it’s created in? I thought the alarmID’s are global.

Do the same for collecting and generating and date and time called endID.

Done (I think ?)

So hopefully each device or devID get’s popped into device into a position in the array equal to the devID.

@PaulS

tmElements_t device.stm; // start time values go here

No. device.stm already has a type.

AlarmID_t startID = Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;

What did I mess up with there ?
I collect all the elements (eg. stm.day etc) to make a tmElements_t called device.stm …whats wrong here?

and this issues

For example when I enter devID 2 then I capture the start and end times and startID and endID for it, must I create a new struct for the next device like devID 3 etc etc.
As I said, a new instance of the struct you have already defined is needed. You have one called device. You’d need another one called device2, and one called device3, etc. Of course an array of instances:
Code:

devonoff devices[10];

makes more sense.

and thanks for this too

Because everything is in a set, you can get at the other stuff in the set.

The gloves example definitely helps makes sense of it …Thank you !

I agree thank you … that clears it up especially using the array as a kind of index/lookup (is that the right terminology?)

Once the array is built up , will I need a for loop to search the array to find all elements that link to a devID for example, or is there another way ?

and in an earlier reply you mentioned this :

Quote
And then how do I set the start time(stm) and end time (etm) ?
Why do you need to? If you insist,

device.stm = makeTime(stm);

device.etm = makeTime(etm);



But, of course your type in the struct definition is wrong. It needs to be whatever makeTime() returns.

Or, it needs to be tmElements_t, use this:


device.stm = stm;
device.etm = etm;

Does maketime() return uint_32 ?

And are you saying I should set the struct member to be:

device.stm = stm;
device.etm = etm;

like this :

typedef struct{      
  uint8_t stm = stm		//start time element - will correct variable type for this                                    
  uint8_t etm  = etm		//end time element -will correct variable type for this 
  uint8_t startID 	//The alarm ID ON time and date
  uint8_t endID 	//The alarm ID OFF time and date
  uint8_t devID 	//pre=populated to device ID 5 for now
}devonoff;

And as I look at the code now I probably don’t even need them in each struct since I will collect them and use them only when an alarm is to be created for both start and end times so they really just need to be declared as variables and it would be a waste of memory to hold these since we already have the alarmID for start and end and it’s these that would eventually get stored in EEPROM.
Is that correct ?

Thank once more, it really is starting to make much more sense now(I think!)

Again and as always I look forward to your reply

Kind regards
Joe444

devonoff device[15];    //array for struct instances

Meaningful names are important. I use singular names for singular variables and plural names for plural variables (arrays)..

device.devid = 5;   //to set dev.id = 5

The array does not have a devid field.

device [device.devid];  //aray positon matches devid ?? is this correct to name each instance?

While this would be valid if device had a devid field, it is meaningless in this context, the same as

device[5];

would be.

startID(){

Functions MUST have return types.

tmElements_t device.stm; // start time values go here

Still wrong. the array does not have a stm field. Even if you used device[0].stm (or some other index value), the type of device[n].stm is defined in the struct. You can't use periods in variable names, so you can't (and don't need to) define a new variable this way.

AlarmID_t startID Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;

Still wrong. There is STILL no equal sign. And, creating the local variable startID in the function makes no sense. It goes out of scope when the function ends, rendering it unusable.

At least try compiling your code before posting it.

@PaulS

First off.. Thanks yet again for the reply :-)

Secondly please accept my apologies for the the code errors, you are correct about it not being compiled, in my excitement I have typed it all up in notepad (hence the reason for mistakes all over the place) and will attempt to compile it on the arduino tomorrow as I am travelling today.

just a quick reply to some of your replies 1.

devonoff device[15]; //array for struct instances

Meaningful names are important. I use singular names for singular variables and plural names for plural variables (arrays)..

so should i be doing something like this ?

devonoff devices[15];

and you also mentioned this :

device.devid = 5;     //to set dev.id = 5

The array does not have a devid field.

So the array (device) doesn't but the struct (devonoff) does ? So how do I let the the array position = the devID ? (isn't his the intention or plan ?

and then on this:

Functions MUST have return types.

Great catch .. I totally left out the return; line. Thank you

and here:

AlarmID_t startID Alarm.triggerOnce(makeTime(device.stm), OnceOnly) ;

Still wrong. There is STILL no equal sign.

All I was trying to do here is set the alarmID which you advised I do in an earlier post. Where did I mess up exactly ? What equal sign ? EEEEK! and :

And, creating the local variable startID in the function makes no sense. It goes out of scope when the function ends, rendering it unusable.

Ok I will skip the functions until I have the code working and then can poke around.

I will go carefully through each of your replies and fix and correct where I messed up and once that's all done I will feed back.

Thanks once again , in fact thank you, thank you and thank you. I have lots of info now , the dark tunnel is getting lighter and I have some research and lots of reading.

I look forward to you reply.

Kind regards

Joe4444

So how do I let the the array position = the devID ? (isn't his the intention or plan ?

You don't, and no it isn't. If the array index were the device ID, there would be no reason to store the device ID in the struct.

All I was trying to do here is set the alarmID which you advised I do in an earlier post. Where did I mess up exactly ? What equal sign ? EEEEK!

AlarmID_t is a type. startID is a variable name. Alarm.triggerOnce() is a function call. The function returns a value, which needs to be assigned to the variable. Therefore, you need an assignment operator somewhere in the statement. It should be fairly obvious where, and what the operator is. If not, look at one of my earlier responses, where I highlighted some stuff.