pinchangeinterrupt question on the idea of groups

Credit to GitHub - NicoHood/PinChangeInterrupt: A simple & compact PinChangeInterrupt library for Arduino

I'm using mega board 2560 with many I/O connected and wish to enable at least 4 of them as interrupt triggered pins. Unfortunately, external interrupt pins are not enough for me so I turn to this PinChangeInterrupt library.

#define BUTTONPIN01 50
#define BUTTONPIN04 63  //A9
#define BUTTONPIN07 66  //A12
#define BUTTONPIN10 69  //A15

volatile unsigned int bcounter01 = 0;
volatile unsigned int bcounter04 = 0;
volatile unsigned int bcounter07 = 0;
volatile unsigned int bcounter10 = 0;

volatile unsigned long last_interrupt_time1 = 0;
volatile unsigned long last_interrupt_time4 = 0;
volatile unsigned long last_interrupt_time7 = 0;
volatile unsigned long last_interrupt_time10 = 0;

setup(){
  pinMode(BUTTONPIN01, INPUT);
  pinMode(BUTTONPIN04, INPUT);
  pinMode(BUTTONPIN07, INPUT);
  pinMode(BUTTONPIN10, INPUT);
  
  attachPCINT(digitalPinToPCINT(BUTTONPIN01), pin_change01, CHANGE);
  attachPCINT(digitalPinToPCINT(BUTTONPIN04), pin_change04, CHANGE);
  attachPCINT(digitalPinToPCINT(BUTTONPIN07), pin_change07, CHANGE);
  attachPCINT(digitalPinToPCINT(BUTTONPIN10), pin_change10, CHANGE);

}

loop(){

  // job with many delay().

}

The following is one of my 4 Interrupt Request Handler:

void pin_change01(void)
{
  // Do NOT use Serial class or delay() inside pinChange interrupts.
  unsigned long interrupt_time = 0;
  uint8_t trigger = getPinChangeInterruptTrigger(digitalPinToPCINT(BUTTONPIN01));
  if( trigger == FALLING ){
    interrupt_time = millis();
    if (interrupt_time - last_interrupt_time1 > 50){
    bcounter01 += 1;
    }
    last_interrupt_time1 = 0;
  }
  else{
    last_interrupt_time1 = millis();
  }
}

As far as I know, pin 50 and 63 are on the same group, pin 66 and 69 on the same group.

Does it mean if pin 50 and 63 were triggered at the same time, one of the interrupt will not be process?

Thank you in advanced.

I don't use that library so have no idea. You can read Arduino Playground: Simple Pin Change Interrupt on all pins. In the relevant ISR, you can use digitalRead (or direct port manipulation) to determine which pins triggered the interrupt. E.g.

ISR (PCINT1_vect)
{
  if (digitalRead(A0) == LOW)
  {
    doSomething();
  }
  if (digitalRead(A1) == LOW)
  {
    doSomethingElse();
  }
}
loop(){

// job with many delay().

}

Don't use delay and there is a good chance that you don't need interrupts. What is connected to the pins?

Be aware that interrupt routines need to be sweet and short; switching a LED on/off is OK, something that takes a while will interfere with e.g. your delays.

PS
Karma added for using code tags in your first post.

FYI PinChangeInterrupt has been deprecated, you should get the new EnableInterrupt.

In general, pin change interrupts operate on a port-wide basis. That means that any pin on that port that has been enabled is capable of firing the interrupt. What needs to happen when that occurs is the software (library) needs to determine which pin caused the interrupt and execute the attached ISR. As soon as an interrupt fires, global interrupts are disabled so another interrupt of equal or lower priority cannot cause the program flow to be changed. All interrupts attached to the same port have the same priority, different ports have different (higher/lower) priority (see ch. 14 in the datasheet). As soon as the interrupt has been serviced, a return instruction executed by the ISR, global interrupts are enabled. You don't need to do anything, it happens automatically. If there has been an interrupt occur (of equal or lower priority) while you're servicing an existing interrupt, there is a flag set that effectively allows the other interrupt(s) to be queued and it/they will be serviced immediately after. It is impossible for two interrupts on the same port to occur at the same time as the trigger to initiate an ISR is handled sequentially. Each interrupt will maintain the interrupt flag until it is serviced, so all interrupts will eventually get attention. This is why it is important to have your ISRs as short as possible and not have any instruction within the ISR that relies on an interrupt (Serial.print, delay, etc.). How the interrupts of the same priority (same port) get serviced is up to the code that determines which gets first dibs, usually bit0 first, bit7 last.

Thank you both DKWatson and sterretje for replying my question!!

I'll look into EnableInterrupt.

I ran a quick test which triggers pin 50 and 63 in the same time and the interrupt process accordingly. None of which is discard.

Based on the information you kindly provided, a "flag" is being set to the pin that is triggered. If my interrupt finishes the job within the corresponding handler and the flag is being unset before the next interrupt was triggered on that same pin. I'm safe to apply as many pins as the board supported. (Mega-->pin 10-15 and A8-A15 and SS, SCK, MOSI, MISO) Is this statement correct?

I do keep in mind that to avoid lengthy code in the ISR handler. However, delays and Serial.print within the mainloop is unavoidable.

My I/O inputs are 200ms square wave signals(100ms high and 100ms low) with peak-peak voltage of approximately 4 volt. The purpose of this piece of code is aim to validate these signals and ignore short impulses with width < 50 ms.

Regards,

As you have not shown your code, my statement is that delays are always avoidable.

I'm aware that there are some things that require extremely accurate timing (e.g. neopixels) but when using those, interrupts will more than likely be disabled so they don't interfere with the timing.

Regarding serial prints (and writes), they are basically non-blocking till such time that the output buffer (64 bytes) is full.

100 ms is an ethernity in Arduino time.

It takes time from the moment that the interrupt is triggered till the ISR is called. It also takes time before your actual ISR code is executed as the program counter and a number of bytes are pushed onto stack; if I recall correctly, it's around 30 cpu cycles (not really a train smash in your case).