External interrupt is delaying after a while
Basic Infos
- [x] This issue complies with the issue POLICY doc.
- [x] I have read the documentation at readthedocs and the issue is not addressed there.
- [ ] I have tested that the issue is present in current master branch (aka latest git).
- [x] I have searched the issue tracker for a similar issue.
- [x] If there is a stack dump, I have decoded it.
- [x] I have filled out all fields below.
Platform
- Hardware: [ESP-12]
- Core Version: [2.6.3]
- Development Env: [PlatformIO]
- Operating System: [Linux Mint]
Settings in IDE
- Module: [Generic ESP8266 Module]
- Flash Mode: [dio]
- Flash Size: [4MB]
- lwip Variant: [Higher Bandwidth]
- Reset Method: [nodemcu]
- Flash Frequency: [40Mhz]
- CPU Frequency: [80Mhz]
- Upload Using: [OTA]
Problem Description
I'm having a trouble with external interrupt measuring zero cross in AC 60 Hz. In high level, my trouble is that my lamp after a while turn off per 2 seconds and turn on again. The frequency for this problem to occur is variable, so 3 times per day, twice/day, sometimes working two days consecutive without problem. I am monitoring the problem over osciloscope and I captured the image below:
Line yellow: hardware zero cross
Line green: LED inverting each zero crossing (60 Hz - frequency, 16,666 ms - period)
It seems that my ISR keeps accumulating and after a while releases a bunch of execution at once. I already got this same problem with software timer. I think this problem is because some task in wifi is harding and the priority wifi is high over external interrupt. Someone has any idea about the solution to this problem? I tried include noInterrupts() and interrupts() inside my ISR but it isn't successfull. Thanks folks
MCVE Sketch
#include <Arduino.h>
bool flagInvert{false};
static void ICACHE_RAM_ATTR ZeroCrossISR(void)
{
noInterrupts();
digitalWrite(2, flagInvert);
flagInvert ^= 1;
// some logical that isn't relevant to problem
interrupts();
}
void setup() {
pinMode(5, INPUT);
pinMode(2, OUTPUT);
attachInterrupt(5, ZeroCrossISR, FALLING);
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.begin("MY_SSID", "MY_PASS");
}
void loop() {
}
Your code is wrong, you're always setting the same value without changing it.
Your code is wrong, you're always setting the same value without changing it.
Sorry, I wrote on the fly here, but the correct is:
#include <Arduino.h>
bool flagInvert{false};
static void ICACHE_RAM_ATTR ZeroCrossISR(void)
{
noInterrupts();
digitalWrite(2, flagInvert);
flagInvert ^= 1;
// some logical that isn't relevant to problem
interrupts();
}
void setup() {
attachInterrupt(5, ZeroCrossISR, FALLING);
}
void loop() {
}
@fpalarminiscenario - It also looks like you missed setup calls to pinMode. Details are fuzzy to me, I believe with core version 2.6.3 the SDK may use previously saved WiFi credentials unless you have additional code to prevent that. With the current core, the sketch would default to WiFi off.
@fpalarminiscenario - It also looks like you missed setup calls to
pinMode. Details are fuzzy to me, I believe with core version 2.6.3 the SDK may use previously saved WiFi credentials unless you have additional code to prevent that. With the current core, the sketch would default to WiFi off.
Yes, I omitted simple code like pinMode and WiFi.begin because I believe this isn't relevant to the main problem that is strange behaviour on external interrupt...
This is only to demonstrate the device running correctly:
And sometimes, this problem occur, as if the ISR kept accumulating:

And, after around 2 seconds, the ISR is stable again
In sketch pinMode is very important. If you don't set pinMode correctly your sketch don't work fine.
On Mon, 28 Nov 2022, 19:28 fpalarminiscenario, @.***> wrote:
This is only to demonstrate the device running correctly: [image: 20221128_151752] https://user-images.githubusercontent.com/67068566/204351593-f44e29c1-67c0-41d7-af6b-9684948194bb.jpg And sometimes, this problem occur, as if the ISR kept accumulating: [image: 20221123_085751] https://user-images.githubusercontent.com/67068566/204352300-a807bdb7-adb0-4a57-8c1f-675f2ebc0eee.jpg
— Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/8730#issuecomment-1329551728, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIPMDFE6P6PUEUVNTYRULQTWKT2TBANCNFSM6AAAAAASLKBKM4 . You are receiving this because you are subscribed to this thread.Message ID: @.***>
In sketch pinMode is very important. If you don't set pinMode correctly your sketch don't work fine.
Ok, I updated the code. But, how I said, this isn't relevant to the problem.
this isn't relevant to the problem.
We can't know, or whether that you have tried and dismissed at as irrelevant. Discussion about what's relevant and what's not is another side effect of omitting certain parts:)
I'd suggest to look at WiFi state first, as mentioned in the https://github.com/esp8266/Arduino/issues/8730#issuecomment-1329337477 You'll have to use 4.x.x platform instead of 2.6.3
I'd suggest to look at WiFi state first, as mentioned in the #8730 (comment) You'll have to use 4.x.x platform instead of 2.6.3
4.x.x? The latest version is 3.0.2, isn't? Or this version that you mentioned isn't core version?
Ok, I will update, but I didn't want to update without know the root of problem. I saw this same problem with software timer, so, I thought that more people had this problem. But, as nobody had this problem, I think the latest version won't work.
We can't know, or whether that you have tried and dismissed at as irrelevant. Discussion about what's relevant and what's not is another side effect of omitting certain parts:)
Yes, indeed, but as the problem is involving external interrupt, and to setup a interrupt I need only attachInterrupt and one callback, so I think there is nothing more that can affect the interrupt or has? This is what I want to know. I can rely on timing external interrupt or some task can damage my time precision on interrupt?
Software timer is not itself an interrupt, if you mean Ticker / ets_timer. Underlying TIMER peripheral will trigger one, yes, to notify about it's expiration but the execution itself happens in SDK aka SYS task.
WiFi driver can spend a lot of time doing things. e.g. WiFi begin() and a simultaneously started very short timer for 100ms could instead end up executing in ~1sec b/c WiFi is doing some kind of work. Pin interrupt is prone to masking or locking by anyone, you might have better time setting up TIMER1 and periodically reading the pin state.
Not using latest version we run into a problem not reliably testing things yet again. Including our change to WiFi, which you missed out on
PlatformIO uses overarching 'platform' that contains framework, toolchain, upload tools and etc. See PACKAGES when building for Core version translated to our versioning scheme from theirs.
Pin interrupt is prone to masking or locking by anyone, you might have better time setting up TIMER1 and periodically reading the pin state.
Ok, I already use hardware timer triggering triac, but I also thought this approach to read pin on my hardware timer, this will spend a considered time to adequate my source code but maybe it is the only way...
I used to have a similar problem
the problem is related to the threshold voltage value that an ISR could be fired
So the problem basically is your ISR is being fired multiple times at the same falling edge
the solution is to add a _NOP() loop for a tiny amount of time let's say for 500 iterations
OR to disable the external interrupt and re-enable it in your loop code