Is it possible attachInterrupt for 11 pin?

hi

I know this is possible manually.
but can I somehow in arduino
attachInterrupt for digitalPinToInterrupt(11)

PS: NANO

No only pins 2 & 3 have pin change interrupts on a nano
See the Reference

For UNO and Nano, attachinterrupt() is only available on pin#2 and pin#3.

only pin 2 and 3 have External Interrupt support
all the 20 signal pins can be used as interrupt pins if you go for pin change interrupts

But as other stated, you can't use attachinterrupt(). There are many online tutorials for pin change interrupts, here is a first google hit (did not read it)

1 Like

Tools->Manage libraries...
Search for "PinChangeInterrupt"

That library will let you use Pin Change interrupts much like External interrupts.

See the documentation here:

1 Like

J-M-L, johnwasser, please help me to figure out my mistake
in the following code I want to print the pin number (which fired interrupt)
but always get 0

int ledPin = 13;                // LED
int PIR = 3;                 // PIR Out pin
int pirStat = 0;                   // PIR status
int flag = 0;
int KEYVAL = 0;
int PBLAST = 0;

void setup() {

  DDRB = 0; PORTB = 0;
  cli();
  PCICR |= (1 << PCIE0); // Enables Ports B as Pin Change Interrupts
  PCMSK0 |= (1 << PCINT7) | (1 << PCINT6) | (1 << PCINT5); // PCINT0
  sei();

  pinMode(ledPin, OUTPUT);
  Serial.begin(19200);
}
void loop() {

  if (flag) {
    char PBNOW = PINB ^ PBLAST;
    switch (PBNOW) {
      case (1 << PB7):
        KEYVAL = 11;
        break;
      case (1 << PB6):
        KEYVAL = 10;
        break;
      case (1 << PB5):
        KEYVAL = 9;
        break;
      default:
        break;
    }
    flag = 0;
    Serial.println(millis());
    digitalWrite(ledPin, HIGH);  // turn LED ON
    delay(4000);
    digitalWrite(ledPin, LOW); // turn LED OFF if we have no motion
    Serial.println(KEYVAL); // HERE should be pin
KEYVAL = 0;
    PBLAST = PINB;
    PCMSK0 |= (1 << PCINT7) | (1 << PCINT6) | (1 << PCINT5);
  }

}

ISR(PCINT0_vect)
{
  PCMSK0 = 0;
  flag++;
}


which pins are you targeting?

KEYVAL starts with the value 0 and only changes if exactly one of the PORTB pins has changed.

Try masking off the unused pins before the XOR. That won't help if two pins change before you handle the interrupt.

WARNING! Pin 9 is PB1, Pin 10 is PB2, and Pin 11 is PB3. You are using PB5, PB6, and PB7 for some reason. PB7 is not connected to an Arduino UNO/Nano pin.

If you want to keep track of which pin or pins triggered interrupts, you should probably do that in the ISR.

volatile byte Rising = 0;
volatile byte Falling = 0;
volatile byte Changed = 0;

ISR(PCINT0_vect)
{
  static byte oldState = 0;
  byte newState = PINB;
  changed = oldState ^ newState;
  Rising|= newState & changed;
  Falling |= (~newState) & changed;  // TYPO: had 'Changed'
  Changed |= changed;
  oldState = newState;  // EDIT: Forgot this line!
}

Then in loop() you can grab the data an report:

void loop()
{
  noInterrupts();
  byte changed = Changed;
  byte rising = Rising;
  byte falling = Falling;
  Changed = 0;
  Rising = 0;
  Falling = 0;
  interrupts();

   if (rising & _BV(PB1)) // Pin 9
   {
      Serial.print(millis());
      Serial.println(" Pin 9 RISING")
   }
   if (falling & _BV(PB1)) // Pin 9
   {
      Serial.print(millis());
      Serial.println(" Pin 9 FALLING")
   }

   if (rising & _BV(PB2)) // Pin 10
   {
      Serial.print(millis());
      Serial.println(" Pin 10 RISING")
   }
   if (falling & _BV(PB2)) // Pin 10
   {
      Serial.print(millis());
      Serial.println(" Pin 10 FALLING")
   }

   if (rising & _BV(PB3)) // Pin 11
   {
      Serial.print(millis());
      Serial.println(" Pin 11 RISING")
   }
   if (falling & _BV(PB3)) // Pin 11
   {
      Serial.print(millis());
      Serial.println(" Pin 911FALLING")
   }
}
1 Like

I have connected PB5..PB7 to PCINT
when interrupt is triggered I want to print respective pin.

I tested little bit now and looks like pin 9 and pin 10 is printing correct to serial...
only instead 11, I see in the serial 0

cant understand why 11 is not printing

why |= ? maintaining the changed status if not dealt with in loop?

sorry, pb5-pb7 for micro board....

Yes. I figured the main program would want to know that a pin had changed even if it wasn't changed in the latest interrupt.

OK makes sense

So when you put "PS: NANO" in your original post that should have been "PS: Micro"?

in original was nano, now on my desktop micro (I know micro has only one port for pcint and nano - 3) sorry. but issue not in port's name

cannt understand why PB6 is printing and PB7 not :\

now , I found one more issue, if arduino goes to sleep, and when wake up from PCINT then

PBNOW 

is not contain current triggered pin :frowning: always prints 0 even for PB6

to avoid confusing all I 'll open new topic

This sketch works on my UNO and can be switched between UNO and Micro.

#if 1 // 1 for Arduino Micro, 0 for UNO or Nano
const byte Mask11 = _BV(PCINT7);
const byte Mask10 = _BV(PCINT6);
const byte Mask9 = _BV(PCINT5);
#else
const byte Mask11 = _BV(PCINT3);
const byte Mask10 = _BV(PCINT2);
const byte Mask9 = _BV(PCINT1);
#endif

volatile byte Rising = 0;
volatile byte Falling = 0;
volatile byte Changed = 0;

ISR(PCINT0_vect)
{
  static byte oldState = 0;
  byte newState = PINB;
  byte changed = oldState ^ newState;
  Rising |= newState & changed;
  Falling |= (~newState) & changed;
  Changed |= changed;
  oldState = newState;
}

void setup()
{
  Serial.begin(115200);
  delay(200);

  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);

  noInterrupts();
  PCICR |= _BV(PCIE0); // Enables Ports B as Pin Change Interrupts
  PCMSK0 = Mask11 | Mask10 | Mask9;
  PCIFR = _BV(PCIF0);
  interrupts();
}

void loop()
{
  noInterrupts();
  // byte changed = Changed;
  byte rising  = Rising;
  byte falling = Falling;
  Changed = 0;
  Rising  = 0;
  Falling = 0;
  interrupts();

  if (rising & Mask9) // Pin 9
  {
    Serial.print(millis());
    Serial.println(" Pin 9 RISING");
  }
  if (falling & Mask9) // Pin 9
  {
    Serial.print(millis());
    Serial.println(" Pin 9 FALLING");
  }

  if (rising & Mask10) // Pin 10
  {
    Serial.print(millis());
    Serial.println(" Pin 10 RISING");
  }
  if (falling & Mask10) // Pin 10
  {
    Serial.print(millis());
    Serial.println(" Pin 10 FALLING");
  }

  if (rising & Mask11) // Pin 11
  {
    Serial.print(millis());
    Serial.println(" Pin 11 RISING");
  }
  if (falling & Mask11) // Pin 11
  {
    Serial.print(millis());
    Serial.println(" Pin 11 FALLING");
  }
}

I think this is not enough real case... for example for my interrupt (from PIR sensor) level changed for 2 (or more - can be tuned) seconds (HI) then it self returns to initial it state (LOW). so only HI level meaning that it triggered. and many sensors works in this mode
so ... when it HI your ISR will trigger and this is line stores HI level to oldState, after 2 seconds level became LOW your ISR will trigger again , it will think that now falling state...

but I understand its not error in the code just one of many cases how it could be implemented/worked

thanks for helping

(now will try to execute your code from this and second topics)

why we storing something in Changed if in the loop it always is zero ?

I tried this code on micro

17079 Pin 11 RISING
19745 Pin 11 FALLING
36873 Pin 11 RISING
39826 Pin 11 FALLING

so Im confused :\ why in your code pin 11 is reading in my - no :slight_smile:

pin 10 reads in both ( my and your)
hm...

That is how 'Pin Change' interrupts work. They interrupt when the state of a pin changes. If you don't care about the pin Falling, don't check the pin's Falling flag.

It isn't always zero. It just isn't used. I'm looking at the Rising and Falling flags so I don't need the Changed flags.

Maybe you have made some coding mistake? Maybe there is a fault in the "deepSleep" library?

1 Like