RTC Vs DateTime

Hello Arduino Community!

We’re currently working on a final project for school by designing a motion detection alarm system using 2 PIR sensors

So far the sensors are working fine thanks to

PIRsense by Kristian Gohlke

We would like to implement time stamping on events, and for the last couple days I’ve been struggling trying to get DateTime working in my code

Would we be better off going with an external RTC or working through and getting DateTime working?

any tips/tricks would be more than appreciated

thank you!

:-/

I would be happy to help you get DateTime working with your code if you describe the nature of the problem.

ok

pretty much the problem is the only examples I can find are what come with the library when you download it. which on their own work fine, but as soon as i try to bring it into my sensor program errors come about. they range from not declaring errors to function errors.

to be honest i just don’t understand the library at all lol

just need to break the tipping point :-[

If you post your sketch with a brief explanation of what you want it to do I can probably help you get it going

i will get that ready and post it later on today

thank you

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)

int calibrationTime = 60;       

//the time when the sensor outputs a low impulse

long unsigned int lowIn;        
long unsigned int lowIn2;  

//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped

/////////////////////////////
//Sensor A
long unsigned int pause = 5000;

boolean lockLow = true;
boolean takeLowTime; 

/////////////////////////////
//Sensor B

boolean lockLow2 = true;
boolean takeLowTime2;

/////////////////////////////
//Sensor A
int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 12;   //Extra LED

/////////////////////////////
//Sensor B
int pirPinB = 2;    //the digital pin connected to the PIR sensor's output
int ledPinB = 11;   //On Board LED

/////////////////////////////
//SETUP

void setup(){
  Serial.begin(9600);

/////////////////////////////
//Sensor A

  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

/////////////////////////////
//Sensor B

  pinMode(pirPinB, INPUT);
  pinMode(ledPinB, OUTPUT);
  digitalWrite(pirPinB, LOW);
 
  //give the sensor some time to calibrate
  Serial.print("Calibrating PIR Sensors A & B | 60 Seconds ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print("*");
    delay(1000);
  }

  Serial.println(" Finished");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

////////////////////////////
//LOOP
void loop(){

    if(digitalRead(pirPin) == HIGH){
    digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
    if(lockLow){ 
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow = false;           
      Serial.println("---");
      Serial.print("motion detected on sensor A at ");
      Serial.print(millis()/1000);
      Serial.println(" sec");
      delay(50);

  }
 
    takeLowTime = true;

  }

    
  if(digitalRead(pirPin) == LOW){      
    digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

    if(takeLowTime){
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause,
    //we assume that no more motion is going to happen
    if(!lockLow && millis() - lowIn > pause){ 
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow = true;                       
      Serial.print("motion ended on sensor A at ");      //output
      Serial.print((millis() - pause)/1000);
      Serial.println(" sec");
      delay(50);
    }
  }
 
  /////////////////////////////////
  //Sensor B
 
  if(digitalRead(pirPinB) == HIGH){
    digitalWrite(ledPinB, HIGH);   //the led visualizes the sensors output pin state
    if(lockLow2){ 
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow2 = false;           
      Serial.println("---");
      Serial.print("motion detected on sensor B at ");
      Serial.print(millis()/1000);
      Serial.println(" sec");
      delay(50);
    }        
    takeLowTime2 = true;
  }

  if(digitalRead(pirPinB) == LOW){      
    digitalWrite(ledPinB, LOW);  //the led visualizes the sensors output pin state

    if(takeLowTime2){
      lowIn2 = millis();          //save the time of the transition from high to LOW
      takeLowTime2 = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause,
    //we assume that no more motion is going to happen
    if(!lockLow2 && millis() - lowIn2 > pause){ 
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow2 = true;                       
      Serial.print("motion ended on sensor B at ");      //output
      Serial.print((millis() - pause)/1000);
      Serial.println(" sec");
      delay(50);
    }
  }
 
 
 
}

here is some sample output

Calibrating PIR Sensors A & B | 60 Seconds ************************************************************ Finished

SENSOR ACTIVE


motion detected on sensor A at 60 sec


motion detected on sensor B at 60 sec

motion ended on sensor B at 67 sec


motion detected on sensor B at 74 sec

motion ended on sensor B at 76 sec

motion ended on sensor A at 77 sec


motion detected on sensor A at 89 sec


motion detected on sensor B at 89 sec

motion ended on sensor B at 92 sec

motion ended on sensor A at 95 sec

what we would like to achieve is instead of having it say

motion detected on sensor A at 60 sec

motion ended on sensor A at 77 sec

have the output say

motion detected on sensor A at 1:22:30 PM [DATE if Possible]

motion ended on sensor A at 1:22:44 PM [DATE if Possible]

thanks!

It will be easy to add the code to display the date and time, but to do that we need to set the date and time in the Arduino. How are you displayin the serial output on the PC?

If you want, I can help you adapt the Processing application that is included with the DateTime Library so it will synchronize the arduino time to the PC time and also display the data from your sensors.

How are you displayin the serial output on the PC?

0012 Alpha and the serial monitor

i would definitely appreciate any tips or directions, i’ve been through the SetArduinoClock.pde and DateTime.pde a few times :-[ and can’t get it working with the above code

No problem, I will post something in the morning.

Here is your sketch modified to work with the DateTime library. If you run the SetArduinoClock Processing sketch supplied in the DateTime download you can click the window to set the time. You should see the serial output in the Processing serial monitor. Note the default baud rate is 19200 so I have changed the Arduino setup to match.

If the time is not synchronized then the clock will start at midnight Jan 1 2009.
Also note that the Processing sketch defaults to using the first com port on you PC, you may need to change the portIndex variable in the Processing sketch if your arduino is connected to a different port.

#include <DateTime.h>
#include <DateTimeStrings.h>
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  255   // Header tag for serial time sync message

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)

int calibrationTime = 60;      

//the time when the sensor outputs a low impulse

long unsigned int lowIn;        
long unsigned int lowIn2;  

//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped

/////////////////////////////
//Sensor A
long unsigned int pause = 5000; 

boolean lockLow = true;
boolean takeLowTime;

/////////////////////////////
//Sensor B

boolean lockLow2 = true;
boolean takeLowTime2;

/////////////////////////////
//Sensor A
int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 12;   //Extra LED

/////////////////////////////
//Sensor B
int pirPinB = 2;    //the digital pin connected to the PIR sensor's output
int ledPinB = 11;   //On Board LED

/////////////////////////////
//SETUP

void setup(){
  Serial.begin(19200); // changed to 19200 to match the baud rate of the Processing sketch
  DateTime.sync(1230768000); // set Jan 1 2009 as the default time

  /////////////////////////////
  //Sensor A

  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  /////////////////////////////
  //Sensor B

  pinMode(pirPinB, INPUT);
  pinMode(ledPinB, OUTPUT);
  digitalWrite(pirPinB, LOW);

  //give the sensor some time to calibrate
  Serial.print("Calibrating PIR Sensors A & B | 60 Seconds ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print("*");
    delay(1000); 
  }

  Serial.println(" Finished");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

////////////////////////////
//LOOP
void loop(){
  getPCtime(); // set the time if a time sync message is available on the serial port

  if(digitalRead(pirPin) == HIGH){
    digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
    if(lockLow){
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow = false;          
      Serial.println("---");
      printEvent("Sensor A", "Motion detected", DateTime.now());
      delay(50);
    }
    takeLowTime = true;
  }


  if(digitalRead(pirPin) == LOW){      
    digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

    if(takeLowTime){
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause,
    //we assume that no more motion is going to happen
    if(!lockLow && millis() - lowIn > pause ){
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow = true;                      
      printEvent("Sensor A", "Motion ended", DateTime.now() - pause/1000);
      delay(50);
    }
  }

  /////////////////////////////////
  //Sensor B

  if(digitalRead(pirPinB) == HIGH){
    digitalWrite(ledPinB, HIGH);   //the led visualizes the sensors output pin state
    if(lockLow2){
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow2 = false;          
      Serial.println("---");
      printEvent("Sensor B", "Motion detected", DateTime.now());
      delay(50);
    }        
    takeLowTime2 = true;
  }

  if(digitalRead(pirPinB) == LOW){      
    digitalWrite(ledPinB, LOW);  //the led visualizes the sensors output pin state

    if(takeLowTime2){
      lowIn2 = millis();          //save the time of the transition from high to LOW
      takeLowTime2 = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause,
    //we assume that no more motion is going to happen
    if(!lockLow2 && millis() - lowIn2 > pause){
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow2 = true;                      
      printEvent("Sensor B", "Motion ended", DateTime.now() - pause/1000);
      delay(50);
    }
  }
}

void printEvent(char * sensorStr, char * eventStr, time_t time){
  Serial.print(eventStr);      
  Serial.print(" on ");
  Serial.print(sensorStr);      
  Serial.print(" at ");      //output
  printTimeDate(time);
  Serial.println();  
}

void printTimeDate(time_t time){
  byte sec,min,hour,hr,day,wday,month,year;

  DateTime.localTime(&time,&sec,&min,&hour,&day,&wday,&month,&year);
  // the following converts 24 hour time to 12 hour time 
  if( hour == 0 )
    hr = 12; // 12 midnight
  else if( hour  > 12)
    hr = hour - 12 ;
  else
    hr = hour ;

  Serial.print(hr,DEC);
  printDigits(min);
  printDigits(sec);
  Serial.print(" ");  
  Serial.print( hour < 12 ? "AM" : "PM");  
  Serial.print(" ");
  Serial.print(day,DEC); 
  Serial.print(" ");
  Serial.print(DateTimeStrings.monthStr(month));
  Serial.print(" ");
  Serial.print(year + 1900,DEC);   
}

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

boolean getPCtime() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    if( Serial.read() == TIME_HEADER ) {        
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        char c= Serial.read();          
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      }   
      DateTime.sync(pctime);   // Sync Arduino clock to the time received on the serial port
      Serial.print("Clock set at ");
      printTimeDate(DateTime.now());      
      return true;   // return true if time message received on the serial port
    }  
  }
  return false;  //if no message return false
}

a test run produced this output:

Clock set at 11:56:29 AM 9 February 2009

Motion detected on Sensor A at 11:56:34 AM 9 February 2009
Motion ended on Sensor A at 11:56:39 AM 9 February 2009

I thought it may be helpful to modify your sketch to make it easier to enhance. The following version creates a sensor class and that makes it simple to add sensors.

#include <DateTime.h>
#include <DateTimeStrings.h>
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  255   // Header tag for serial time sync message

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)

int calibrationTime = 60;      
int pause = 5; //the time when the sensor outputs a low impulse, this is now in seconds

class SensorClass
{
private:
  char sensorID;
  byte pirPin;  
  byte ledPin;
  boolean lockLow; // flag to indicate the sensor has gone low
  boolean takeLowTime;
  time_t lowIn; //the time the sensor transitioned from high to low
public:
  SensorClass(byte, byte, byte );
  void begin();
  void checkMotionDetected();
  void checkMotionEnded();
};

SensorClass SensorA('A',3,12);  // sensor A on pin 3, led on pin 12
SensorClass SensorB('B',2,13);  // sensor B on pin 2, led on pin 13

/////////////////////////////
//SETUP

void setup(){
  Serial.begin(19200); // changed to 19200 to match the baud rate of the Processing sketch
  DateTime.sync(1230768000); // set jan 1 2009 as the default time

  SensorA.begin(); //Sensor A 
  SensorB.begin(); // Sensor B

  //give the sensor some time to calibrate
  Serial.print("Calibrating PIR Sensors A & B | 60 Seconds ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print("*");
    delay(10); // !!todo  was 1000;
  }

  Serial.println(" Finished");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

////////////////////////////
//LOOP
void loop(){
  getPCtime(); // set the time if a time sync message is available on the serial port

  SensorA.checkMotionDetected();
  SensorA.checkMotionEnded();
  SensorB.checkMotionDetected();
  SensorB.checkMotionEnded();
 
}

////////////////////////////
// routines to output to the serial port

void printEvent(char sensorID, char * eventStr, time_t time){
  Serial.print(eventStr);      
  Serial.print(" on ");
  Serial.print("Sensor ");
  Serial.print(sensorID);      
  Serial.print(" at ");      //output
  printTimeDate(time);
  Serial.println();  
}

void printTimeDate(time_t time){
  byte sec,min,hour,hr,day,wday,month,year;

  DateTime.localTime(&time,&sec,&min,&hour,&day,&wday,&month,&year);
  // the following converts 24 hour time to 12 hour time 
  if( hour == 0 )
    hr = 12; // 12 midnight
  else if( hour  > 12)
    hr = hour - 12 ;
  else
    hr = hour ;

  Serial.print(hr,DEC);
  printDigits(min);
  printDigits(sec);
  Serial.print(" ");  
  Serial.print( hour < 12 ? "AM" : "PM");  
  Serial.print(" ");
  Serial.print(day,DEC); 
  Serial.print(" ");
  Serial.print(DateTimeStrings.monthStr(month));
  Serial.print(" ");
  Serial.print(year + 1900,DEC);   
}

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

boolean getPCtime() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    if( Serial.read() == TIME_HEADER ) {        
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        char c= Serial.read();          
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number    
        }
      }   
      DateTime.sync(pctime);   // Sync Arduino clock to the time received on the serial port
      Serial.print("Clock set at ");
      printTimeDate(DateTime.now());      
      return true;   // return true if time message received on the serial port
    }  
  }
  return false;  //if no message return false
}

////////////////////////////
/// sensor class 

SensorClass::SensorClass(byte ID, byte pirpin, byte ledpin ){
  this->sensorID = ID;
  this->pirPin = pirpin;  
  this->ledPin = ledpin;
  this-> lockLow = true;
}

void SensorClass::begin(){
  pinMode(this->pirPin, INPUT);
  pinMode(this->ledPin, OUTPUT);
  digitalWrite(this.pirPin, LOW);
}

void SensorClass::checkMotionDetected(){
  if(digitalRead(this->pirPin) == HIGH){
    digitalWrite(this->ledPin, HIGH);   //the led visualizes the sensors output pin state
    if(this->lockLow){
      //makes sure we wait for a transition to LOW before any further output is made:
      this->lockLow = false;          
      Serial.println("---");
      printEvent(this->sensorID, "Motion detected", DateTime.now());
      delay(50);
    }
    this->takeLowTime = true;
  }
}

void SensorClass::checkMotionEnded(){
  if(digitalRead(this->pirPin) == LOW){      
    digitalWrite(this->ledPin, LOW);  //the led visualizes the sensors output pin state

    if(this->takeLowTime){
      this->lowIn = DateTime.now();       //save the time of the transition from high to LOW
      this->takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause, we assume that no more motion is going to happen
    if(!(this->lockLow) && DateTime.now() - this->lowIn > pause){
      //makes sure this block of code is only executed again after a new motion sequence has been detected
      this->lockLow = true;                      
      printEvent(this->sensorID, "Motion ended", DateTime.now() - pause);
      delay(50);
    }
  }
}

can’t wait to get home tonight and try this out :o ;D :o ;D

I will report back

damn you make it seem to easy, that’s spot on! thanks mem

Motion detected on Sensor B at 12:01:02 AM 1 January 2009


Motion detected on Sensor A at 12:01:02 AM 1 January 2009

Motion ended on Sensor A at 12:01:07 AM 1 January 2009

Motion ended on Sensor B at 12:01:07 AM 1 January 2009


Good to know you have it going.

I was curious as to hear about your initial difficulty with the DateTime library. Any suggestions on how the library and/or documentation could be improved so that it would be easier to understand and use?

i would say the over all issue was my rusty programming “skills” its been over a year since I’ve had to tackle microcontroller interfacing and the placement of what goes in void setup and void loop confused me, espically since i was getting nowhere by trial and error

Any suggestions for additional comments/changes to make the example sketch easier to understand would be appreciated by those yet to pick up and use the library.