Sleep with wakeup pin weirdness on Electron

We’ve been using the sleep with several wakeup pins call for months now. But I’ve just struck some weirdness that’s not in the docs.

  1. I set D4 to pullup: pinMode(D4, INPUT_PULLUP);
  2. It correctly interrupts when connected to GND
  3. I sleep (standby) with Electron set to wake on D4 and other pins
  4. Connecting D4 to GND does not wake the Electron
  5. Connecting D4 to 3V3 does wake the Electron
  6. Now that it’s awake again D4 still only fires when connected to 3V3

So it appears we can’t wake on a pin that needs a built-in pullup resistor, and if we do it’s pull up/down state is reset. Is this expected? If so it should really be documented.

One more piece of weirdness with the wake pins. We have been using D5 as a (pulldown) wake input for months out in the field with no issues. But I’ve just noticed while researching the above problem that D5 is not listed as a supported pin for external interrupt when waking from standby: But it definitely works. Am I OK using this?

This is with DeviceOS 1.1.0.

pinMode() has no influence on the wake pin.
When calling System.sleep() the designated edge for the wake sets the internal pull-resistors ensuring the un-triggered level (RISING = pull-down, FALLING = pull-up and CHANGE = no internal pull).

So to properly advise, we’d need to see your System.sleep() call.

Why are you looking at the (now outdated) pre-release docs?
I’d rather look here

However, the statement about possible wake pins hasn’t been adapted for the Electron and still only lists the Photon pins - @rickkas7?

1 Like

Thanks again @ScruffR. You’re exactly right. Using FALLING edge both wakes and keeps a working pullup input.

Wouldn’t it make more sense then that edge was not specified to System.sleep and it figured it out from the previously set pin mode? Otherwise it’s easy to fall into the trap I did. Or at least this should be documented.

Ah, would you believe I’ve had that link open in my browser since 0.8.0 was RC :slight_smile:

And if anyone wants to have a play here’s the test app I put together to try this out:

#include <Particle.h>


static const pin_t pin = D4;
static const PinMode mode = INPUT_PULLUP;
static const InterruptMode edge = FALLING;

static SerialLogHandler logHandler(LOG_LEVEL_INFO);

static volatile int counter = 0;

void isr() {

void setup() {
  pinMode(pin, mode);
  attachInterrupt(pin, isr, edge);

void loop() {
  for (int i = 0; i < 10; i++) {
    counter = 0;
    Particle.process();"Count: %d", counter);
  delay(100);  // Wait for serial to flush
  counter = 0;
  System.sleep(pin, edge, 5);
  delay(3000);  // Wait for serial to reconnect"Awake");

Agreed, the exact behaviour should be documented but I’d not rely on the user to set the correct pinMode().
However, I have (in the past) suggested an optional “override” flag for System.sleep() which disable the automatism and allow the user to specify (e.g. via pinMode()) the desired mode (especially to allow disabling the internal pull for all edge triggers when they are not needed due to external circuitry).

@rickkas7, could you add this to the documentation?
I have also noticed this in multiple places in these docs :wink:

We only have three constants documented - what am I missing? :confused:

1 Like