Go Down

Topic: Time and TimeAlarms Libraries – Ask here for help or suggestions (Read 217304 times) previous topic - next topic

Bob808

It seems that I have another problem :)

I am storing the time on EEPROM, and have it read into 2 variables (hour and minute) and those variables are read by Alarms.
The thing is that if I have stored the alarm time on my EEPROM, at startup everything is fine, I do get the trigger on time.
But, if I dynamically change the EEPROM after the Arduino boot, then the alarms won't refresh.

Let me give you a bit of code so you understand:

Code: [Select]
void setup () {
 
 
    readEEPROM(0);          //read eeprom for alarm hour;
    onH=rec;               
    readEEPROM(1);          //read eeprom for alarm minute;
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);         
    offM=rec;
   
    Alarm.alarmRepeat(onH, onM, 0, LightsOn);
    Alarm.alarmRepeat(offH, offM, 0, LightsOff);
    if (onH < resethour && offH > resethour)
    {
      LightsOn();
    }
    else if (onH == resethour && onM <= resetminute)
    {
      if (offH == resethour && offM > resetminute)
       {
         LightsOn();
         FanOn();
       }
     }
}


void loop () {
  Alarm.delay(1);
}

void LightsOn() {
digitalWrite(light, HIGH); // Set Lights On
    Serial.println("Lights On");
}

void LightsOff() {
digitalWrite(light, LOW); // Set Lights Off
   Serial.println("Lights Off"); 
}

void readEEPROM(unsigned int eeaddress)                //EEPROM read function
{
  //function for reading EEPROM address, may vary depending on chip used
}

void writeEEPROM( unsigned int eeaddress, byte data)   //EEPROM write function
{
  //function for writing EEPROM address, may vary depending on chip used
}





I also have a part where I can write the alarm times on EEPROM with buttons/LCD. So, the part in setup after the alarms basically is a redundancy for power failure. At boot it reads the EEPROM for times and sets the Alarms with those times. If I boot the board, everything is ok, alarm starts at times read from EEPROM.
The issue is when I re-write those values while the software is running. If I change those values, the alarms won't trigger on the new times that were written on the EEPROM. I tried adding:
Code: [Select]
readEEPROM(0);         
    onH=rec;               
    readEEPROM(1);       
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);         
    offM=rec;

in void loop() so to have the values updated constantly but it seems that Alarms is stuck with the first values read at boot. Also adding alarms to loop didn't help.
Is there a way that the alarm times update in real time?

PaulS

Quote
But, if I dynamically change the EEPROM after the Arduino boot, then the alarms won't refresh.

How do you do this? How do you make the existing instances aware of this change?

Your readEEPROM() function should NOT be diddling with a global variable. It should be returning a value.
The art of getting good answers lies in asking good questions.

UKHeliBob

If you want to change the value used by an alarm that has already been set up you need to use the Alarm.write() method.

From the TimeAlarms readme
Quote
write(ID,  value);  -  write the value (and enable) the alarm for the given ID
The ID is created when the alarm is first set and can be found by setting the alarm like this
Code: [Select]
ID = Alarm.alarmRepeat(onH, onM, 0, LightsOn);

You may also be able to do what you want by disabling the alarm and setting it again.  See the readme for details.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Bob808

I use the write eeprom function from the LCD menu:

Code: [Select]
void writeEEPROM( unsigned int eeaddress, byte data)   //EEPROM write function
{
 Wire.beginTransmission(addr);
 Wire.write((int)(eeaddress >> 8));   // MSB
 Wire.write((int)(eeaddress & 0xFF)); // LSB
 Wire.write(data);
 Wire.endTransmission();
 delay(15);
}


And I read it with the read eeprom function:
Code: [Select]
void readEEPROM(unsigned int eeaddress)                //EEPROM read function
 {
 Wire.beginTransmission(addr);
 Wire.write((int)(eeaddress >> 8));
 Wire.write((int)(eeaddress & 0xFF));
 Wire.endTransmission();
 Wire.requestFrom(addr, 1);
 rec=Wire.read();
 }


And I store that into a variable that is used by Alarms.

Code: [Select]
readEEPROM(0);          
   onH=rec;                
   readEEPROM(1);        
   onM=rec;                
   readEEPROM(2);        
   offH=rec;
   readEEPROM(3);        
   offM=rec;
    Alarm.alarmRepeat(onH, onM, 0, LightsOn);
    Alarm.alarmRepeat(offH, offM, 0, LightsOff);


My read function returns an int value.
So, I am re-writing those addresses on the EEPROM with the write function from the LCD menu, but those "new" values aren't reflected in Alarms. Alarms only reads that value at boot. And inserting Alarms into loop doesn't help either. That was the first thing I tried. Any suggestions ?
I want to automate this process, not having to initiate a newly set alarm by rebooting the Arduino. I guess I'm not asking for much. How can alarms be refreshed automatically during program time?

PaulS

Quote
My read function returns an int value.

No, it doesn't.

The write function takes an int address and a byte value. The read function takes an int address and stores a byte in a global variable. It is not clear from your snippets what type rec is, but the function does not return anything and it does not read an int.
The art of getting good answers lies in asking good questions.

Bob808

#275
Sep 16, 2014, 02:22 pm Last Edit: Sep 16, 2014, 02:24 pm by Bob808 Reason: 1
rec is declared as byte.
My read write functions work, I checked in serial monitor with Serial.print(onH) etc. Aaaaand! My Alarms fire at time IF I reboot the Arduino. So, my read write functions do their job very good.
How else would the alarms fire at the exact time that is written (previous to reboot) by me, from LCD menu, with the write function on eeprom? the alarm times are written successfully by the write funtion on the eeprom, then the read function puts those times into alarm. I have checked that the times are written to EEPROM with serial.print, then the alarms fire on the times written on the EEPROM at reboot, they do work ok. the problem is, if I change those times on the EEPROM while the program is running, the alarms don't refresh. how can I do that? :)

//edit:
If you have a 24LC256 eeprom please test my code to see that it works. why would I lie?


@UKHeliBob
I will look into it, thx

PaulS

Quote
why would I lie?

The statements you made were indeed incorrect. That is not the same, necessarily, as lying.
The art of getting good answers lies in asking good questions.

Bob808

Well, I said the functions work, that they write and read from the EEPROM, and that the alarms fire on those values, but only at reboot :)

Bob808

Forgot to add that onH,onM,offH,offM are declared as int.

PaulS

Quote
but only at reboot

Have you waited 24 hours to see if they fire again?

Have you showed us the code where you write new data to EEPROM? No.
Have you showed us code where you re-read that data? No.
Have you showed us code where you apply those values to the existing instances? No.
Have you showed us anything other than a snippet or two? No.
Can you reasonably expect help, then? No.
The art of getting good answers lies in asking good questions.

Bob808

You having a bad day?  :P

So,

I showed you where I read the data:

Code: [Select]
void setup () {
 
 
    readEEPROM(0);          //read eeprom for alarm hour;
    onH=rec;               
    readEEPROM(1);          //read eeprom for alarm minute;
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);         
    offM=rec;
   
    Alarm.alarmRepeat(onH, onM, 0, LightsOn);
    Alarm.alarmRepeat(offH, offM, 0, LightsOff);



Also I apply those values to Alarm.alarmRepeat. onH/onM/offH/offM are integers with values from the read function "readEEPROM". and those integers go to alarm command. So I showed you that.
What else do you want me to show you? If you are in the "know" why would you want the whole code? I explained the structure and gave plenty of info.
I DO expect help, seems that just not from you at the moment...

Code: [Select]
#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int addr = 0x52;
const int light = 7;
byte resethour,resetmin,rec;
int  onH,onM,offH,offM,address,t;;
static tmElements_t tm;
 


void setup () {
   
    Serial.begin(57600);
    Wire.begin();
    setSyncProvider(RTC.get);
     pinMode(light, OUTPUT);
     digitalWrite(light, LOW);

    writeEEPROM(0,14);      //manual alarm time input on eeprom. will be made from UI.
    writeEEPROM(1,0);      //
    writeEEPROM(2,14);      //
    writeEEPROM(3,17);      //




    readEEPROM(0);         
    onH=rec;               
    readEEPROM(1);         
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);       
    offM=rec;
     Alarm.alarmRepeat(onH, onM, 0, LightsOn);
     Alarm.alarmRepeat(offH, offM, 0, LightsOff);
    int resethour = hour();
    int resetminute = minute();
    if (onH < resethour && offH > resethour)
    {
      LightsOn();
    }
    else if (onH == resethour && onM <= resetminute)
    {
      if (offH == resethour && offM > resetminute)
       {
         LightsOn();
       }
     }
}
 
void loop () {
  Alarm.delay(1);
}

void LightsOn() {                         // Set Lights On
digitalWrite(light, HIGH);
    Serial.println("Lights On");
}



void LightsOff() {                         // Set Lights Off
digitalWrite(light, LOW);
   Serial.println("Lights Off"); 
}



void writeEEPROM( unsigned int eeaddress, byte data)   //EEPROM write function
{
  Wire.beginTransmission(addr);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(15);
}

void readEEPROM(unsigned int eeaddress)                //EEPROM read function
  {
  Wire.beginTransmission(addr);
  Wire.write((int)(eeaddress >> 8));
  Wire.write((int)(eeaddress & 0xFF));
  Wire.endTransmission();
  Wire.requestFrom(addr, 1);
  rec=Wire.read();
  }



More code, at beginning of Setup you see some eeprom write functions. Those were used at first phase of testing, but didn't know that I'd have these problems. As they were first written the immediately read and dumped into alarms. Now I have a different code that writes those values AFTER boot, and after the values from the EEPROM have been read by the read commands and dumped into alarms.

Bob808


Quote
but only at reboot

Have you waited 24 hours to see if they fire again?


You don't get it.
Alarms FIRE, but on the time read at boot, from the EEPROM.
They WILL fire again, but at those "old" times.
They do NOT fire on the times written to eeprom AFTER boot. They most definitely  fire on the times that were read from the eeprom at boot. That's for sure. I tested it. It's easy to understand.
I wanted to know how to update the alarm times after boot, after they got the times from the EEPROM with:
Code: [Select]
readEEPROM(0);         
    onH=rec;               
    readEEPROM(1);         
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);       
    offM=rec;


That bit of code is in setup(). That's read at startup, and it sets the alarm from the eeprom time.
Arduino Boot - read eeprom - set those values in the alarm function - alarm triggers at that time.
my problem:
Arduino Boot - read eeprom - set those valuies in alarm function (will call it "old time") - alarms will trigger at that time - me setting up new values in eeprom ( will call it "new time") - arduino does not fire on "new time", but fires on "old time".
My problem: how to reflect changes ("new time") in alarms function.

PaulS

Quote
You having a bad day?

Nope. Are you?

Quote
Also I apply those values to Alarm.alarmRepeat. onH/onM/offH/offM are integers with values from the read function "readEEPROM". and those integers go to alarm command. So I showed you that.

You do that in setup(), which runs ONCE. You do not read EEPROM anywhere else. You don't write to EEPROM anywhere other than setup(), either. So, it is not surprising that the times that the alarms happen never changes.

Quote
If you are in the "know" why would you want the whole code?

So that I can confirm that the statements you've made are true. They are not, since you never change the values in EEPROM except at bootup, and you never read the values except in setup().

Quote
Now I have a different code that writes those values AFTER boot, and after the values from the EEPROM have been read by the read commands and dumped into alarms.

But, you aren't going to share that code. I see. Good day.
The art of getting good answers lies in asking good questions.

Bob808

I tried adding the readeeprom in loop but there was no change. My lcd code uses a menu library, can't paste it as I'm not home anymore. That wouldn't help you.
What I'm saying is that even if I put :
readEEPROM(0);         
    onH=rec;               
    readEEPROM(1);         
    onM=rec;               
    readEEPROM(2);         
    offH=rec;
    readEEPROM(3);       
    offM=rec;

In loop, it doesn't make any changes. OnH etc get updated, alsrms does not update on those variables. I can serial.print from loop, i see the new values. Alarms does not reflect with those values.
So far you haven't said anything, you posted for nothing. If you don't know what it's all about, why post?
Or maybe you cannot understand, and that's fine, but don't waste my time with posts that tell me nothing.
UKHeliBob understood and offered an idea. You just post no content.
I am pretty sure most people who read what I said got the idea.
So, even if I read the values in loop, the alarm doesn't reflect them. And i know I should not put alarms in loop.

PaulS

Quote
OnH etc get updated, alsrms does not update on those variables.

Because the alarm time is not bound to the value in OnH. The VALUE in OnH is passed to the Alarm instance when the instance is created.

UKHeliBob explained what you need to do to update the existing instance(s) with the new data.

Quote
So far you haven't said anything, you posted for nothing. If you don't know what it's all about, why post?

I do know what it's all about, and how to solve your problem. I've been waiting to see if you were doing something wrong in the code, or simply making incorrect assumptions about what the code you have should be doing. You've finally posted enough information to confirm that it is the latter.

Quote
Or maybe you cannot understand, and that's fine, but don't waste my time with posts that tell me nothing.

You are the one wasting time not posting all the code that illustrates the problem you are having.

The art of getting good answers lies in asking good questions.

Go Up