I have an arduino uno and want to react to three sensors, which should trigger an ISR.

I wrote the following program, and for sensor 3 it works, however the other two sensor don't seem to trigger an interrupt. I checked the sensors by connected each one to pin A5, and every sensor worked.

Is there a better way to check which pin caused the interrupt than digitalRead()? Is this maybe even my problem?

#define pinDrehen 12
#define pinRevDrehen 13

volatile boolean triggeredAngleSensor1 = false;
volatile boolean triggeredAngleSensor2 = false;
volatile boolean triggeredAngleSensor3 = false;
volatile unsigned int triggeredTimeAngleSensor1;
volatile unsigned int triggeredTimeAngleSensor2;
volatile unsigned int triggeredTimeAngleSensor3;

ISR (PCINT1_vect) // handle pin change interrupt for for A0 to A6 and reset [only A3 to A5 are enabled]
  if (digitalRead(A3)){//angle sensor 1 
    triggeredAngleSensor1 = true;
    triggeredTimeAngleSensor1 = millis();
  if(digitalRead(A4)){//angle sensor 2
    triggeredAngleSensor2 = true;
    triggeredTimeAngleSensor2 = millis();
  if(digitalRead(A5)){//angle sensor 3
    triggeredAngleSensor3 = true;
    triggeredTimeAngleSensor3 = millis();

void setup() {

  // pin change interrupt 
  PCMSK1 |= bit (PCINT13) | bit (PCINT12 | bit (PCINT11));  // want pin A5 or A4 or A3
  PCIFR  |= bit (PCIF1);    // clear any outstanding interrupts
  PCICR  |= bit (PCIE1);    // enable pin change interrupts for A0 to A6 and reset

  pinMode(pinDrehen, OUTPUT);
  pinMode(pinRevDrehen, OUTPUT);

  //start turning machine:
  digitalWrite(pinDrehen, HIGH);
  digitalWrite(pinRevDrehen, HIGH);

void loop() {
    Serial.print("Sensor 1 interrupt at time: ");
    Serial.print("Sensor 2 interrupt at time: ");
    Serial.print("Sensor 3 interrupt at time: ");

This line:

PCMSK1 |= bit (PCINT13) | bit (PCINT12 | bit (PCINT11));  // want pin A5 or A4 or A3

is probably not what you want.

Let's break it down and look at just what you have there.

bit (PCINT13)

The bit function returns the bitmask for a specific bit. So if you pass it 3 you get a value with the third (counting from 0) bit enabled (1 << 3, or 0b1000, or 0x08).

PCINT13 is 5. So you have 1 << 5, or 0x20.

So far so good. Now you OR that with:

bit (PCINT12 | bit (PCINT11))

And this is the bit that's wrong. Inside is bit (PCINT11) which, with PCINT11 being 3, results in 0x08. That is then ORed with PCINT12, which is 4. The result is 8+4. That's 12. The value 12 is then fed through another bit() function, which gives you 1<<12. That, of course, overflows outside of an 8-bit value, so you end up with 0.

The final result is ORed together with the 0x20 from before, which of course remains as 0x20.

What you probably wanted (and intended) is to have:

PCMSK1 |= bit (PCINT13) | bit (PCINT12) | bit (PCINT11);  // want pin A5 or A4 or A3

the logic in the isr is incorrect.

generally, you want to set up the pcint pins so that they respond to an edge.

in the isr (with multiple pin changes), you will need to either 1) preserve and maintain the previous state so to determine which pins have experienced a state change; or 2) use pin change flags.

what you have there can lead to false determination of triggers.

  • In my application a sensor will be triggered only for a short time (at least while i am reacting to interrupts) and two sensors can not deliver HIGH at the same time, therefor i don't think this is an issue. However i am curious about your two possibilities. Wouldn't i realisiere the first one with (boolean) flags, which would be the second one? (Or are pin change flags some bits in a hardware register and you don't mean flags i set on my own?) – Hannes Nov 25 '17 at 16:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.