Separate Interrupts For High/Low Pin Status

Is it possible to have separate hardware interrupts for pin high and low status run concurrently:

attachInterrupt(0,InterruptA_High,RISING);
attachInterrupt(0,InterruptA_Low,FALLING);
attachInterrupt(1,InterruptB_High,RISING);
attachInterrupt(1,Interruptb_Low,FALLING);

I'm guessing not, but this would allow me to reduce that amount of code inside the interrupts for a high frequency application.

attachInterrupt(0,InterruptA_Low,TRAILING);

will definitely not work because TRAILING is not a valid parameter, but have you tried attaching 2 interrupts to the same pin with the correct parameter ?

http://arduino.cc/en/Reference/AttachInterrupt

You read my post before I corrected the code to say "FALLING." Anyway, I tried it and it doesn't seem to fire both, just on the last call to attachInterrupt().

The options are exclusive. Try CHANGE

you should use CHANGE and in the ISR you can go to the right code depending on the line. Fastest is to keep the state yourself.

void myISR()
{
  state = 1 - state;
  if (state == 1) myHIGHISR();
  else myLOWISR();
}

works like a charm (note that digitalRead(pin) takes more time)

renniejohnson:
You read my post before I corrected the code to say “FALLING.” Anyway, I tried it and it doesn’t seem to fire both, just on the last call to attachInterrupt().

The last call overrides any previous calls.

You can have one and one only ISR per interrupt (external or internal).

Mark

Thanks guys. I've got both interrupts working on a quadrature encoder and I'm only getting accuracy up to about 50KHz. Is there a faster way to read the pin status than "digitalRead()"?

bitRead(PINX,n) is simple to use, and will get you most of the available speed increase.

Direct Port Manipulation where you read both pins at once is slightly faster.

void setup() {
  // put your setup code here, to run once:
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);
  Serial.begin(115200);

  unsigned long microsStart=micros();

  for (int i=0;i<1000;i++){
    digitalRead(2);
    digitalRead(3);
  }

  unsigned long microsEnd=micros();

  Serial.println(microsEnd-microsStart);


  microsStart=micros();
  for (int i=0;i<1000;i++){
    bitRead(PIND,2);
    bitRead(PIND,3);
  }
  microsEnd=micros();

  Serial.println(microsEnd-microsStart);
  
  microsStart=micros();
  for (int i=0;i<1000;i++){
    (PIND & B00001100)>>2;
  }
  microsEnd=micros();

  Serial.println(microsEnd-microsStart);

}

void loop() {
  // put your main code here, to run repeatedly: 

}

Output

8740
596
528

With this sketch I can count up to about 200 kHz.

volatile bool counting;
volatile unsigned long events;

unsigned long startTime;
const unsigned long INTERVAL = 1000;  // 1 second

void activateInterrupt0 ()
  {
  EICRA &= ~(bit(ISC00) | bit (ISC01));  // clear existing flags
  EICRA |=  bit (ISC01);    // set wanted flags (falling level interrupt)
  EIFR   =  bit (INTF0);    // clear flag for interrupt 0
  EIMSK |=  bit (INT0);     // enable it
  }  // end of activateInterrupt0

void deactivateInterrupt0 ()
  {
  EIMSK &= ~bit (INT0);     // disable it
  }  // end of deactivateInterrupt0
  
ISR (INT0_vect)
  {
  if (counting)
    events++;    
  }  // end of ISR (INT0_vect)
  
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  activateInterrupt0 ();
  }  // end of setup

void showResults ()
  {
  Serial.print ("I counted ");
  Serial.println (events);
  }  // end of showResults
  
void loop ()
  {
  if (counting)
    {
    // is time up?
    if (millis () - startTime < INTERVAL)
      return;  
    counting = false;
    showResults ();
    }  // end of if
    
  noInterrupts ();
  events = 0;
  startTime = millis ();
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  counting = true;
  interrupts ();
  }  // end of loop

Remember though that this is counting every 5 µS. An interrupt routine takes about that time to enter and leave. So you won’t get much faster than that with interrupts.

cattledog’s suggestion of using PIND in a tight loop is about as good as you can get, and that assumes you don’t want to do anything else. His figures suggest about one read per µS which sounds about right.

To get even higher frequency counts, use the hardware timers/counters. See:

Timers

My example there counted up to 5 MHz. After all, it’s the job of the hardware counter to count, may as well use it.