[Solved]-How to let PIR triggered & sent notification at specific time period

Hi,

I am still struggling for "trigger at specific time period" , need help, please.

The following 3 items are all O.K.

  1. PIR works perfect.
  2. Get NTP time without any problem.
  3. Send message to Twitter without any problem.

Now I want PIR only detected & triggered during 22:00~05:00 everyday, please kindly help.

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <time.h>

int pirPin = D4;
int val;

char auth[] = "Blynk Token";
char ssid[] = "ssid";
char pass[] = "password";
int pirValue; // Place to store read PIR Value

int timezone = 8;
int dst = 0;

BlynkTimer timer;

void setup()
{
Serial.begin(115200);
Serial.setDebugOutput(true);
Blynk.begin(auth, ssid, pass);
pinMode(pirPin, INPUT);

configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov", "time.windows.com");
Serial.println("\nWaiting for time");
while (!time(nullptr)) {
Serial.print(".");
delay(3000);
}
Serial.println("");
}

void loop()
{
time_t now = time(nullptr);
Serial.println(ctime(&now));
delay(1000);

if (current time >=22 && current time <= 5) // <-- Need help for the time comparison

{
val = digitalRead(pirPin);
//low = no motion, high = motion
if (val == HIGH)
{
Serial.println("Motion detected");
long uptime = millis() / 60000L;
Blynk.tweet(String("Alert!Danger!Motion Detected!") + uptime + " \n @TwitterUserName");
}
else
{
Serial.println("No motion");
}
}
}
Blynk.run();
timer.run();
delay(1000);
}

if (current time >=22 && current time <= 5) // <-- Need help for the time comparison

You need the current hour and minute of the time to compare. You print the time using the ctime() function which returns a nice string with everything in it from the 'now' you get from this line:

time_t now = time(nullptr);

'now' is internally represented in seconds and, according to the Time.h header file:

This implementation uses an unsigned 32 bit integer offset from Midnight Jan 1 2000

so there's a function (gmtime_r) which converts number-of-seconds since 2000 into a 'tm' structure which contains:

    /**
        The tm structure contains a representation of time 'broken down' into components of the
        Gregorian calendar.

        The value of tm_isdst is zero if Daylight Saving Time is not in effect, and is negative if
        the information is not available.

        When Daylight Saving Time is in effect, the value represents the number of
        seconds the clock is advanced.

        See the set_dst() function for more information about Daylight Saving.

    */
    struct tm {
        int8_t          tm_sec; /**< seconds after the minute - [ 0 to 59 ] */
        int8_t          tm_min; /**< minutes after the hour - [ 0 to 59 ] */
        int8_t          tm_hour; /**< hours since midnight - [ 0 to 23 ] */
        int8_t          tm_mday; /**< day of the month - [ 1 to 31 ] */
        int8_t          tm_wday; /**< days since Sunday - [ 0 to 6 ] */
        int8_t          tm_mon; /**< months since January - [ 0 to 11 ] */
        int16_t         tm_year; /**< years since 1900 */
        int16_t         tm_yday; /**< days since January 1 - [ 0 to 365 ] */
        int16_t         tm_isdst; /**< Daylight Saving Time flag */
    };

So, in your code, instead of Serial.println(ctime(&now)); you can do:

  struct tm timeParts;
  gmtime_r(&now, &timeParts);
  Serial.print( timeParts.tm_hour ); Serial.print(":");
  Serial.print( timeParts.tm_min );  Serial.print(".");
  Serial.println( timeParts.tm_sec );

...so now you can use timeParts.tm_hour and timeParts.tm_min in your if() statement.

Yours,
TonyWilk

What number is greater than or equal to 22 AND less than or equal to 5? - Scotty

if (current time >=22 && current time <= 5)  // <-- Need help for the time comparison

I think you want:

if (hour() >=22 || hour() < 5)  // 22:00 through 23:59  || Midnight (0:00) through 4:59

All,

Thank you very much for taking good care of this case, I appreciated it.

I got the error below, could you please kindly help checking them out again?

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <time.h> /* time_t, struct tm, time, gmtime */

int pirPin = D4;
int val;

char auth[] = "Blynk Token";
char ssid[] = "ssid";
char pass[] = "password";
int pirValue; // Place to store read PIR Value

int timezone = 8;
int dst = 0;

BlynkTimer timer;

void setup()
{
Serial.begin(115200);
Serial.setDebugOutput(true);
Blynk.begin(auth, ssid, pass);
pinMode(pirPin, INPUT);

configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov", "time.windows.com");
Serial.println("\nWaiting for time");
while (!time(nullptr)) {
Serial.print(".");
delay(3000);
}
Serial.println("");
}

void loop()
{
time_t now = time(nullptr);

struct tm timeParts;
gmtime_r(&now, &timeParts);
Serial.print( timeParts.tm_hour ); Serial.print(":");
Serial.print( timeParts.tm_min ); Serial.print(".");
Serial.println( timeParts.tm_sec );

delay(1000);

if (timeParts.tm_hour >= 22 || timeParts.tm_hour < 5) // 22:00 through 23:59 || Midnight (0:00) through 4:59
{
val = digitalRead(pirPin);
//low = no motion, high = motion
if (val == HIGH)
{
Serial.println("Motion Detected");
long uptime = millis() / 60000L;
Blynk.tweet(String("Alert!Danger!Motion Detected!") + uptime + " \n @TwitterUserName");
}
else
{
Serial.println("No Motion");
}
}
}
Blynk.run();
timer.run();
delay(1000);
}


Blynk_ESP8266_PIR_Clock_Twitter:63: error: expected unqualified-id before '{' token
{
^
exit status 1
expected unqualified-id before '{' token

It's a confusing error message for a simple thing...

... check all your pairs of { and } brackets (hint: it's near the end).

Yours,
TonyWilk

Oops, silly me, I made a mistake, I removed the bracket, see below, please.

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <time.h>
#define gmtime_r <-------------- 2. I added that.

int pirPin = D4;

...................
.........................

else
{
Serial.println("No Motion");
}
}
} <-------------- 1. I removed that, and then it's O.K. but I got the error that related to undefined 'gmtime_r', see error message on the bottom, I have no idea about that, thus, I put #define gmtime_r on the top, then it's O.K. to upload the code to ESP8266, then got another issue, the time always shows 0:0.0

0:0.0
No Motion

0:0.0
No Motion

...

Looks like the time wasn't converted successfully, is there something missing in the time convert?
Tony, Please kindly advise again, thank you very much.

Blynk.run();
timer.run();

C:\Arduno\Blynk_ESP8266_PIR_Clock/Blynk_ESP8266_PIR_Clock.ino:29: undefined reference to `gmtime_r'

collect2.exe: error: ld returned 1 exit status

exit status 1

Hmmm, gtime_r should be defined in time.h

This line is just defining gtime_r as nothing, so remove it:

#define gmtime_r

and compile the code.

If you get an error, Post the code (preferably click the </> in the message editor and paste your code between code tags) and whatever error has happened.

Yours,
TonyWilk

Thanks again, here is the sketch,

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <time.h>

int pirPin = D4;
int val;

char auth[] = "Blynk Token";
char ssid[] = "ssid";
char pass[] = "password";
int pirValue; // Place to store read PIR Value

int timezone = 8;
int dst = 0;

BlynkTimer timer;

void setup()
{
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Blynk.begin(auth, ssid, pass);
  pinMode(pirPin, INPUT);

  configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov", "time.windows.com");
  Serial.println("\nWaiting for time");
  while (!time(nullptr)) {
    Serial.print(".");
    delay(3000);
  }

  Serial.println("");
}

void loop()
{
  time_t now = time(nullptr);

  struct tm timeParts;
  gmtime_r(&now, &timeParts);
  Serial.print( timeParts.tm_hour ); Serial.print(":");
  Serial.print( timeParts.tm_min );  Serial.print(".");
  Serial.println( timeParts.tm_sec );

  delay(1000);

  if (timeParts.tm_hour >= 22 || timeParts.tm_hour < 5)   // 22:00 through 23:59  || Midnight (0:00) through 4:59
  {
    val = digitalRead(pirPin);
    //low = no motion, high = motion
    if (val == HIGH)
    {
      Serial.println("Motion Detected");
      long uptime = millis() / 60000L;
      Blynk.tweet(String("Warning!Danger!") + uptime + " \n @TwitterUsername");
    }
    else
    {
      Serial.println("No Motion");
    }
  }

  Blynk.run();
  timer.run();
  delay(1000);
}

Error Message

Arduino: 1.8.5 (Windows 7), Board: "NodeMCU 1.0 (ESP-12E Module), 80 MHz, 115200, 4M (3M SPIFFS)"

Archiving built core (caching) in: C:\Users\zephyr\AppData\Local\Temp\arduino_cache_675032\core\core_esp8266_esp8266_nodemcuv2_CpuFrequency_80,UploadSpeed_115200,FlashSize_4M3M_28f73eb30973fdb5d307d594ef7382dc.a
sketch\Blynk_ESP8266_PIR_Clock_Twitter.ino.cpp.o: In function `setup':

C:\Users\zephyr\Documents\Arduino\Blynk_ESP8266_PIR_Clock_Twitter/Blynk_ESP8266_PIR_Clock_Twitter.ino:29: undefined reference to `gmtime_r'

C:\Users\zephyr\Documents\Arduino\Blynk_ESP8266_PIR_Clock_Twitter/Blynk_ESP8266_PIR_Clock_Twitter.ino:33: undefined reference to `gmtime_r'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board NodeMCU 1.0 (ESP-12E Module).

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Well, that's a bit odd. Nice posting of the code and error message by the way :slight_smile:

I downloaded those libraries and selected board "NodeMCO 1.0 (ESP-12E Module)" and got the same error!

It seems like they didn't implement that particular function for this board, however they did implement localtime() so you should be able to replace:

// replace this
// gmtime_r(&now, &timeParts);

// with this:
timeParts = * localtime(&now);

Then cross your fingers and compile it ....

Yours,
TonyWilk

Hi Tony,

You are really an expert! It works perfect! Fantastic & Sweet! This must be the best Christmas gift for me, I really appreciate your instruction, big thanks and

Merry Christmas ^.^

TonyWilk:
Well, that's a bit odd. Nice posting of the code and error message by the way :slight_smile:

I downloaded those libraries and selected board "NodeMCO 1.0 (ESP-12E Module)" and got the same error!

It seems like they didn't implement that particular function for this board, however they did implement localtime() so you should be able to replace:

// replace this

// gmtime_r(&now, &timeParts);

// with this:
timeParts = * localtime(&now);




Then cross your fingers and compile it ....

Yours,
TonyWilk

Thanks, still, you put 99% of it together.

Well done and a Merry Christmas to you too!

Yours,
TonyWilk

Hi Tony, ladies and gentlemen,

It's me again, the PIR with time start/stop function works perfect, no issue, but the PIR hardware limitation cause lots of false alarm, I could not sleep well, my eyes look like panda, help me again, please.

Google the PIR's weakness, I understood the wind, temperature and light cause false alarm frequently, thus, my idea is,

If motion detected consecutive 5 times , then sent notification to my smart phone.

For example,

Motion Detected
Motion Detected
Motion Detected
No Motion

It won't send notification to me.

Motion Detected
Motion Detected
Motion Detected
Motion Detected
Motion Detected

It sends notification to me.

Thank you very much for any help you can provide.

If motion detected consecutive 5 times

How far apart are those 5 "consecutive" times? 10 nanoseconds? 10 days?

Thanks for reply, for my case, output one result per second, so

No Motion
<1 sec.>
No Motion
<1 sec.>
No Motion
<1 sec.>
No Motion
<1 sec.>
No Motion
.
.
.
.

You read the PIR sensor. If it is HIGH, you increment a variable, initialized to 0. If it is LOW, you set the variable to 0.

Then, you check the value of the variable. If the value is 5 or more, there has been motion for 5 seconds, so you send the tweet.

Hi Paul,

Sorry to get back to you so late, I had fun during the long holiday.

Based on your hints, I will focus on the following items,

  1. Increment a variable --> counter++
  2. Initialized to 0 --> I have no idea yet.
  3. Set the variable to 0 --> Assuming it's count=0
  4. Check the value of the variable --> if (counter >= 5)

Thank you so much for your help, I will study more Arduino language and then try fixing above issue.

  1. Initialized to 0 --> I have no idea yet.
int counter = 0; // Initial value is not 22
  1. Set the variable to 0 --> Assuming it's count=0

With a semicolon on the end...

Hi PaulS,

Big thanks again, I got it, I will do some research in the case.