INPUT_PULLUP in combination with sleep and interrupt on WKP pin

I’m trying out to use a toggle switch to wake up the Photon from sleep. The toggle switch uses an internal pullup.

I use the CHANGE interrupt because my program should react whatever state of the button (LOW to HIGH, HIGH to LOW).

I also attach an interrupt to the button, because I’d like to make my system go asleep on a press. However the pin seems to start floating (when not attached to ground), this should be prevented by the INPUT_PULLUP.

I’m just wondering if internal pullup doesn’t work well in combination with sleep or interrupts in general. The combination seems to give a problem at least. I have no problem adding a pull-down / up resistor externally, but I’m just wondering is this is normal behaviour.

My code:

What is the right forum etiquette? Is it better to include code over here directly or to use an external service like gist for this kind of scripts?

That depends on the length of the code. A couple of screen pages should be fine as long you wrap your code in a set of these

 ```cpp
 // your code
For more, a gist link or any other similar service is fine.

For your original question, you need to be aware that `System.sleep()` (with pin interrupt to wake) will attach their own internal pull-resistors according to the respective wake edge - for CHANGE this means ***no*** internal pull-resistor and this will override your `pinMode()`.
For that reason I'd put these two lines ***after*** the sleep instruction.

```cpp
  pinMode(WKP, INPUT_PULLUP);
  attachInterrupt(WKP, buttonPress, CHANGE);

Or you use an external pull-resistor and go for INPUT instead of INPUT_PULLUP.
BTW, since deep sleep needs a rising edge to wake, using an external pull-down and closing to 3.3V would keep that avenue open for you too.

For your particular case where you only want to sleep once at the end of setup() you could also go this (rather hacky) way

void setup() {
  ...
  pinMode(WKP, INPUT_PULLUP);
  System.sleep(WKP, digitalRead(WKP) ? FALLING : RISING); 

  pinMode(WKP, INPUT_PULLUP);
  attachInterrupt(WKP, buttonPress, CHANGE);
}
1 Like

Thanks! This case was just my first test case, so I won’t use sleep in the end of setup() in general.

Just for my understanding what is the benefit of using:
System.sleep(WKP, digitalRead(WKP) ? FALLING : RISING);
instead of:
System.sleep(WKP, CHANGE);

Is it not the same?

The obvious answer is it can’t be the same otherwise it would implicitly mean that FALLING, RISING and CHANGE would be the same too - but we know they aren’t.

But the more elaborate answer is:
My version first checks the current state of your button and then chooses the opposite level to trigger the wake with.
And in combination with the knowledge that a the desired trigger causes the system to select the corresponding pull-resistor for sleep() like this

FALLING   PULL-UP
RISING    PULL-DOWN
CHANGE    NONE

we know that the internal pull resistors will help us to actually get that level.
(if your switch closes to HIGH it has to be 3.3V and not 5V to avoid GPIO damage)

1 Like

On second thought I’d go with an external pull-up and CHANGE after all.

But there was discussion that a way of selecting dedicated pull-resistors for the wake-pin would be desirable.

I was thinking to use an external pull-down, because of the rising edge needed when in deep sleep. Don’t know if I use it (stop mode is pretty low power as well, since I run on a power supply).

Or does a pull-up has other benefits over pull-down?

Sorry, sure - forgot I did argue for that before myself :blush:

1 Like