Pause While loop by IRQ

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
Jerremy09
Posts: 28
Joined: Wed May 08, 2019 7:40 am

Pause While loop by IRQ

Post by Jerremy09 » Mon Mar 30, 2020 11:01 am

Hello,

is there a way how to pause "While loop" by IRQ signal and then continue back in while?

Reason:
I have an external signal connected to one of the pins (counting number of signals), this part of code is supposed to work while the time the "While loop" operates another part of code. and if Counter reaches a specific amount then break "While Loop".

Thank you

Jan Vaško

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Pause While loop by IRQ

Post by jimmo » Mon Mar 30, 2020 11:51 am

hi,

Not completely sure I understand what you're asking, but can you set a global flag in your IRQ that enables/disables the while loop's contents.

i.e.

Code: Select all


enabled = True

def irq_handler():
  global enabled
  enabled = not enabled
  
def main():
  while True:
    if not enabled:
      continue
    # do the main program thing
    counter += 1
    if counter == N:
      break

main()
On some ports, you could experiment with lightsleep/wfi to "sleep" the loop (instead of the "continue") but best get it working first.

Jerremy09
Posts: 28
Joined: Wed May 08, 2019 7:40 am

Re: Pause While loop by IRQ

Post by Jerremy09 » Mon Mar 30, 2020 12:56 pm

Hi,

thank you for the reply. think is that during while cycle inside "Move_MR.py" the designed IRQ "Stepp_Count" is not triggered:

- first IRQ is done on display by xpt2046 (works well)
- second IRQ should be done by Stepp_Count
- PIN25 and PIN26 are physically connected by wire

Program:
boot.py:

Code: Select all

Empty
main.py:

Code: Select all

def touch_ON(pin):
    #Touch
    stisk = ts_touch.raw_touch()

    #Search
    if stisk!=None:
        print("Touched")
        import Move_MR
        Move_MR.Start()

import machine
import xpt2046
spi = machine.SPI(1, baudrate=2000000, polarity=0, phase=0, miso=machine.Pin(19), mosi=machine.Pin(23), sck=machine.Pin(18))
ts_touch = xpt2046.XPT2046(spi = spi, confidence=5, margin=50, delay=10)

#Display
ts_bussy = machine.Pin(0, machine.Pin.IN)
ts_bussy.irq(handler=touch_ON)

print("Main Finished")
Move_MR.py

Code: Select all

def Start():
    def Count(pin):
        nonlocal Counter
        Counter = Counter + 1
        print("Counting each PWM: "+str(Counter))
        if Counter == 100:
            Step.deinit()

    import machine
    import time
    Stepp_Count = machine.Pin(26, machine.Pin.IN)
    Stepp_Count.irq(handler=Count, trigger=machine.Pin.IRQ_FALLING)
    Step = machine.PWM(machine.Pin(25, machine.Pin.OUT))
    
    Counter = 0
    speed = 200

    while True:
        import Motor_Move
        Motor_Move.Start_Movement(speed)
        print("Counter: "+str(Counter))
        time.sleep(1)
        speed = speed - 1
        if speed == 0:
            break
Motor_Move.py

Code: Select all

def Start_Movement(speed):
    import machine
    Step = machine.PWM(machine.Pin(25, machine.Pin.OUT))
    Step.deinit()
    Step.init()
    Step.freq(speed)
    Step.duty(512)
Result:
REPL:
1) printed text "Touched" (by IRQ in main.py)
2) Continuous printing of text "Counter: 0"

>>>Touched
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
Counter: 0
...

--> there is no interruption by IRQ which would increase Counter + print text "Counting each PWM: " and then continue with While cycle to finish the main program on Move_MR.py

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Pause While loop by IRQ

Post by jimmo » Tue Mar 31, 2020 1:15 am

Hi,

I think the core issue here is that you're doing all the program logic inside IRQ context. It looks like this must be ESP32 (i.e. soft interrupts) which is why this works at all, but in general the rule is: do the absolute minimum in interrupt handlers.

See http://docs.micropython.org/en/latest/r ... rules.html

That doc is mostly written with "hard" interrupt handlers in mind, but on ESP32 they're soft which means they're implicitly scheduled by micropython.schedule. What this means is that while you're currently in an interrupt handler, another one cannot be scheduled. There's a scheduler queue, but scheduled tasks can only interrupt the "main" thread, not other scheduled tasks.

So the while loop in Start prevents Count from being able to run.

What you need to do instead is think of this like a state machine. The interrupt handlers should only set flags or increment counters (no loops or delays), while your main loop looks at these flags and counters and does the appropriate actions.

Even better would be to use asyncio, which might be worth looking into. https://github.com/peterhinch/micropyth ... UTORIAL.md

Post Reply