wakeup in PinChange interrupt

Hi!

i've got an couple of buttons which i don't want to poll so i created an event with the pcint of pin change interrupt.
After that i want to let the arduino sleep... and it will sleep! it sleeps to long because when i push a button i won't wake up :frowning:

anyone suggestions?

Martijn from the Netherlands :smiley:

anyone suggestions?

Post your code?

Sleep code is at the bottom

#include <LiquidCrystal.h>
#include "pins_arduino.h"
#include <avr/sleep.h>

char strMenu1[] = "Accu 1";
char strMenu2[] = "Accu 2";
char strMenu3[] = "Water";
char strMenu4[] = "Afval";
char* strucMenu[] = { strMenu1,strMenu2,strMenu3,strMenu4 };
int menu;

// RS // Enable // D4,5,6,7
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

volatile uint8_t *port_to_pcmask[] = {
  &PCMSK0,
  &PCMSK1,
  &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = { 
  NULL };

volatile static uint8_t PCintLast[3];

/*
 * attach an interrupt to a specific pin using pin change interrupts.
 * First version only supports CHANGE mode.
 */
 void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  uint8_t slot;
  volatile uint8_t *pcmask;

  if (mode != CHANGE) {
    return;
  }
  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  } 
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }
  slot = port * 8 + (pin % 8);
  PCintFunc[slot] = userFunc;
  // set the mask
  *pcmask |= bit;
  // enable the interrupt
  PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *pcmask;

  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  } 
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }

  // disable the mask.
  *pcmask &= ~bit;
  // if that's the last one, disable the interrupt.
  if (*pcmask == 0) {
    PCICR &= ~(0x01 << port);
  }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
  uint8_t bit;
  uint8_t curr;
  uint8_t mask;
  uint8_t pin;

  // get the pin states for the indicated port.
  curr = *portInputRegister(port+2);
  mask = curr ^ PCintLast[port];
  PCintLast[port] = curr;
  // mask is pins that have changed. screen out non pcint pins.
  if ((mask &= *port_to_pcmask[port]) == 0) {
    return;
  }
  // mask is pcint pins that have changed.
  for (uint8_t i=0; i < 8; i++) {
    bit = 0x01 << i;
    if (bit & mask) {
      pin = port * 8 + i;
      if (PCintFunc[pin] != NULL) {
        PCintFunc[pin]();
      }
    }
  }
}


SIGNAL(PCINT0_vect) {
  PCint(0);
}
SIGNAL(PCINT1_vect) {
  PCint(1);
}
SIGNAL(PCINT2_vect) {
  PCint(2);
}

void setup()
{
  lcd.begin(8,2);
  pinMode(11,INPUT);
  pinMode(12,INPUT);
  pinMode(13,INPUT);
  digitalWrite(11,HIGH);
  digitalWrite(12,HIGH);
  digitalWrite(13,HIGH);
  lcd.print("boot");
  PCattachInterrupt(11, e, CHANGE);
  PCattachInterrupt(12, t, CHANGE);
  PCattachInterrupt(13, d, CHANGE);   
}

void e()
{
  if(digitalRead(11) == LOW)
  {
    menu--;
    lcd.clear();
    lcd.print(menu);
    fnMenu();
  }
}
  
void t()
  {
    if(digitalRead(12) == LOW)
    {
      menu++;
      lcd.clear();
      lcd.print(menu);
      fnMenu();
    }
  }
  
void d()
  {
    if(digitalRead(13) == LOW)
    {
      lcd.clear();
      lcd.print("Read...");
      fnMenu();
    }
  }

void fnMenu()
{
  if(menu <= 0)
  {
   menu = 0; 
  }
  if(menu >= 4)
  {
   menu = 4; 
  }
  lcd.clear();
  lcd.print(strucMenu[menu]);
  set_sleep_mode(SLEEP_MODE_STANDBY); // sleep mode is set here
  sleep_enable();
  sleep_mode();                        // System sleeps here
  sleep_disable();  
}

void loop()
{


}

That's not a very good start to debug a wake-up problem - there's too much stuff that has absolutely nothing to do with wake-up interrupts.
Cut down your program to the bare minimum to set up the switch inputs, wake up conditions, and use Serial debug prints.

that's true idd...

but i was wondering IF the arduino can wakeup from this interrupt... the datasheet of the atmel chip is to !@#@$#%$#$@# :D:D:D

i'm cutting down the code... ::slight_smile:

a normal interrupt wakes the arduino up... pcint until now not...