Photon interrupt pin high upon wakeup from interrupt or timeout

I’ve built a little motion detector/weather combination sensor using a PIR motion sensor, a Particle Photon, and a BME280 temperature, atmospheric pressure, humidity sensor and a log-linear light sensor. I have it programmed and working. I want it to report the sensors every ten minutes. I also want it to report motion plus the sensors when motion is detected. I want it to save energy and sleep in stop mode otherwise. I am using System.sleep(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds), like this

SYSTEM_MODE(SEMI_AUTOMATIC);
...
System.sleep(PIR, RISING, 600);  //Sleep for x seconds or till PIR HIGH

So it wakes up every ten minutes, or wakes up when there is motion, as expected.
QUESTION 1: How can the program detect and display whether it woke up because of movement or because of the time elapsed? I have this section below that reads the pin upon wakeup, it’s part of my boolean sensor class:

bool boolSensor::measure_Detected() { // measure if there is activity detected
    _detected = digitalRead(_pin);
    delay(10);
    _detected = digitalRead(_pin);
    return _detected;
}

I have it reading twice, with a debouncing step, which didn’t help.

THE PROBLEM: no matter what, the interrupt pin (A5 in my case) reads HIGH when the Photon is woken up by time OR by the PIR signal. I think this is expected, can someone confirm? I didn’t expect that the timeout was using the pin to wake up the Photon. I expected the pin to read LOW when waking from timing out.

QUESTION 2: So what’s a way to sleep in stop mode and wake up on either an external interrupt (3V signal from PIR) or on a timer, AND be able to distinguish which of the two (time or ext. interrupt) was the cause for wake up? Use a Real Time Clock to measure the time between interrupts to look for an expected 10 minutes wait? Isn’t there another more bullet-proof way than comparing time elapsed to time expected to elapse?

Cheers and thanks for your consideration.

That question has been asked before and the usual answer is - as you already stated - check the time.

Another possible way is to add a sample’n’hold circuitry for the PIR trigger to keep the signal stored long enough for the device to wake and read the pin.

My PIR motion detector holds the signal for ~ 30 seconds, as per my setting. If I make sure the Photon has woken from it’s sleep (I may need to increase the on time) and published an event within the time period that the PIR is on (say 30 secs), are you suggesting the following?

SYSTEM_MODE(SEMI_AUTOMATIC);
...
System.sleep(PIR, RISING, 600);  //Sleep for x seconds or till PIR HIGH
digitalWrite(_pin, LOW);
_detected = digitalRead(_pin);
if (_detected == HIGH) {do stuff when motion detected}; // if == HIGH then PIR motion detected
else {do stuff meant for timed intervals}; //if == LOW then Photon woke on timer not on motion

I don’t know why I couldn’t find this timer external interrupt topic answered in prior posts.
Thanks again.

If you use SYSTEM_THREAD(ENABLED) in conjunction with SYSTEM_MODE(SEMI_AUTOMATIC) your Photon should be ready to digitalRead() the PIR pin in less than a second.

Why would you do digitalWrite(_pin, LOW) as first action after wake and not immediately digitalRead(PIR) to catch the state of the interrupt pin when this is held HIGH for 30sec?
If it was HIGH, then you have been woken by an interrupt, if it’s not, it’s most likely due to a timed wake.

Also what do you expect to get as result from that?

digitalWrite(_pin, LOW);
_detected = digitalRead(_pin);

How would you ever read anything else from _pin than LOW? :confused:


Some related threads (search term “wake pin time”)
Electron Detect Wakeup from Pin Vs. Timer
Photon WKP Pin Interupt Flag Question