Page 1 of 1

External interrupts, different behavior between Arduino and MicroPython

Posted: Sun Oct 18, 2020 5:11 pm
by donVictorio
Hi,

I use ESP8266 NodeMcu V3 board and built circuit similar to this one https://i.ytimg.com/vi/eFeOSiL-IBQ/hqdefault.jpg
At the beginning I tried to count "frequency"
In code bellow i expected -/+ 100 ticks per second (50Hz), but I got 200-208.

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)    

import machine
import time
from machine import Pin

counter = 0

def handler(pin):
    global counter
    counter += 1
    
pin = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
pin.irq(trigger=Pin.IRQ_RISING, handler=handler)

while (True):
    time.sleep_ms(1000)
    print(counter)
    counter = 0
I created similar C++ code and the same circuit works as expected.

Code: Select all

int counter = 0;

void setup() {
  Serial.begin(115200);   
  pinMode(12, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(12), zcDetect, RISING);
}

void loop() {
    delay(1000);
    Serial.println(counter);
    counter = 0;
}

ICACHE_RAM_ATTR void zcDetect() {
  counter += 1;
}

Why is that?
Any suggestions?

Re: External interrupts, different behavior between Arduino and MicroPython

Posted: Sun Oct 18, 2020 5:48 pm
by Roberthh
On ESP8266 with MicroPython I have seen multiple trigger at slow ramps. That could happen here. So you have to either increase the slope of the signal, e.g. with a schmitt-trigger gate, or you could try to clear the second interrupt in the ISR. In my application I choose the second way (see code below). But that might not work in your case, if the slope is too slow.

Code: Select all

#
# Clear Interrupt status
#
@micropython.viper
def clear_isr(mask: int):
    ptr32(0x60000324)[0] = mask
It was called with
clear_isr(0x20) # clear interrupt mask of Pin(5)
You have to change the 0x20 value according to the pin you use.

Re: External interrupts, different behavior between Arduino and MicroPython

Posted: Mon Oct 19, 2020 5:23 pm
by donVictorio
Thank you for your suggestion Roberthh.

Before I posted this topic, I had read and followed your suggestion from this one viewtopic.php?f=2&t=6840#p38861 clearing the second interrupt. But result was the same.
In the end of the "handle routine" when I call clear_isr there is no "waiting" interrupt.

I measure time in microseconds between each call and receive results like this:
call no|result
1|
2|9580
3|238! (this should not take place)
4|9790
5|211! (this should not take place)

I expected :
1|
2|9580
3|9790
It is "crossing zero" interval for 50hz.

And this is what i get using Arduino C++ code.
This is something that puzzles me.

Right now i don't have possibilities to test it using "Schmitt-Trigger gate"

Re: External interrupts, different behavior between Arduino and MicroPython

Posted: Tue Oct 20, 2020 6:06 am
by pythoncoder
I wonder if this would best be done using polling. The idea being that you respond to the first transition on the line and ignore the rest. Pseudocode:

Code: Select all

while True:
    wait for pin to assume ON state
    t = ticks_ms()  # Get run time.
    wait for correct phase (ensure < 10ms)
    trigger output
    trun = ticks_diff(ticks_ms, t)
    if trun < 7:
        sleep_ms(7 - trun)  # Now nearing end of half cycle
Here I'm measuring run time but another option may be to calculate it.

It's perhaps worth noting that ESPx aren't the best platforms for applications requiring ms level timing.

Re: External interrupts, different behavior between Arduino and MicroPython

Posted: Tue Oct 20, 2020 2:50 pm
by donVictorio
Thanks for yours suggestions.

Over last few days i tried to solve this problem using software approach by codding, flashing ect... without any success.
Finally inspired by Roberthh i created hardware solution based on NPN

... but i still dont know why the same circuit behaves differently, driven by C ++ and MicroPython

Re: External interrupts, different behavior between Arduino and MicroPython

Posted: Wed Oct 21, 2020 10:53 am
by pythoncoder
Nor do I. But slow signals on interrupt pins are a bad idea on any hardware. At the very least the outcome will be sensitive to electrical noise.