flip sensor state to wake sleeping mcu via interrupt pin

I see that only LOW state interrupts in SLEEP_MODE_PWR_DOWN can successfully wake the mcu. I have a sensor that outputs HIGH when something happens, what is the simplest solution to flip states?

Perhaps, invert it with a transistor.

There was a recent thread where we discovered that any transition woke the CPU. You could try it and see if it worked. (It isn’t supposed to).

The other, simpler and more reliable, way is to use a pin-change interrupt. They are documented to work when the processor is asleep.

Perhaps, invert it with a transistor.

I tried a transistor last night (100k to gnd at sensor, sensor to 100k to base, collector to arduino d3, collector to 100k to 5v+ and emitter to gnd) but it didn’t work as expected. I used a 2222.

There was a recent thread where we discovered that any transition woke the CPU. You could try it and see if it worked. (It isn’t supposed to).

It didn’t for me. I implemented pin change interrupts as explained on your site but the mcu doesn’t wake up. My code follows below.

#include <avr/sleep.h>

#define pinPIR       3 // digital pin 3
#define pinLEDR      6 // digital pin 6

int testInterrupts = 0; // change to 1 to test interrupts on pin d3 (doesn't wake)

volatile int sleepState = 0;  // default device is powered (just a placeholder for now)

void setup()
{  
  tone(pinSpeaker, 700, 100); 
   
  pinMode(pinPIR, INPUT);
        
  analogWrite(pinLEDR,1);
  
  // wait for first sensor init (LOW when ready)
  while (true)
  {
    if (digitalRead(pinPIR)==LOW)
      break;
  }
  
  // blink ready
  for (int a=0;a<3;a++)
  {
    analogWrite(pinLEDR,1);
    delay(150);
    analogWrite(pinLEDR,0);
    delay(150);
  }
  
  if (testInterrupts==1)
  {
    // pin change setup
    PCMSK2 |= _BV (PCINT19);  // want pin d3
    PCIFR  |= _BV (PCIF2);   // clear any outstanding interrupts
    PCICR  |= _BV (PCIE2);   // enable pin change interrupts for d0 to d7
  }
}

ISR (PCINT2_vect)
{
 // pin change interrupt for D0 to D7 here
}

void loop()
{
  
  if (testInterrupts == 0)
  {
    // this non-interrupt loop works properly with the sensor
    while (true)
    {      
      if (digitalRead(3)==HIGH)
      {
        // sensor change
        sleepState=0;
        tone(pinSpeaker, 600, 50);
        digitalWrite(pinLEDR, HIGH);
        delay(5000);
      } else
        {
          // sensor no change
          if (sleepState != 1)
            tone(pinSpeaker, 300, 50);
          
          sleepState=1;
          digitalWrite(pinLEDR, LOW);
          delay(250);
        }
    }
  } // (testInterrupts == 0)
  else
  {
    // interrupt driven
    while (true)
    {
      sleepState=1;
      tone(pinSpeaker, 300, 50);
      delay(100);
      digitalWrite(pinLEDR, LOW);

      set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
      sleep_mode ();
      
      // doesn't wake up here
      tone(pinSpeaker, 600, 50);
      sleepState=0;
      digitalWrite(pinLEDR, HIGH);
      delay(5000);
    }
  } // (testInterrupts == 1)
  
}

Link us to the sensor.

Link us to the sensor.

j514:
I implemented pin change interrupts as explained on your site but the mcu doesn’t wake up. My code follows below.

I modified your code to get the relevant parts. That is, does the pin change interrupt work or not? It does using this code:

#include <avr/sleep.h>

#define pinPIR       3 // digital pin 3
#define pinLEDR      13 

volatile int sleepState = 0;  // default device is powered (just a placeholder for now)

void setup()
{  
  pinMode (pinPIR, INPUT_PULLUP);
  pinMode (pinLEDR, OUTPUT);

  // pin change setup
  PCMSK2 = _BV (PCINT19);  // want pin d3
  PCICR  = _BV (PCIE2);   // enable pin change interrupts for d0 to d7
}

ISR (PCINT2_vect)
{
  // pin change interrupt for D0 to D7 here
  sleepState = 0;
}

void loop()
{
  sleepState=1;
  delay(100);
  digitalWrite(pinLEDR, LOW);

  PCIFR  = _BV (PCIF2);   // clear any outstanding interrupts
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_mode ();

  // flash LED 5 atimes
  for (byte i = 0; i < 5; i++)
    {
    digitalWrite (pinLEDR, HIGH);
    delay (500);
    digitalWrite (pinLEDR, LOW);
    delay (500);
    }
    
}

The LED (13) flashes 5 times when you ground pin 3, and another 5 times when you un-ground it, and so on. So it works on either falling or rising.

That is, does the pin change interrupt work or not? It does using this code:

I tried it, but no luck on my stock Mega 2560r2 and homebrew mega 2560. The sketch I posted shows that the sensor returns HIGH and LOW properly (and as expected with motion) when the testInterrupts variable is 0 though. Any other ideas? TIA

Not all Mega pins support pin change interrupts. You need to find ones that do.

Aha! The PinChangeInt library was able to get it going on pin 13, I don't know what its doing different.

Thanks for your help just the same.

The transistor wired up as a NOT gate will work..

If that was too much for you, buy a NOT gate ic... to flip the bit state.