Interrupts in Arduino not working (for detecting zero crossing)

In summary, the code is supposed to enable the interrupts before using them, but this was not done in this case.
  • #1
Wrichik Basu
Science Advisor
Insights Author
Gold Member
2,116
2,691
In my previous thread, I learned about the H11AA1 optocoupler, which can be used instead of the 4N35 to detect zero crossings with Arduino.

Arduino has a specific function for detecting interrupts: attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) This function is supposed to be used rather than the loop() function. Interrupt Service Routines (ISR) have to be short, but the code inside the loop() function can often be long, which will delay the next iteration and an interrupt can be missed.

The function allows the following four modes:
mode: defines when the interrupt should be triggered. Four constants are predefined as valid values:
  • LOW to trigger the interrupt whenever the pin is low,
  • CHANGE to trigger the interrupt whenever the pin changes value,
  • RISING to trigger when the pin goes from low to high,
  • FALLING for when the pin goes from high to low.

Code:

Arduino:
const int PIN_INTERRUPT = 7;

void setup() {
  
    Serial.begin(9600);

    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(PIN_INTERRUPT, INPUT);

    digitalWrite(LED_BUILTIN, LOW);

    attachInterrupt(digitalPinToInterrupt(PIN_INTERRUPT), zeroCrossing, FALLING);
}

void loop() {
    Serial.println(analogRead(A0));
}

void zeroCrossing(){
    digitalWrite(LED_BUILTIN, HIGH);
}
The code is quite simple: the inbuilt LED is originally off, but the first time an interrupt is detected, it is turned on, and it stays on thereafter. I do not have an oscilloscope, so I am using the Arduino serial plotter and analogRead() to plot voltage values.

Circuit:

1608480792576.png

The diagram for the optocoupler follows from the Vishay datasheet.

Problem: Arduino is not detecting the interrupts: the inbuilt LED is not glowing, which implies that the ISR is not being called.

Output of Arduino serial plotter:

1608481068013.png

The above plot has interesting characteristics — it has a periodic pattern. The spikes almost always go below 300 (< 1.24V, LOW for arduino digital logic) from > 900 (> 4.41V, HIGH for Arduino digital logic), so these are the interrupts I want to see. This implies that the optocoupler is working fine, but Arduino still does not call the ISR.

I have tried many times before; this is the best graph I got. Now I don't know what to do. I cannot keep on using the loop() function because that will later be used for user input.

All help appreciated.
 
Engineering news on Phys.org
  • #2
Dumb question, but for most microcontrollers (uCs), you have to "enable" the interrupt(s) before they work. I may have missed it, but I don't see mention of that in your code above...
 
  • #3
berkeman said:
Dumb question, but for most microcontrollers (uCs), you have to "enable" the interrupt(s) before they work. I may have missed it, but I don't see mention of that in your code above...
Not a dumb question; I had thought about that before. It's supposed to be enabled by default in Arduinos. I also tried to specifically enable it by calling the interrupts() function, but nothing changed.
 
  • #4
Wrichik Basu said:
The code is quite simple: the inbuilt LED is originally off, but the first time an interrupt is detected, it is turned on, and it stays on thereafter.
The LED is turned on by every zero crossing ISR, so it appears to stay on.
You are seeing a beat between the mains zero crossings and the loop routine.
Maybe count the ISR calls and copy the sixth bit of that counter to the LED. You should see 1/64'th of the interrupt rate.
 
  • #5
Baluncore said:
The LED is turned on by every zero crossing ISR, so it appears to stay on.
You are seeing a beat between the mains zero crossings and the loop routine.
Maybe count the ISR calls and copy the sixth bit of that counter to the LED. You should see 1/64'th of the interrupt rate.
Maybe I was a bit unclear: the inbuilt LED is supposed to stay on, but it doesn't turn on at all.
 
  • #6
Test the LED by turning it on and off with delays in the main Loop().
When you know you have the LED control OK, then try the interupt.
 
  • #7
Baluncore said:
Test the LED by turning it on and off with delays in the main Loop().
When you know you have the LED control OK, then try the interupt.
Sorry, but I don't know if I fully understand what you are saying. If I use delay() in loop() in the above code, I will miss some of those spikes. I can use delayMicroseconds() instead, but I don't see why that is necessary. If you are asking me to test whether the LED is functioning properly, then the answer is yes; digitalWrite(LED_BUILTIN, HIGH) does turn on the LED.

Actually the LED is just a visual indicator that the ISR is being called; inside the ISR, I cannot use Serial.print(), so I am turning on the LED for debugging.
 
  • #8
EUREKA! Found the problem. And the solution.

In Arduino, not all pins can receive interrupts:

1608588039327.png


Changed the interrupt pin to 2, and now the code works fine.
 
  • Informative
Likes Tom.G

1. Why aren't my interrupts in Arduino working for detecting zero crossing?

There could be several reasons for this issue. One common reason is that the interrupt pin is not connected properly. Make sure the interrupt pin is connected to the correct pin on your Arduino board.

2. How do I know if my interrupts are enabled in Arduino?

You can check if interrupts are enabled by using the Arduino function "interrupts()". If it returns a value of 1, then interrupts are enabled. If it returns a value of 0, then interrupts are disabled.

3. What is the purpose of using interrupts for detecting zero crossing in Arduino?

Interrupts allow the Arduino to respond immediately to a specific event, in this case, the zero crossing signal. This can improve the accuracy and efficiency of your code, as the Arduino does not have to constantly check for the zero crossing signal.

4. Can I use any pin for interrupts in Arduino?

No, not all pins on an Arduino board can be used for interrupts. Only specific pins, usually labeled as "interrupt pins", can be used for interrupts. Refer to your Arduino board's documentation to find out which pins can be used for interrupts.

5. How can I troubleshoot if my interrupts are still not working for detecting zero crossing?

If you have checked all the connections and code, and interrupts are still not working, you can try using a different interrupt pin. You can also try using a different Arduino board to see if the issue is with the hardware. Additionally, checking for any interference or noise in the zero crossing signal may also help troubleshoot the issue.

Similar threads

Replies
5
Views
946
  • Electrical Engineering
Replies
3
Views
8K
  • Electrical Engineering
Replies
5
Views
3K
  • Programming and Computer Science
Replies
2
Views
2K
Replies
22
Views
2K
  • Computing and Technology
Replies
1
Views
6K
  • Engineering and Comp Sci Homework Help
Replies
8
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
9
Views
1K
  • Electrical Engineering
4
Replies
138
Views
22K
Replies
3
Views
10K
Back
Top