Time and TimeAlarms Libraries – Ask here for help or suggestions

I didn't find this thread until after I already posted here:

I'm trying to figure out how Time handles the situation when millis() rolls over but I'm not getting it. I'd love a nudge in the right direction.

Cheers!

Hi,

I'm trying to use the Time library with arduino 1.0-beta4 for OSX (library is located at ~willem/Documents/Arduino/Libraries/Time) when I compile I get

UdpNtpClient_WE.cpp:1:18: error: Time.h: No such file or directory

I guess something has changed for IDE 1.0 (beta) .... who knows the solution ?

Cheers, Willem.

Hi all,

I'm using the time library for my home energy monitoring project. In this project, I count the pulses coming from my electricity, gas and water meter. I also read out a temp/humidity sensor (SHT15) located in my garage.
Each time a change in one of the "sensors" occurs (i.e pulse or value change from temp/humidity sensor) , a UDP message with a small XML string is sent to a monitoring system. Below is an example of such a message (when a value change occurs for the humidity sensor) :

<e>
<s id="6" vChMSRo="0" vChMS="1599330" vChDT="2011-09-15T10:06:01" val="487" />
</e>

Explanation :
id = sensor identification
vChMSRo = value change millis rollover (I count the number of times the millis() rolled over since start-up)
vChMS = number of milliseconds at which the value change occurred
vChDT = date/time at which the value change occurred
val = the actual value

And below is one for a pulse counter (I'm using interrupt service routines for counting pulses) :

<e>
<s id="1" pIDRo="0" pID="3" pStartMSRo="0" pStartMS="8162174" pStartDT="2011-09-15T11:55:27" pDurMS="138" pIntMS="0" state="0" />
</e>

Explanation :
id = sensor identification
pIDRo = number of times the pulse ID rolled over
pID = pulse ID
pStartMSRo = number of times the millis() rolled over at the time the pulse started
pStartMS = millis() value at the time the pulse started
pStartDT = date/time the pulse started
pDurMS = duration of the pulse in ms
pIntMS = interval between this pulse and the previous pulse (in ms)
state = current state of the pulse

The XML string contains - among other info - the date and time at which the event occurred.
For each (pulse) sensor, the date/time is stored in a time object.
For reporting, I'm using the following function to convert the time object to a date/time string :

char* XMLDateTime(time_t t)
{
   char chrDT[21];
   PString strDT(chrDT, sizeof(chrDT));
  
   strDT.print(year(t));
   strDT.print("-");
   if (month(t) < 10)
   {
      strDT.print("0");
   };
   strDT.print(month(t));
   strDT.print("-");
   if (day(t) < 10)
   {
      strDT.print("0");
   };
   strDT.print(day(t));
   strDT.print("T");
   if (hour(t) < 10)
   {
      strDT.print("0");
   };
   strDT.print(hour(t));
   strDT.print(":");
   if (minute(t) < 10)
   {
      strDT.print("0");
   };
   strDT.print(minute(t));
   strDT.print(":");
   if (second(t) < 10)
   {
      strDT.print("0");
   };
   strDT.print(second(t));
   strDT.print("Z");
   return chrDT;
}

The problem :
Very frequently I get crappy output in the date/time string part, like this :

<s id="5" vChMSRo="0" vChMS="8462268" vChDT="2011-09-15	!Ó" val="243" />
<s id="6" vChMSRo="0" vChMS="8433906" vChDT="2011-09!ÓS" val="507" />

It seems that sometimes a kind of buffer overflow occurs. Initially, I used the String object, but that made it even worse! (PString is a buffer overflow save string object).
Could you please check what could be the reason for this strange output?

Kind regards,

Bart.

willem4ever:
Hi,

I'm trying to use the Time library with arduino 1.0-beta4 for OSX (library is located at ~willem/Documents/Arduino/Libraries/Time) when I compile I get

UdpNtpClient_WE.cpp:1:18: error: Time.h: No such file or directory

I guess something has changed for IDE 1.0 (beta) .... who knows the solution ?

Cheers, Willem.

Here is an NTP code for Arduino 1.0:

/*
 * Time_NTP sketch
 * Example showing time sync to NTP time source
 *
 * This sketch uses the Time library
 * and the Arduino 1.0 Ethernet library
 */

#include <Time.h>
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUDP.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 44 }; // set this to a valid IP address (or use DHCP)

unsigned int localPort = 8888;      // local port to listen for UDP packets

IPAddress timeServer(192, 43, 244, 18); // time.nist.gov NTP server

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in first 48 bytes of message
byte packetBuffer[ NTP_PACKET_SIZE]; // buffer to hold incoming/outgoing packets

time_t prevDisplay = 0;    // when the digital clock was displayed

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  while(timeStatus()== timeNotSet)
     ; // wait until the time is set by the sync provider
}

void loop()
{
  if( now() != prevDisplay)   //update the display only if the time has changed
  {
    prevDisplay = now();
    digitalClockDisplay();
  }
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(dayStr(weekday()));
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(monthShortStr(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);
}

/*-------- NTP code ----------*/

unsigned long getNtpTime()
{
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);
  if ( Udp.parsePacket() ) { 
     Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read packet into buffer


     //the timestamp starts at byte 40, convert four bytes into a long integer
     unsigned long hi = word(packetBuffer[40], packetBuffer[41]);
     unsigned long low = word(packetBuffer[42], packetBuffer[43]);
     // this is NTP time (seconds since Jan 1 1900
     unsigned long secsSince1900 = hi << 16 | low;  
     // Unix time starts on Jan 1 1970
     const unsigned long seventyYears = 2208988800UL;     
     unsigned long epoch = secsSince1900 - seventyYears;  // subtract 70 years
     return epoch;
  }
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);  // set all bytes in the buffer to 0

  // Initialize values needed to form NTP request
  packetBuffer[0] = B11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum
  packetBuffer[2] = 6;     // Max Interval between messages in seconds
  packetBuffer[3] = 0xEC;  // Clock Precision
  // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
  packetBuffer[12]  = 49;  // four-byte reference ID identifying
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // send the packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}

tigro:
Hi all,

I'm using the time library for my home energy monitoring project.
The problem :
Very frequently I get crappy output in the date/time string part, like this :

It seems that sometimes a kind of buffer overflow occurs. Initially, I used the String object, but that made it even worse! (PString is a buffer overflow save string object).
Could you please check what could be the reason for this strange output?

Kind regards,

Bart.

Bart,
You can check if the problem is due to the chrDT buffer overflowing by testing with a hard coded string of the correct length for the date.
If you still have the problem this is probably not a Time library issue and if that is the case then best to move the discussion to a new thread.

hello there :slight_smile:

back from testing my code concerning a web enabled programmer you can try it here :

http://sprinkler.zapto.org/arduinoJqueryUI.html
user/password viknet/viknet

mem, there (as always I think) is two bug I had to correct in your library:
in the function updateNextTrigger,

I removed the check if next trigger is not yet in the future:
if the check is already in the future but you just changed the alarm to something else, the updatetrigger won't be effective immediately

I also change the write function to :

if(isAllocated(ID))
      {
        Alarm[ID].value = value;
        Alarm[ID].Mode.alarmType=period;    
        if (value!=dtINVALID_TIME)
          enable(ID); 
        else
          free(ID);
      }

because trying to set the alarm to 0 was leaving alarm in a strange state before.

all in all I am more and more convinced that 0 should be treated as a valid alarm value meaning 0:00:00 today, the main reason for that when setting an alarm to 24:00:00 (which currently work) if you read the value and apply the usual hour() minute() second() it reply 00:00:00 which is kind of wrong.

To avoid this I disabled the possibility to set an alarm at midnight : 00:00:00 and 24:00:00 are not valid time in my project :slight_smile:

Mem/Michael,
I wasn't 100% sure how to set the time, so much thanks for the code snippet/s :slight_smile:

  • Red

Hello
My name is Joe
I have made clock from this page "The TC18 – My IV-18 Based VFD Tube Clock – vonnieda.org" but it doesn't have alarm,so I would like to add it.
This is first time for me to do something with arduino,can someone add alarm part for clock sketch for me please.

Im attaching sketch file

Thanks

TC18.pde (23.1 KB)

I need to convert UTC time (from my LS00031 GPS unit) to local time (i.e +10.5 hours). Sure I could code this but I expect this has been done many times before. A pointer to existing code or library call would be much appreciated. TIA

Okay, it apears the GPS synch isn't working.

Looked like part of the sample code is not finished?

time_t gpsTimeSync(){
  //  returns time if avail from gps, else returns 0
  unsigned long fix_age = 0 ;
  gps.get_datetime(NULL, NULL, &fix_age);
  unsigned long time_since_last_fix;
  if(fix_age < 1000)
    return gpsTimeToArduinoTime(); // return time only if updated recently by gps  
  return 0;
}

Always returns False.

After commenting out a few lines...

time_t gpsTimeSync(){
  //  returns time if avail from gps, else returns 0
  unsigned long fix_age = 0 ;
  gps.get_datetime(NULL, NULL, &fix_age);
  //unsigned long time_since_last_fix;
  //if(fix_age < 1000)
    return gpsTimeToArduinoTime(); // return time only if updated recently by gps  
  //return 0;
}

Seems to work...took a while before I got a synch....?

This is covering the exact issue I'm dealing with. I commented out the same code around "fix_age" and had some success, but not as much as you ... have a look here: http://arduino.cc/forum/index.php/topic,81175.msg612786.html#msg612786

I figured "fix_age" wasn't working, so commented it out, but now I'm getting same time reported every time it starts (7:37:12 8 Jan 2000 from memory). I know the GPS is working as I've got another program that reads from it just fine, so I'm pretty sure the problem is in the way I'm using timeGPS, or with timeGPS itself.

I'd really like to nail this one ...!

PS: you say it took a while before you got synch ... can you estimate how long that was (a few secs, or mins or longer?)

Hi,

I am having a problem compiling a sketch in Arduino 1.0 that compiled and uploaded just fine in Arduino 23. Any suggestions on how I can fix these errors:

C:\Arduino\arduino-1.0\libraries\TimeAlarms\TimeAlarms.cpp:25:22: error: WProgram.h: No such file or directory
C:\Arduino\arduino-1.0\libraries\TimeAlarms\TimeAlarms.cpp: In member function 'void TimeAlarmsClass::delay(long unsigned int)':
C:\Arduino\arduino-1.0\libraries\TimeAlarms\TimeAlarms.cpp:256: error: 'millis' was not declared in this scope

Is anyone else having this trouble?

Thanks,
Jeff

you need to read through "Readme.txt" file on the downlaod opage for Arduino 1.0. It explains a few changes that you will need to make, such as replacing "Wprogram.h" with "Arduino.h" in you programs and any libraries using it.

There may be a new version of the library posted to correct the problem - look wherever you got it. If not, find the file C:\Arduino\arduino-1.0\libraries\TimeAlarms\TimeAlarms.cpp and open it with notepad. At line 25 you'll find the reference to Wprogram.h which you can change to Arduino.h and save.

Yes, thank you. That worked fine. Just change the reference from Wprogram.h to Arduino.h and all is well again.

Hi there,
I'm making a self watering system, that has a reed switch that indicates if the water level is low, a moisture sensor for the soil, and a battery voltmeter to let me know when I should recharge my batteries, and a relay to turn on the pump.
Here is what I want to do.

  • Blink the LED if my battery gets below 7 volts - it would be nice to check this every 5 minutes or so.
  • If the water level goes below a certain point, I also want the LED to blink - want to check the value while pumping water
  • If the moisture is < 900, start the pump for 5 seconds, wait 10 seconds, then check the moisture sensor. If it's still <900 continue until it isn't
  • I want to run this code every 3 days (don't want too much water going to my plant)

I've been trying to work with the Time library to do the following:

  • check battery level every 5 minutes
  • wait 10 seconds for another moisture reading before starting the pump again
  • Run the code after 36 hours

I've taken out the time code from the sketch because I wanted to show that this working how I want it, just not with respect to the time I'm looking for.

Just getting a little frustrated with all these times. Any help or suggestions would be greatly appreciated.

/*
 * Gardening Project v1.2
 * Combining the capacitive sensor, moisture sensor, pump and led indicator.
 * Reading how much water is in the container.
 * Reading how much moisture is in the ground.
 * Pumping water if moisture is dry.
 * LED
 * Red - low battery , blink
 
 */
#include <Bounce.h>
#include <Time.h>
#include <TimeAlarms.h>

#define LED 9  // LED on pin 9
#define SWITCH 10  // Defines the Reed switch on digital pin 10
int reed_val = 0;  // used to store the input of the reed switch
Bounce bouncer = Bounce( SWITCH,10 ); 

//  Volt monitoring
  int batteryPin = 1;
  float vout = 0;
  int value = 0;
  float R1 = 991;    // !! resistance of R1 !!
  float R2 = 995;     // !! resistance of R2 !!
  float vin = 0;

// Moisture Sensor
  int moistureSensor = 5;  // Sensor pin 5, other pin connected to GRN through a 10k resistor
  int moisture_val;  // Storing the current value of the Sensor pin
  int waterpump = 7;  // Initializing pin 7 for waterpump


void setup()  {
  Serial.begin(9600); 
  pinMode(SWITCH, INPUT);  // Defines the switch as an input
  digitalWrite(SWITCH, HIGH);
  pinMode(LED,OUTPUT);  // LED as an output
  pinMode(waterpump,OUTPUT);  // Setting waterpump to output
  digitalWrite(waterpump,LOW);  // waterpump off

  
}

void loop()  {
  
  analogReference(EXTERNAL);
  bouncer.update();
  int reed_val= bouncer.read();
  moisture_val = analogRead(moistureSensor);
  
  // Volt Monitoring
  value = analogRead(batteryPin);
  vout= (value * 5)/1024.0;  //voltage coming out of the voltage divider
  vin = vout / (R2/(R1+R2));  //voltage to display
 

  // Debugging with LCD
  Serial.print("V: ");  // Print out V:
  Serial.println(vin);  // This is where the number of volts are displayed
  Serial.print("M: ");
  Serial.println(moisture_val);
  Serial.print("Reed: ");
  Serial.print(reed_val);
  delay(100);

  if (vin < 7.0)  {
    digitalWrite(waterpump,LOW);
    digitalWrite(LED,HIGH);  // LED turns on
    delay(200);
    digitalWrite(LED,LOW);
    delay(200);
 }

// Reed Switch monitoring
 
  if (reed_val==HIGH)  {
    Serial.println("Fill Water");
    digitalWrite(waterpump,LOW);
    digitalWrite(LED,HIGH);
    delay(200);
    digitalWrite(LED,LOW);
    delay(200);
    
  }


  // Check whether input is LOW (switch closed)
  if (moisture_val < 900 && reed_val==LOW)  {
    Serial.println ("Turning on pump");   // Debugging or adding add to LCD
    digitalWrite(waterpump,HIGH);  // waterpump on
    delay(5000);
    
   
  }
  digitalWrite(waterpump,LOW);

  
  }

I don't see that you need the Time or TimeAlarm libraries at all.

What you want to do can be done with a pencil and paper (variables on the Arduino) and a watch/clock (the millis() function on the Arduino).

On each pass through loop, see if it is time to check the battery level. If it is, check the battery level, and set the lastChecked time to now.

See if it is time to turn the water on. If it is, turn the water on and set the lastWaterOn time to now.

Do the same for moisture reading.

The 3 day pause affects everything? The plant dries out and dies during that 3 days, and that's OK? The battery does dead in that 3 days, and that's OK?

If you turn the system off for 3 days (i.e. do nothing in that time) and then check the water level, and it is fine, so you turn off for three days again, it could take a long time before you check the battery level. So, be careful that you check everything before going into do-nothing-for-three days mode.

Frankly, I think you have some contradictory requirements, which might explain your difficulties implementing them.

Thanks for your help PaulS.

Are you suggesting not to use the Time library at all? Instead use millis() ?
One of the reasons I would like to use the Time library is due to the draw of mA. If I use the code without the Time library I'm drawing about 30mA, then when the relay turns on it uses up to 90mA.
If I'm counting using the Time library I seem to be only using 20mA while it's counting, then of course it uses the same 90mA when the relay kicks in.

My thought was that as long as I'm checking the battery every 5 minutes or so, if the battery drops below 7 volts, I will be notified by a blinking LED and go and charge it. Since this is outside of the 3 day pause, i would be notified at least within 5 minutes and not have to wait for a full 3 days before I found out.

The plant is a palm and it's winter...so I doubt the plant is going to completely dry out in 3 days, plus I figured this should save battery power. I can change the amount of time to check later if I find it drying out too fast. I understand what you're saying about checking every three days, perhaps I should start with every day to check.

Battery check - every 5 minutes
Waterlevel check - once every day
Moisture check - once every day

Cheers

So, you want the Time library to wake the Arduino every 5 minutes

Check the battery level and increment a counter for the number of times the timer has disturbed your sleep.

If the battery voltage is low, stay awake, blinking the LED.

If the counter hits some value, check for the need for water. If it needs watering, stay awake and water the plant. Reset the counter when done.

Go back to sleep. Repeat when the timer goes off again.

Watering the plant should be completed in 5 minutes, so go back to sleep at the 5 minute mark, to get back on the 5 minute sleep/wake cycle.

Yes , I want to wake the Arduino every 5 minutes to check the battery and water level.
Not sure what you mean about incrementing a counter for the number of times the timer has disturbed you sleep?
Yes, stay awake and blink the LED if the voltage is low.
Wake the Arduino every 24 hours and check if the moisture value is below 900 (900 is wet soil). If it needs watering, turn on pump for 5 seconds, then wait 5 seconds before reading the value again. If it needs watering, turn on pump for another 5 seconds, then wait 5 seconds before reading value again. Continue this procedure until the value is above 900.

Thanks again, I appreciate the help.