Interrupts on Nano - weird behavior

As part of a bigger project I want to count pulses from two sources by triggering interrupts. The code for that should be straightforward:

const int pinA = 2;
const int pinB = 3;

volatile unsigned long pulseCountsA=0;
volatile unsigned long pulseCountsB=0;

void ISRA() {
  pulseCountsA++;
}

void ISRB() {
  pulseCountsB++;
}


void setup() {
  Serial.begin(115200);
  while(!Serial);

  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);

  attachInterrupt(digitalPinToInterrupt(pinA), ISRA, RISING);
  attachInterrupt(digitalPinToInterrupt(pinB), ISRB, RISING);

  Serial.println("Setup successful.");
  delay(500);

}

void loop() {
  unsigned long pulsesA;
  unsigned long pulsesB;
  
  noInterrupts();
  pulsesA = pulseCountsA;
  pulsesB = pulseCountsB;

  pulseCountsA = 0;
  pulseCountsB = 0;
  interrupts();
      
  Serial.print("CountA pulses ");    
  Serial.print(pulsesA);
  Serial.print("  CountB pulses ");    
  Serial.println(pulsesB);

  delay(1000);
}

This works fine (HW: Arduino Nano, old bootloader) as long as I send pulses to ONE of the pins (2 or 3), but not if I send pulses to both pins. Pulses are generated w/ a signal generator and I can confirm the frequencies of the square waves w/ an oscilloscope. When I generate pulses to both pins (2 and 3), the counts are higher/erratic.
I'd appreciate any help/suggestions as to what I may be doing wrong. Thank you in advance!

Good job with code tags on your first post. :slight_smile:

What frequencies are you trying to measure?

Are the grounds of the signal generator and the Arduino connected?

If you generate your signal on the Nano instead of on the signal generator is the count stable? You can use tone() to generate a wide range of frequencies

Add these lines to setup and jumper the output from pin 11 to pins 2 and 3.

pinMode(11,OUTPUT);
tone(11,5000); //set frequency with second parameter

what is the output voltage of the signal generator?
is it an AC output?

Don't forget to connect pull-down resistors with DPin-2, 3.

You can try the following codes for your loop() function (assuming you want to collect the pulses in every 1-sec interval).

unsigned long pulsesA; //global declaration
unsigned long pulsesB;
void loop()
{
      unsigned long prMillis = millis();
      while(millis() - prMillis < 1000)   //1000 ms; let the pulses be counted for 1-sec time.
      {
           ;    //wait and check if 1-sec has elapsed
      }
      noInterrupts();
      pulsesA = pulseCountsA;
      pulsesB = pulseCountsB;

      pulseCountsA = 0;
      pulseCountsB = 0;
     
      Serial.print("CountA pulses ");   
      Serial.print(pulsesA);
      Serial.print("  CountB pulses ");   
      Serial.println(pulsesB);
      //--------------------------------
      interrupts();
}

cattledog:
What frequencies are you trying to measure?
Are the grounds of the signal generator and the Arduino connected?

If you generate your signal on the Nano instead of on the signal generator is the count stable? You can use tone() to generate a wide range of frequencies

From a few Hz to a few kHz.
Yes, the Arduino ground pin and the shielded connectors on the signal generator and the oscilloscope are all connected in one point.
Tested w/ the tone() function per your suggestion and everything worked as expected (one input from tone() and the other from the generator). Obviously, I was doing something wrong. I took a closer look at the signal from the generator and found that it wasn't properly offset and it wasn't a proper TTL level :-(. // a 0 offset means +-2.5V amplitude. I'm not sure why it worked at all with just one input...
My apologies for wasting your time. Thanks again for the great troubleshooting tip.

gcjr:
what is the output voltage of the signal generator?
is it an AC output?

Square wave 0-5V. But that's what I thought the output was. Apparently, I didn't set correctly the offset and instead the signal was +-2.5V. Fixing the offset resolved the problem. Thanks for the tip and I'm sorry to waste your time.

GolamMostafa:
Don't forget to connect pull-down resistors with DPin-2, 3.

Thanks for the suggestion and for the code sample! I resolved the problem: the signal from the generator wasn't a proper TTL level (didn't notice that it was offset). I did use pull-up resistors of 8.2k but that of course didn't fix the problem while the signal wasn't correctly offset. The odd thing is that the count was correct when only one signal was supplied and counted. Anyhow, thank you and apologies for the naive mistake.

When you have only one signal, there there is only one interrupts and the counting goes well for one interrupt process.

When you have two interrupts, then the INT1 interrupt remains OFF while the INT0 interrupt is in process. The reverse is also true. So, there is a chance that you miss 1 or 2 counts for both the counters. However on an average, the result would be OK.

GolamMostafa:
When you have only one signal, there there is only one interrupts and the counting goes well for one interrupt process.

When you have two interrupts, then the INT1 interrupt remains OFF while the INT0 interrupt is in process. The reverse is also true. So, there is a chance that you miss 1 or 2 counts for both the counters. However on an average, the result would be OK.

My understanding is that as long as the interrupt handler doesn't take too long to complete I shouldn't be missing any pulses since the outstanding interrupts (no more than one) will be handled after the completion of the current ISR. In this case I'm simply incrementing a long and that definitely shouldn't be a problem. Thanks for your input.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.