30 minute simple Timer event

Hi all,
Any help greatly appreciated.

On a Leonardo, I am running this sketch and I have a PIR connected to Pin 7 that gives a 'CTRL' keypress when activated, on the connected PC to wake the screen.
I also want to wake the screen every 30 minutes regardless.
Would someone kindly explain exactly what I need to write to achieve this. My head is literally spinning from reading all about interrupts, delays, registers etc. I'm sure it won't be very complicated but I am stuck.
Many thanks

#include <Keyboard.h>

// use this option for OSX:
char ctrlKey = KEY_LEFT_GUI;
// use this option for Windows and Linux:
//  char ctrlKey = KEY_LEFT_CTRL;

void setup() {
  // make pin 7 an input:
  pinMode(7, INPUT);
  // initialize control over the keyboard:
  Keyboard.begin();
}

void loop() {
  while (digitalRead(7) == LOW) {
    // do nothing until pin 2 goes HIGH
    delay(500);
  }
  delay(1000);
  // new document:
  Keyboard.press(ctrlKey);
  delay(100);
  Keyboard.releaseAll();
  
  delay(1000);
}

maybe something like that (typed here, fully untested)

#include <Keyboard.h>
const byte pirPin = 7;
const char ctrlKey = KEY_LEFT_GUI;
const unsigned long thirtyMinute = 1800000ul; // 30 min x 60 seconds per minute x 1000 milliseconds per second

unsigned long lastWakeUp;
bool pirIsIdle = true;

void sendWakeUpWhenNeeded(bool forced = false) {
  if (forced || (millis() - lastWakeUp >= thirtyMinute)) {
    Keyboard.press(ctrlKey);
    delay(100);
    Keyboard.releaseAll();
    lastWakeUp = millis();
  }
}

void setup() {
  pinMode(pirPin, INPUT);
  Keyboard.begin();
}

void loop() {
  // handle PIR
  if (pirIsIdle) {                                     // if PIR was not triggered yet
    if (digitalRead(pirPin) == HIGH) {                 // check if PIR got activated
      sendWakeUpWhenNeeded(true);                      // it did, force-send the command 
      pirIsIdle = false;                               // and remember PIR got activated
    } else {                                           // the PIR had been activated, 
      pirIsIdle = (digitalRead(pirPin) == LOW);        // wait for the PIR to go back to LOW 
    }
  }

  // handle time based wake-up
  sendWakeUpWhenNeeded();
}
1 Like

Many thanks, I will try it. I must admit it looks more complicated than I had imagined!
Thanks again for your help.

the only "complicated" part you might not have anticipated is the fact that you probably don't want to send the ctrlKey continually whilst the PIR is triggered (they usually stay active for a few seconds or minutes). so you need something that tells the code "I've already sent the notification for this PIR event, I won't send another one until it went back to rest."

I could have separated the code for the PIR and the code for the timer but it sounds easier to group sending the key when needed in one function.

1 Like

Thank you.
For testing purposes, is it as simple as just changing 'thirtyMinute' value to something smaller? Doing that won't alter anything else?

yes, that's why I made that a constant, easy to change at the top of the program

1 Like

So it almost works. Set the timer for 15 seconds and left it running for a bit. CTRL every 15 seconds as it should. About 7 seconds after a timed event, activated PIR and instant CTRL command. Timer kicked back in for every 15 seconds. PIR then stopped activating but timer ok. Reloaded original basic PIR program and proved PIR itself still functioning correctly. Uploaded timer program and did exactly the same. PIR stopped working after first activation but timer carried on functioning correctly. I've tried to read the code to see if I could understand why but beyond me.
Last time I wrote any code was approx. 1981 in school computer club on a ZX81!
I appreciated your time already but would you have any ideas?
Kindest regards

How long does your PIR stay on once activated?

1 Like

I've set it at the lowest at around 0.3 seconds.

so what's exactly the incorrect behavior?

1 Like

It seems that once the PIR has been activated for the first time from boot up, it stops passing any further 'high' signals to the Arduino. The timer does carry on working correctly.

can you run this

const byte pirPin = 7;
bool pirIsIdle = true;

void setup() {
  pinMode(pirPin, INPUT);
  Serial.begin(115200); Serial.println();
}

void loop() {
  if (pirIsIdle) {                                     // if PIR was not triggered yet
    if (digitalRead(pirPin) == HIGH) {                 // check if PIR got activated
      Serial.println("PIR IS ACTIVATED");
      pirIsIdle = false;                               // and remember PIR got activated
    } else {                                           // the PIR had been activated,
      pirIsIdle = (digitalRead(pirPin) == LOW);        // wait for the PIR to go back to LOW
      if (pirIsIdle) Serial.println("PIR IS DEACTIVATED");
    }
  }
}

an open the Serial monitor at 115200 bauds
you should see messages each time the PIR is activated and deactivated

does it work?

1 Like

Thanks, I'll try that and let you know.

So as soon as I open serial monitor, it scrolls at a rate of knots (deactivated). As soon as I activate the PIR, the scrolling stops, PIR activated comes up and then it all stops. No further PIR activation has any output to the serial monitor.
Thanks again

18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS DEACTIVATED
18:25:17.080 -> PIR IS ACTIVATED

sorry I messed up the brackets typing on my phone

can you try this

const byte pirPin = 7;
bool pirIsIdle = true;

void setup() {
  pinMode(pirPin, INPUT);
  Serial.begin(115200); Serial.println();
}

void loop() {
  if (pirIsIdle) {                                     // if PIR was not triggered yet
    if (digitalRead(pirPin) == HIGH) {                 // check if PIR got activated
      Serial.println("PIR IS ACTIVATED");
      pirIsIdle = false;                               // and remember PIR got activated
    }
  } else {                                           // the PIR had been activated,
    pirIsIdle = (digitalRead(pirPin) == LOW);        // wait for the PIR to go back to LOW
    if (pirIsIdle) Serial.println("PIR IS DEACTIVATED");
  }
}

and if that works (showing PIR status) then just set the {} right in the previous code

#include <Keyboard.h>
const byte pirPin = 7;
const char ctrlKey = KEY_LEFT_GUI;
const unsigned long thirtyMinute = 1800000ul; // 30 min x 60 seconds per minute x 1000 milliseconds per second

unsigned long lastWakeUp;
bool pirIsIdle = true;

void sendWakeUpWhenNeeded(bool forced = false) {
  if (forced || (millis() - lastWakeUp >= thirtyMinute)) {
    Keyboard.press(ctrlKey);
    delay(100);
    Keyboard.releaseAll();
    lastWakeUp = millis();
  }
}

void setup() {
  pinMode(pirPin, INPUT);
  Keyboard.begin();
}

void loop() {
  // handle PIR
  if (pirIsIdle) {                                     // if PIR was not triggered yet
    if (digitalRead(pirPin) == HIGH) {                 // check if PIR got activated
      sendWakeUpWhenNeeded(true);                      // it did, force-send the command
      pirIsIdle = false;                               // and remember PIR got activated
    }
  } else {                                           // the PIR had been activated,
    pirIsIdle = (digitalRead(pirPin) == LOW);        // wait for the PIR to go back to LOW
  }

  // handle time based wake-up
  sendWakeUpWhenNeeded();
}
1 Like

Thank you so much, that did it.
You are a legend and I applaud you.
Thanks for sticking with it and using your valuable time.
I am now going to try and decipher the code and try and understand it.

most important part indeed !

have fun

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.