External Interrupt not working

I am using Arduino Pro Mini 5V 328P, pin no. 3 for detecting zero cross from AC 50Hz, thru opto coupler.

Though I can read 50+50 = 100Hz at pin no. 3 but the ISR is not running. I have tried FALLING, RISING and CHANGE.

Here is the code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); 

const byte zeroCross   = 3;   
int a = 0;

void setup() 
{
  pinMode(zeroCross, INPUT_PULLUP);
  attachInterrupt(3, zero, LOW); // on Pin 3
  
  lcd.init();       
  lcd.backlight(); 
  lcd.setCursor(0,0);
  lcd.print("a =");
 
}

void loop()
{
}


void zero()
{
  a++;
  lcd.setCursor(4,0);
  lcd.print(a);
}

hi abuhaffs,

the total execution-time of interrupt-service-routines (in short ISR) should be kept as short as possible.

you have coded in your isr

void zero()
{
  a++;
  lcd.setCursor(4,0);
  lcd.print(a);
}

two commands that do output to the I2C-serial display.
It might be that this output takes more than 0,02 seconds which is too long.

the output to your LCD should be done outside the ISR
your ISR should have the the IRAM_ATTR attribute

code that is placed in internal RAM is executed much faster than from the flash

Variables that are shared between your ISR and your main-code need the attribute “volatile”
without the attribut volatile the compiler can “optimise” your code that results in non-functioning

so try this version

last but not least you should develop a habit of using selfexplaining names for all identifiers I did some namechanging in this way

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

const byte zeroCross   = 3;   

volatile int NumberOfZeroCrossings = 0;

void IRAM_ATTR zero_ISR()
{
  NumberOfZeroCrossings++;
}

void setup()
{
  pinMode(zeroCross, INPUT_PULLUP);
  attachInterrupt(3, zero_ISR, LOW); // on Pin 3
 
  lcd.init();       
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("ZC ="); 
}

void loop()
{
  lcd.setCursor(5,0);
  lcd.print(NumberOfZeroCrossings);  
}

this code compiles. But I don’t have your hardware. So I would like to hear from you if it working now

best regards Stefan

StefanL38: your ISR should have the the IRAM_ATTR attribute

I don't think that is appropriate for an Atmega 328

...R

Robin2: I don't think that is appropriate for an Atmega 328

As I already explained to @StefanL38 here.

Hi Robin2m Hi gfvalvo

you are right. No IRAM_ATT on Atmegas. Most of the time I code for ESP8266 and ESP32 I was assuming Atmengas are mostly advanced as ESPs.

I think now the "WriteEEPROM" into my brain was successful ;-))

One of the most basic rules is to NEVER attempt serial input/output in an ISR. Interrupts are off in an ISR and serial I/O depends on interrupts.

Set a global flag variable in the ISR (declared volatile) and let the main program do the work.

I am using Arduino Pro Mini 5V 328P, pin no. 3 for detecting zero cross

attachInterrupt(3, zero, LOW); // on Pin 3

Incorrect syntax. The first parameter to attachInterrupt() is an interrupt number.

See https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

The Mode should be CHANGE. instead of LOW.

attachInterrupt(digitalPinToInterrupt(3), zero, CHANGE);

cattledog: attachInterrupt(3, zero, LOW); // on Pin 3

Incorrect syntax. The first parameter to attachInterrupt() is an interrupt number.

See https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

The Mode should be CHANGE. instead of LOW.

attachInterrupt(digitalPinToInterrupt(3), zero, CHANGE);

Thanks for the correction. :)