Simultaneous interrupts - how?

Hi eveyone,

I have to receive & analyse 2 different pulse signals using the Mega.

Is it ok to split each pulse to two inputs and use attachInterrupt() to recognize rises & falls by increasing the related counters?

This means:

int.0 - Pulse 1 rise
int.1 - Pulse 1 fall
int.2 - Pulse 2 rise
int.3 - Pulse 2 fall

In case the two rises or two falls happen at the same time, will they be queued up & processed just fine?

The inputs could be either high or low state before pulsing happens depends on the controller.
Do I need to use pull down resistor here or just leave them all floating?

Thanks for any comment.

Don't leave them floating, who knows what they will read if you do that?

In case the two rises or two falls happen at the same time, will they be queued up & processed just fine?

Yes.

In case the two rises or two falls happen at the same time, will they be queued up & processed just fine?

Both the events will be latched, you won't lose them as long as you handle them before the next edge. But you can of course only service one at a time. The first to be serviced will be the one with the highest priority, immediately (well almost) upon leaving the ISR for that one the ISR for the second one will be called.


Rob

Thanks for the responses gents.

Nick, the input state could be preset high or low depends on the ICs (that generates the pulses) before or after the pulses happens.

At one stage, after all pulses are received, the ICs decides the leave all pins High right after the last rise.
What happens to the input if I grounded it by a 10K resistor? Will the pin remains high and no extra interrupt recognized?

It's OK if the input is kept high, but not if it is high-impedance (floating).

Thanks Nick.

Wonder if any of us can help spot out anything not right with the code?

volatile unsigned int count1 = 0;                        //number of phase change of Phase A
volatile unsigned int count2 = 0;                        //number of phase change of Phase B

int countA = 0;                                          //Phase A counter
int countB = 0;                                          //Phase B counter

int phaseA1 = 0;                                         //check for initialization stages; pass ~ 1 or fail ~ 0
int phaseA2 = 0;
int phaseB1 = 0;
int phaseB2 = 0;

void setup()
{     
  attachInterrupt(0, isrA, CHANGE);           //Pin D2, enable the interrupt of Phase A detected
  attachInterrupt(1, isrB, CHANGE);          //Pin D3, enable the interrupt of Phase B detected 
  
  Serial.begin(115200);   
}

void isrA()                                           //routine to count the rising edge of A Phase
{ 
  count1++;
}

void isrB()                                            //routine to count the falling edge of A Phase
{     
  count2++;
}

void getCount()                                   //handle interrupt counters outside interrupt routine
{
  byte oldSREG = SREG;                             //remember if interrupts are on or off
  if (countA != count1)
  {
    noInterrupts();                             //turn interrupts off
    countA = count1;                            //update countA   
    SREG = oldSREG;                             //turn interrupts back on, if they were off  
    
    Serial.print("A");
    Serial.print(countA);
    Serial.print(" ");
    Serial.print("B");
    Serial.println(countB);    
  }  
  
  if (countB != count2)
  {
    oldSREG = SREG;                             //remember if interrupts are on or off
    noInterrupts ();                            //turn interrupts off
    countB = count2;                            //update countB    
    SREG = oldSREG;                             //turn interrupts back on, if they were off  
    
    Serial.print("A");
    Serial.print(countA);
    Serial.print(" ");
    Serial.print("B");
    Serial.println(countB);    
  }  
}

void resetCount()                                //reset counters if a phase has passed
{
  byte oldSREG = SREG;                           //remember if interrupts are on or off  
  noInterrupts();                               //turn interrupts off     
  countA = count1 = 0;                          //reset countA
  countB = count2 = 0;                          //reset countB   
  SREG = oldSREG;                               //turn interrupts back on, if they were off    
  
  Serial.print("Reset ");
  Serial.print("A");
  Serial.print(countA);
  Serial.print(" ");
  Serial.print("B");
  Serial.println(countB); 
}

void loop()
{      
  getCount();                                //update & print counters if changes occur
  
  if (countA == 13 && countB == 13 && phaseA1 == 0 && phaseB1 == 0)
  {        
    Serial.print("A");
    Serial.print(countA);
    Serial.print(" ");
    Serial.print("B");
    Serial.println(countB);   
    Serial.println("Initialization Phase A1 & B1 Done");        
    phaseA1 = 1;  
    phaseB1 = 1;
    Serial.print("Phase A1: ");
    Serial.print(phaseA1);
    Serial.print(" ");
    Serial.print("Phase B1: ");
    Serial.println(phaseB1);  
    resetCount();    
   }   
   
   if (countA == 13 && countB == 13 && phaseA1 == 1 && phaseB1 == 1)
    {
      Serial.print("A");
      Serial.print(countA);
      Serial.print(" ");
      Serial.print("B");
      Serial.println(countB);  
      Serial.println("Initialization Phase A2 & B2 Done");         
      phaseA2 = 1;  
      phaseB2 = 1;    
      Serial.print("Phase A2: ");
      Serial.print(phaseA2);
      Serial.print(" ");
      Serial.print("Phase B2: ");
      Serial.println(phaseB2); 
      Serial.println("Initialization Done"); 
      phaseA1 = 0;  
      phaseB1 = 0;
      phaseA2 = 0;  
      phaseB2 = 0;      
      resetCount();      
    }
}

How the results should be:

A1 B0
A1 B1
A1 B2
A2 B2
A2 B3
A3 B3
A3 B4
A4 B4
A4 B5
A5 B5
A5 B6
A6 B6
A6 B7
A7 B7
A7 B8
A8 B8
A8 B9
A9 B9
A9 B10
A10 B10
A10 B11
A11 B11
A11 B12
A12 B12
A12 B13
A13 B13
A13 B13
Initialization Phase A1 & B1 Done
Phase A1: 1 Phase B1: 1
Reset A0 B0
A1 B0
A1 B1
A2 B1
A2 B2
A3 B2
A3 B3
A4 B3
A4 B4
A5 B4
A5 B5
A6 B5
A6 B6
A7 B6
A7 B7
A8 B7
A8 B8
A9 B8
A9 B9
A10 B9
A10 B10
A11 B10
A11 B11
A12 B11
A12 B12
A13 B12
A13 B13
A13 B13
Initialization Phase A2 & B2 Done
Phase A2: 1 Phase B2: 1
Initialization Done
Reset A0 B0

But occasionally I got the below when repeated the initialization

Initialization Phase A2 & B2 Done
Phase A2: 1 Phase B2: 1
Initialization Done
Reset A0 B0
A1 B0
A1 B1
A1 B2
A2 B2
A2 B3
A3 B3
A3 B4
A4 B4
A4 B5
A5 B5
A5 B6
A6 B6
A6 B7
A7 B7
A7 B8
A8 B8
A8 B9
A8 B10
A9 B10
A9 B11
A10 B11
A10 B12
A11 B12
A11 B13
A12 B13
A12 B14
A13 B14
A14 B14
A14 B15
A15 B15
A15 B16
.....

I monitor the inputs on the oscilloscope and the sequence of the passed results above is confirmed.

Which part is wrong, exactly?

Try clearing the interrupts before attaching them:

EIFR = bit (INTF0);  // clear flag for interrupt 0
EIFR = bit (INTF1);  // clear flag for interrupt 1

Where should I use the code you provided Nick? Once, in setup?

void setup()
{     
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  EIFR = bit (INTF1);  // clear flag for interrupt 1
  attachInterrupt(0, isrA, CHANGE);           //Pin D2, enable the interrupt of Phase A detected
  attachInterrupt(1, isrB, CHANGE);          //Pin D3, enable the interrupt of Phase B detected 
  
  Serial.begin(115200);   
}

To answer your question, expected results:

A13 B12
A13 B13

if both counters A and B return 13 then this phase is passed, and the counters are reset for next phase.

at fault the counters are increased not as expected here, it's kind of random:

A12 B13
A12 B14
A13 B14

I suspect either the flow of the program is not right or the interrupt routine is interrupted but yet to debug it successfully.

  if (countA == 13 && countB == 13 && phaseA1 == 0 && phaseB1 == 0)
...
   if (countA == 13 && countB == 13 && phaseA1 == 1 && phaseB1 == 1)

Well, aren’t there other possibilities? Like: phaseA1 == 1 && phaseB1 == 0

Yes, it is for fault diagnosis even though I did not code in yet.
But by monitoring the oscilloscope, I can confirm the inputs are normal when that wrong reading happens

any other suggestion anyone?

The fact that you are overshooting 13 makes it clear that your counters are going higher than you expect, quite possibly while you output the messages. Try testing for >= rather than ==.

Well, aren’t there other possibilities? Like: phaseA1 == 1 && phaseB1 == 0

Thanks Nick. This morning I revisited your suggestion and separated the validation of each component (phase A1, A2, B1, B2, etc) and it works well.

The fact is A and B pulses could happens at the same time or lag behind each other. It was my fault to combine the validation.

This works consistently now

void iniServos()
{
  iniServo = 0;
  getCountA();                                //update & print counters if changes occur
  getCountB();                                //update & print counters if changes occur
  
  //check phase A
  if (countA == 13)
  {
    if (phaseA1 == 0)    
    {
      phaseA1 = 1;      
      resetCountA();   
      Serial.println("Initialization Phase A1 Done");  
    }
    else if (phaseA1 == 1)  
    {
      phaseA2 = 1;      
      resetCountA();   
      Serial.println("Initialization Phase A2 Done");  
    }      
  }
  
  //check phase B
  if (countB == 13)
  {
    if (phaseB1 == 0)    
    {
      phaseB1 = 1;      
      resetCountB();   
      Serial.println("Initialization Phase B1 Done");  
    }
    else if (phaseB1 == 1)  
    {
      phaseB2 = 1;      
      resetCountB();   
      Serial.println("Initialization Phase B2 Done");  
    }      
  }   
  
  //check first stage 
  if (phaseA1 == 1 && phaseB1 == 1)
  {
    phaseIni1 = 1;                         //this phase done        
  }
  
  //check second stage
  if (phaseA2 == 1 && phaseB2 == 1)
  {
    phaseIni2 = 1;                         //this phase too     
  }
  
  //check for completion
  if (phaseIni1 == 1 && phaseIni2 == 1)
  {
    iniServo = 1;                              //ini done  
    phaseA1 = 0;                          //reset for next time
    phaseB1 = 0;   
    phaseA2 = 0;                          //reset for next time
    phaseB2 = 0;
    phaseIni1 = 0;                          //reset for next time
    phaseIni2 = 0;
  } 

void loop()
{      
  iniServos();
  if (iniServo == 1)
  {
    Serial.println("Initialization Done");
    Serial.println();    
  }  
}
}

Thanks again for your kind support