Project Timer with DS1307 - Array of TimeElements; - Is Possible ?

From the readme :

"Low level functions to convert between system time and individual time elements are provided:
breakTime( time, &tm); // break time_t into elements stored in tm struct
makeTime( &tm); // return time_t from elements stored in tm struct "

So you can convert both ways.

Hi Guys,
really thanks I've understood now ... so thanks for the very great support !!! I've adjust my sketch and now it's working ... so this morning I will try to play well with this :wink: thanks again,

warm regards,
Gnux

Good Morning,

I've note using the TimerAlarmExample:

#include <Time.h>
#include <TimeAlarms.h>

void setup()
{
  Serial.begin(9600);
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
  // create the alarms 
  Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day 
  Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday 

 
  Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds 
}

void  loop(){  
  //digitalClockDisplay();
 
   
   Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights off");    
}

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

void WeeklyAlarm(){
  Serial.println("Alarm: - its Monday Morning");      
}

void ExplicitAlarm(){
  Serial.println("Alarm: - this triggers only at the given date and time");       
}

void Repeats(){
  Serial.println("15 second timer");         
}

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

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

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

If I didn't put

 Alarm.delay(1000);

the timer doesn't work ...

My understanding is that the timer should work in background without block the cpu each time for a second ...

is there a way to change it ?

thx
gnux

The documentation for TimeAlarms specifically says that you must use Alarm.delay() for it to work otherwise it cannot check for alarms. There is no reason why you should not use Alarm.delay(1) if you want it not to block for 1 second. You could also arrange to call Alarm.delay() at less frequent intervals using millis() as your own non blocking timer and only calling it when the delay will not affect your program.

Thanks for information,
so then Alarm.delay(); is mandatory for start timer ...

into Example there is Alarm.delay(1000); just for see the time that change each 1 seconds...

correct ?

Also another curiosity ... if I use Alarm.triggerOnce(); into setup of course is used one time only , if call Alarm.triggerOnce() into loop after the first time that alarm is triggered each time is call the function ... due the fact the condition is always verify ...

Is there the possibility to Triggered off the alarm just after that is verify ? in this way I can pass several arguments to the triggeronce into the loop and i will able to change my timer ...

Make sense the questions ?

thanks
gnux

Post you whole code that is not working properly so that we can see how it is written and give advice.

I am sorry but I cannot make sense of your questions. Can you please rephrase them ?

If you are asking if you can disable an alarm once it is set then, yes you can. There is a limit to how many alarms can be set, normally 6 but the limit can be increased up to a limit of 255.

Hi, here you are the code ...
for sure the value into the ram are correct ... due the fact if i call the routine

Alarm.triggerOnce(makeTime(tm0stop), StopTimer0);

into the loop it's work ...

the code for the sketch :

void FaiTempo0()
{
   // make time stop timer 1
 TimerWakeup0 = memoria[0];
 tm0start.Hour =   memoria[2];  
 tm0start.Minute = memoria[3];
 tm0start.Second = 00;
 tm0start.Day =   memoria[4];
 tm0start.Month = memoria[5];
 tm0start.Year = (memoria[6]+2000) - 1970;
 StartTimer0 = memoria[7];
 
 // make time stop timer 0 
 tm0stop.Hour =   memoria[8];
 tm0stop.Minute = memoria[8];
 tm0stop.Second = 00;
 tm0stop.Day =   memoria[10];
 tm0stop.Month = memoria[11];
 tm0stop.Year = (memoria[12]+2000) - 1970;
 StopTimer0 = memoria[13];
}

void Timer()
{
   
     FaiTempo0();
      Alarm.triggerOnce(makeTime(tm0start), FunctionStartTimer0);
     if (TimerWakeup0 == 1) 
      {
        if (StartTimer0 == 0)
         {
          Alarm.triggerOnce(makeTime(tm0start), FunctionStartTimer0); 
          memoria[7] = 1;
          EEPROM.write(7, memoria[7]);
          
         }
         else
          {    
             if (StopTimer0 == 0);
              {
                Alarm.triggerOnce(makeTime(tm0stop), FunctionStopTimer0); 
                
                memoria[13] = 1;
                memoria[0] = 0;
               
                EEPROM.write(13, memoria[13]);
                EEPROM.write(0, memoria[0]);
                }   
            }  
       
           }
}

void loop() {
    Timer();
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
  Alarm.delay(1);
}

of course there is all variable declared ...and memoria red value from eeprom correctly at the setup()

my purpose when will be ok is change from a menu value timer (date start and time start,devstart etc etc)

this was the scope of my question ... if is possible call triggerOnce ... into the loop and stop it after will be excute ... but I don't know how ...

thanks for the support,
gnux

We need to see the whole sketch to understand what you are doing

Ok was to long I will split in 2 part :slight_smile:

1°st part:

#include <Time.h>
#include <TimeAlarms.h>
#include <LiquidCrystal.h>	// ensure that the include path is set
#include "M2tk.h"
#include <VirtualWire.h>
#include <Wire.h>
#include <DS1307.h>
#include <EEPROM.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

//Variabili Globali
char dev;
char testo[15];

// usata per mandare il messaggio
char messaggio[15];
// usato nell'index del close del keypad
int ind = 0;
// usato nel keypad
char Tasto;
// usato nel keyoad
unsigned long UltimoTasto = 0;
// usato nel nella procedura seriale
String LeggiStringa;
byte memoria[105];

uint8_t TimerWakeup0;  // serve per controllare se il timer è enable/disable
uint8_t StartTimer0;   // serve per controllare se è stato attivato il primo timer
uint8_t StopTimer0;    // serve per controllare se è stato attivato il secondo timer

TimeElements tm0start;
TimeElements tm0stop;
TimeElements tm1start;
TimeElements tm1stop;
TimeElements tm2start;
TimeElements tm2stop;
TimeElements tm3start;
TimeElements tm3stop;
TimeElements tm4start;
TimeElements tm4stop;
TimeElements tm5start;
TimeElements tm5stop;
TimeElements tm6start;
TimeElements tm6stop;
TimeElements tm7start;
TimeElements tm7stop;

void LeggiEeprom()
{
  int ind;
   for (ind =0; ind <= 105 ; ind++)
      {
        memoria[ind] = EEPROM.read(ind);
      }   
}

void FaiTempo0()
{
   // make time stop timer 1
 TimerWakeup0 = memoria[0];
 tm0start.Hour =   memoria[2];  
 tm0start.Minute = memoria[3];
 tm0start.Second = 00;
 tm0start.Day =   memoria[4];
 tm0start.Month = memoria[5];
 tm0start.Year = (memoria[6]+2000) - 1970;
 StartTimer0 = memoria[7];
 
 // make time stop timer 0 
 tm0stop.Hour =   memoria[8];
 tm0stop.Minute = memoria[8];
 tm0stop.Second = 00;
 tm0stop.Day =   memoria[10];
 tm0stop.Month = memoria[11];
 tm0stop.Year = (memoria[12]+2000) - 1970;
 StopTimer0 = memoria[13];
}

void Timer()
{
   
     FaiTempo0();
      Alarm.triggerOnce(makeTime(tm0start), FunctionStartTimer0);
     if (TimerWakeup0 == 1) 
      {
        if (StartTimer0 == 0)
         {
          Alarm.triggerOnce(makeTime(tm0start), FunctionStartTimer0); 
          memoria[7] = 1;
          EEPROM.write(7, memoria[7]);
          
         }
         else
          {    
             if (StopTimer0 == 0);
              {
                Alarm.triggerOnce(makeTime(tm0stop), FunctionStopTimer0); 
                
                memoria[13] = 1;
                memoria[0] = 0;
               
                EEPROM.write(13, memoria[13]);
                EEPROM.write(0, memoria[0]);
                }   
            }  
       
           }
}


void FunctionStartTimer0()
{
  messaggio[0]='1';
  messaggio[1]='0';
  messaggio[2]='#';
  Serial.println("Start Timer 0");
  // TxMsg(messaggio);
  
}

void FunctionStopTimer0()
{
  messaggio[0]='*';
  messaggio[1]='0';
  messaggio[2]='#';
  Serial.println("Stop Timer 0");
  // TxMsg(messaggio);
  
}

now will continue with the second one :

Second Part:

void DefinizionePin()
{
  //Piedini Utilizzati per Gestire LCD  
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  pinMode(A5, INPUT);
  pinMode(13, OUTPUT);
}

void Comunicazione()
{
   Wire.begin();         // Inizializzo la Comunicazione I2C
   Serial.begin(9600);	 // Inizializzo la Seriale
   vw_setup(1200);	 // Inizializzo al Comunicazione TTL su Virtual Wire
   vw_rx_start();        // Start the receiver PLL running
   RTC.start();          // Fai partire il clock
}


void TxMsg(char buffer[15])
{
   vw_send((uint8_t *)buffer, strlen(buffer));
   vw_wait_tx(); // Wait until the whole message is gone
   Serial.println(buffer);
   buffer[0]='\0';
   Serial.println("Comando Inviato");
}

// Forward declaration of the toplevel element
M2_EXTERN_HLIST(top_el_expandable_menu);

/* SetDate 1-1  */
uint8_t dt_day = 1;
uint8_t dt_month = 1;
uint8_t dt_year = 12;
uint8_t dt_min = 1;
uint8_t dt_hour = 1;

void dt_current(void)
{
  Serial.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  Serial.print(":");
  Serial.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
  Serial.print(":");
  Serial.print(RTC.get(DS1307_SEC,false));//read seconds
  Serial.print("      ");                 // some space for a more happy life
  Serial.print(RTC.get(DS1307_DATE,false));//read date
  Serial.print("/");
  Serial.print(RTC.get(DS1307_MTH,false));//read month
  Serial.print("/");
  Serial.print(RTC.get(DS1307_YR,false)); //read year
  Serial.println();
  
  Serial.print(hour());
  Serial.print(minute());
  Serial.print(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println();
}


void dt_get_from_RTC(void)
{
  dt_day = RTC.get(DS1307_DATE,false);
  dt_month = RTC.get(DS1307_MTH,false);
  dt_year = (RTC.get(DS1307_YR,false)-2000);
  dt_min = RTC.get(DS1307_MIN,false);
  dt_hour = RTC.get(DS1307_HR,true); 
}

void dt_put_to_RTC(void)
{
  RTC.stop();
  RTC.set(DS1307_DATE,dt_day);
  RTC.set(DS1307_MTH,dt_month);
  RTC.set(DS1307_YR,dt_year);
  RTC.set(DS1307_HR,dt_hour);
  RTC.set(DS1307_MIN,dt_min);
  RTC.start();
  setTime(RTC.get(DS1307_HR,true),RTC.get(DS1307_MIN,false),RTC.get(DS1307_SEC,false),RTC.get(DS1307_DATE,false),RTC.get(DS1307_MTH,false),(RTC.get(DS1307_YR,false)-2000)); 
  
  
}

void dt_ok_date(m2_el_fnarg_p fnarg)  
{
  dt_put_to_RTC();
  m2_SetRoot(&top_el_expandable_menu); 
}

void time_ok_button(m2_el_fnarg_p fnarg)
{
 dt_put_to_RTC();
  m2_SetRoot(&top_el_expandable_menu); 
}

void view_ok_button(m2_el_fnarg_p fnarg)
{
  dt_current();
  m2_SetRoot(&top_el_expandable_menu);  
}

M2_U8NUM(el_dt_year, "c2", 0,99,&dt_year);
M2_LABEL(el_dt_sep1, "b1", "-");
M2_U8NUM(el_dt_month, "c2", 1,12,&dt_month);
M2_LABEL(el_dt_sep2, "b1", "-");
M2_U8NUM(el_dt_day, "c2", 1,31,&dt_day);

M2_LIST(list_date) = { &el_dt_year, &el_dt_sep1, &el_dt_month, &el_dt_sep2, &el_dt_day };
M2_HLIST(el_date, NULL, list_date);

M2_ROOT(el_dt_cancel, NULL, "cancel", &top_el_expandable_menu);
M2_BUTTON(el_dt_ok, NULL, "ok", dt_ok_date);
M2_LIST(list_dt_buttons) = {&el_dt_cancel, &el_dt_ok };
M2_HLIST(el_dt_buttons, NULL, list_dt_buttons);

M2_LIST(list_dt) = {&el_date, &el_dt_buttons };
M2_VLIST(el_top_dt, NULL, list_dt);

/* Set time 1-2 ---------------------------------------------------------------------*/

M2_U8NUM(el_dt_hour, "c2", 0,23,&dt_hour);
M2_LABEL(el_dt_c, "b1", ":");
M2_U8NUM(el_dt_min, "c2", 0,59,&dt_min);

M2_LIST(list_time) = { &el_dt_hour, &el_dt_c, &el_dt_min};
M2_HLIST(el_time, NULL, list_time);

M2_ROOT(el_time_cancel, NULL, "cancel", &top_el_expandable_menu);
M2_BUTTON(el_time_ok, NULL, "ok", time_ok_button);
M2_LIST(list_time_buttons) = {&el_time_cancel, &el_time_ok };
M2_HLIST(el_time_buttons, NULL, list_time_buttons);

M2_LIST(list_t) = {&el_time, &el_time_buttons};
M2_VLIST(el_top_time, NULL, list_t);

/* View DateTime 1-3  */
M2_LABEL(el_dt_view, "b1", "DateTimeNow");
M2_LIST(list_view) = {&el_dt_view};
M2_HLIST(el_view, NULL, list_view);

M2_ROOT(el_view_cancel, NULL, "cancel", &top_el_expandable_menu);
M2_BUTTON(el_view_ok, NULL, "ok", view_ok_button);
M2_LIST(list_view_buttons) = {&el_view_cancel, &el_view_ok };
M2_HLIST(el_view_buttons, NULL, list_view_buttons);

M2_LIST(list_v) = {&el_view, &el_view_buttons};
M2_VLIST(el_top_view, NULL, list_v);

/* -------------- DEVICE 2 ----------------------*/

uint8_t u8dev = 0;
uint8_t u8stato = 0;

void fn_clean_dev(m2_el_fnarg_p fnarg) {
  u8dev = 0;
}

void dev_ok_button(m2_el_fnarg_p fnarg) {
  
  if (u8dev <= 9) 
    {
     messaggio[1] = u8dev + 48;  
     messaggio[2] = '#';
     messaggio[3] = '\0';
    }
  
    if (u8dev > 9)
    {
      int x,y;
      y = u8dev/10;
      messaggio[1] = y + 48;
      x = u8dev % 10;
      messaggio[2] = x + 48;
      messaggio[3] = '#';
      messaggio[4] = '\0';
    }    
    
    if (u8stato == 0)
    {
      messaggio[0] ='*';
    }    
    
    if (u8stato == 1)
    {
      messaggio[0] ='1';
    }   
       
  TxMsg(messaggio);
  
  messaggio[0] = '\0';
}

void dev_stato_button(m2_el_fnarg_p fnarg) {
 // procedura per recuperare lo stato della periferica
 
}

M2_LABEL(el_num_label1, NULL, "Select Dev:");
M2_U8NUM(el_num_1, NULL, 0, 64, &u8dev);

M2_LABEL(el_num_label2,NULL, "Turn Off/On:");
M2_U8NUM(el_num_2, NULL, 0, 1, &u8stato);

M2_BUTTON(el_num_zero, "f4", "zero", fn_clean_dev);
M2_BUTTON(el_dev_ok, NULL, "ok", dev_ok_button);
M2_BUTTON(el_dev_stato, NULL, "stato", dev_stato_button);
M2_ROOT(el_num_goto_top, "f4", "back", &top_el_expandable_menu);

M2_LIST(num_list) = { 
    &el_num_label1, &el_num_1, 
    &el_num_label2, &el_num_2, 
    &el_dev_ok, &el_num_zero, &el_num_goto_top,&el_dev_stato
};
M2_GRIDLIST(el_num_menu, "c2", num_list);


/* --------------------------- main menu-------------------------- */
m2_menu_entry m2_2lmenu_data[] = 
{
  { "DATE/TIME 1", NULL },
  { ". SetDate 1-1", &el_top_dt },
  { ". SetTime 1-2", &el_top_time},
  { ". View DateTime 1-3", &el_top_view},
  { "DEVICES 2", NULL},
  { ". Manage 2-1", &el_num_menu},
  { NULL, NULL },
};

uint8_t m2_2lmenu_first;
uint8_t m2_2lmenu_cnt;

M2_2LMENU(el_2lmenu,"l4e1w12",&m2_2lmenu_first,&m2_2lmenu_cnt, m2_2lmenu_data,'+','-','\0');
M2_VSB(el_vsb, "l4w1r1", &m2_2lmenu_first, &m2_2lmenu_cnt);
M2_LIST(list_2lmenu) = { &el_2lmenu, &el_vsb };
M2_HLIST(top_el_expandable_menu, NULL, list_2lmenu);

// m2 object and constructor
M2tk m2(&top_el_expandable_menu, m2_es_arduino_serial, m2_eh_2bs, m2_gh_arduino_serial);

/* --------------------------- end menu-------------------------- */

void setup() 
{
     Comunicazione();
     LeggiEeprom();  
}

void loop() {
  
     
    Timer();
     
     
     
     // Alarm.triggerOnce(makeTime(tm0stop), StopTimer0);
 
  
  m2.checkKey();
  m2.checkKey();
  if ( m2.handleKey() )
    m2.draw();
  m2.checkKey();
  Alarm.delay(1);
}

Now just past the 2 in only one sketch,

regards,
gnux

Good Morning Folks,
with the sketch upload reported I've tried to set a Alarm.TriggerOnce(); for try to set timer dynamically changes the timer values from a menu ...

with the sketch that I've did I've put a If,Then,Else Structure for execute Alarm.TriggerOnce(); one time only check a flag inside a EEPROM.
The fact the function is execute but of course the timer doesn't start because the timer is match ...

So then I need to find a solution for call Alarm.TriggerOnce(); when I've want with dynamically value check this until is verify the first times that is verified change the value into the register and didn't check again until the value will be correct again...

is there something flag for check it inside a library ?

Please let me know if you want more specifics,

thanks
gnux

Sorry, but I am not sure what you want to do and what the problem is.
Can you please explain it step by step ?

I think that you want to set an alarm time from user input and to have the alarm trigger once. Is that right ?
If so, does the user input collect the data correctly (send it to Serial.print to check) and does the alarm trigger if you set the alarm time explicitly in code ?

Good Afternoon,

"I think that you want to set an alarm time from user input and to have the alarm trigger once. Is that right ?"

More or less, better ...

I want to set an alarm time from user input and to have the "Alarm TriggerOnce" each time that the user input match the trigger ...

So for example:

  • Call Timer1 ---> for start at 15:00 28/01/2013

and Can call Timer 1 each time base on the user input ...

If put Alarm TriggerOnce(); into the setup will be excute only one time or every time that value will change ? (of course behind the of value MakeTime() will change )

It is more clear now ? :slight_smile:

Thansk 1000 for the support,
gnux

gnusso:
Good Afternoon,

I want to set an alarm time from user input and to have the "Alarm TriggerOnce" each time that the user input match the trigger ...

You do realise that TriggerOnce will only do what it says and only trigger once ?

To repeat my previous question

does the user input collect the data correctly (send it to Serial.print to check) and does the alarm trigger if you set the alarm time explicitly in code ?

So if I put the Alarm.TriggerOnce(); with my value the alarm trig correct ... is not this the issues ...

you said ... you do realise that TriggerOnce will only do what it says and only trigger once ?

Ok ... so then I can change my questions ...

How i can do fom Trigger and events and the specific time dynamically ? (like Alarm.TriggerOnce(); but when I want ...and not only once ?)

otherwise if there something that told me when the function is execute maybe retrieve true or false I can call into the loop also ...

thanks gnux

Each TriggerOnce will only trigger once, which makes sense, but you can have several active TriggerOnce alarms set for different future dates and times. There is normally a limit of six alarms that can be active but you can change this.

Then ...
I've not understand bad ...

is not possible change dynamically trigger once ... because of course will be call once ... but I can call several times I think if not wrong will be max 255 modify the library ...

So, for you will be possible do ...

  • Configure the Alarm.TriggerOnce(); in the setup in this way will start the first time, always into the setup read timer in eeprom

then

  • I configure a timer from a menu and i store the new value in eeprom, then reset arduino ... now the system will read all the timer in eeprom and i'll apply it ... but is possible reset the micro via software ?

make sense for you ?

otherwise I don't know How to trigger an events dynamically ...

Thanks
gnux

Maybe can be used some function into yellow rectangle ? see the picture below reported ...

thanks
gnux

You can use the ones above the line that says "private:". You probably don't want to use the ones below "private:" even if you can.

In particular you may want to use enable() and disable(). You wouldn't ordinarily have need for those functions, but earlier I think you said something about "stopping" and "starting" alarms, so perhaps these enable() and disable() might be useful for what you are thinking.

What is your native language? I too have a very hard time understanding your posts, because of the English.

Cheers,
John

so, i think that problem is not the mother language but try to define correctly the issues that I've :slight_smile: Anyway I'm Italian ...

I try to explain better what I've in mind:

Scenario:

Set timer from a menu trigger at specific time.

Well, what I've understand using timer that is possible Trigger at specific date time using Alarm.TriggerOnce(); But this is used from one time only.

Assuming that I want call this "several times" changing the "timer value" from a Menu (then dynamically)... Which function should I use instead of Alarm.TriggerOnce() ? which is the correct approach ?

Is possible kindly have a simple example ?

Thanks for the support you are very great!,
gnux