Rising edge detection during pin change interrupt on Atmega2560

I am using controllino MEGA with Atmega2560 chip. I am trying to write a program to detect rising and falling edge on PORT K (PCINT16 AND PCINT17). I have most of it working but there is some issue with consistency and I think there is a problem in my code.

volatile byte state = LOW;
#include <Controllino.h>


void setup(){
  Serial.begin(9600);
   pinMode(CONTROLLINO_R10, OUTPUT);
   pinMode(CONTROLLINO_A8, INPUT);
   PCMSK2 = B00000011; //enable PCINT16 AND 17
   PCIFR = B00000000; // clear all interrupt flags
   PCICR = B00000100; // enable PCIE2 group
}
 
void loop(){
   digitalWrite(CONTROLLINO_R10, state);
}
 
ISR(PCINT2_vect) {
  if(PINK && (1 << PK0)) {
    state = !state;
  }
   return;
}

Currently I am trying solve single problem of Rising edge on A8 (PCINT16)

the output seems inconsistent. sometimes it changes state fine but sometimes it dosen't.

Also I think when it doesn't change state properly it executes ISR twice.

This line is also very confusing to me if(PINK && (1 << PK0))

Thank you

I think you have inconsistent behavior because you do not debounce your entry. Sugest usage of a Schmidt trigger during tests

as for

if(PINK && (1 << PK0))

if bit of order PK0 in PINK port is set

1<<PK0 is a 'one' in the right position of the byte (assume it's a byte port)

and PINK&& 1<< etc extracts the targeted bit of PINK for examination

Good luck

ok I solved it.

Beacause I am working with buttons there is issues with electricity when button engages. with meant that my interupts would sometime run twice or maybe even more. The solution = ADD TIME CHECK. Below is working code. I tried with micros = 800 but would still get issues sometimes, seems millis = 1 is just enough.

volatile byte state = LOW;
unsigned long lastInterrupt;
//byte a;
#include <Controllino.h>
void setup(){
   pinMode(CONTROLLINO_R10, OUTPUT);
   pinMode(CONTROLLINO_A9, INPUT);
   PCMSK2 = B00000011; //enable PCINT16 AND 17
   PCIFR = B00000000; // clear all interrupt flags
   PCICR = B00000100; // enable PCIE2 group
}
 
void loop(){
   digitalWrite(CONTROLLINO_R10, state);
}
 
ISR(PCINT2_vect) {
  if(millis() - lastInterrupt >1){
    lastInterrupt = millis();
  if(digitalRead(CONTROLLINO_A9)==HIGH) {
    state = !state;
  }
  }
  return;
}

Note to anyone in the future if A9 is high any other change in portK will trigger state=!state.

Now if only i could somehow read which pin changed... Although for my current project I will just solve with multiple checks inside IF.

Please mark as Solved

The 'digitalRead()' function is super slow. I wouldn't use it in an ISR, especially not twice. Use direct read of PINK register and mask the appropriate bits.

gfvalvo:
The 'digitalRead()' function is super slow. I wouldn't use it in an ISR, especially not twice. Use direct read of PINK register and mask the appropriate bits.

oh thats kinda smart.

here I edited last part now other things in port K don't stop it from working and don't interfere. Unless you gonna say that bitRead is also slow :frowning: or I am missing something else. Thanks a lot for the help.

ISR(PCINT2_vect) {
  if(millis() - lastInterrupt >1){
    lastInterrupt = millis();
  if(bitRead(PINK, 1) == 1 ) {
    state = !state;
  }
  }
  return;
}