ISR code example gives an error on microbit

Questions and discussion about running MicroPython on a micro:bit board.
Target audience: MicroPython users with a micro:bit.
Post Reply
rivandemo
Posts: 4
Joined: Sun Oct 27, 2019 9:52 am

ISR code example gives an error on microbit

Post by rivandemo » Sun Oct 27, 2019 10:09 am

Hello,

I found an example of using ISR on this page: https://docs.micropython.org/en/latest/ ... rules.html but when i flash it on my microbit card it generates an error "no module named pyb".

Here is the code:

Code: Select all

import pyb, micropython
micropython.alloc_emergency_exception_buf(100)
class Foo(object):
    def __init__(self, timer, led):
        self.led = led
        timer.callback(self.cb)
    def cb(self, tim):
        self.led.toggle()

red = Foo(pyb.Timer(4, freq=1), pyb.LED(1))
green = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2))
and i'm using Mu-editor 1.0.2 on Mac OSX 10.12.6 Sierra.

Btw, i had to split the first line in two import lines as multiple imports on one line is not accepted by Mu-editor.
Should i install the pyb module? And how?

Thanks for help,
Richard

shaoziyang
Posts: 363
Joined: Sun Apr 17, 2016 1:55 pm

Re: ISR code example gives an error on microbit

Post by shaoziyang » Sun Oct 27, 2019 12:37 pm

pyb module is for stm32/pyboard, microbit has no pyb module.

rivandemo
Posts: 4
Joined: Sun Oct 27, 2019 9:52 am

Re: ISR code example gives an error on microbit

Post by rivandemo » Sun Oct 27, 2019 1:22 pm

Thank you!

Is there any way i can use interrupt (ISR) on a microbit? Iaw could you tell me where i can find documentation about this?

Thanks a lot,
Richard

shaoziyang
Posts: 363
Joined: Sun Apr 17, 2016 1:55 pm

Re: ISR code example gives an error on microbit

Post by shaoziyang » Sun Oct 27, 2019 2:39 pm

microbit use nRF51822, and it has 16kb ram only. So some feather can't use in it.

Document for microbit:

https://microbit-micropython.readthedocs.io/en/latest/

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

Re: ISR code example gives an error on microbit

Post by jimmo » Sun Oct 27, 2019 11:10 pm

The micro:bit uses a different version of MicroPython -- based on v1.9.2 https://github.com/bbcmicrobit/micropython
Because it's such a small microcontroller and because it's targeted at education, a lot of features are not available, including interrupts.

Depending on how adventurous you're feeling, you can actually compile the upstream version of MicroPython for micro:bit -- https://github.com/micropython/micropyt ... /ports/nrf which will give you access to some core features like interrupts, but you will lose some other features. And you probably won't be able to use Mu, etc.

What are you trying to do, perhaps we can find a way to do it without interrupts? (I've spent a lot of time teaching with the micro:bit and while we certainly did find the lack of interrupts frustrating, we did find a lot of ways around that limitation too).

rivandemo
Posts: 4
Joined: Sun Oct 27, 2019 9:52 am

Re: ISR code example gives an error on microbit

Post by rivandemo » Mon Oct 28, 2019 4:57 pm

A few weeks ago i block-coded a simple program for my grandson to show him how to display his name on a microbit when button A was pressed and stopping the display when B was pressed. The issue was that when pressing button A again the display restarted from the beginning and not from the last character displayed. I then switched to Python and used a list and an index. The result was better but not completely satisfactory as the "button B pressed" check has to be synchronous with the "while True" loop.

I tried this:

Code: Select all

import microbit

disp = 0
index = 0
maxIndex = 5
marcelList = ["M", "A", "R", "C", "E", "L"]

while True:
    if microbit.button_a.is_pressed():
        disp = 1

    if microbit.button_b.is_pressed():
        disp = 0

    if disp == 1:
        microbit.display.show(str(marcelList[index]))
        index = index + 1
        if index > maxIndex:
            index = 0
        microbit.sleep(1000)
I searched then on Internet an interrupt-based solution..

This being said, my problem is far from being important or urgent.

Richard

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

Re: ISR code example gives an error on microbit

Post by jimmo » Tue Oct 29, 2019 1:40 am

hi Richard,

I'm not sure that interrupts necessarily make this easier.

The key thing though is that while the micro:bit is sleeping, it can't be doing anything else. So it helps to imagine how the sleep function itself works:

Code: Select all

def sleep(delay_ms):
  t = running_time()
  while running_time() < t + delay_ms:
    pass
You can kind of implement your own version of sleep into the main loop of your program. In this case we figure out when the next letter should be shown.

Code: Select all

import microbit
marcelList = ["M", "A", "R", "C", "E", "L"]
maxIndex = 5
next_letter_time = 0
disp = False
letter_delay = 1000
index = 0
while True:
  if microbit.button_a.is_pressed():
        disp = True
        next_letter_time = microbit.running_time() + letter_delay
  if microbit.button_b.is_pressed():
        disp = False
        next_letter_time = 0
  if disp and microbit.running_time() > next_letter_time:
    microbit.display.show(str(marcelList[index]))
    index = index + 1
    if index > maxIndex:
      index = 0
    next_letter_time = microbit.running_time() + letter_delay
I genererally prefer to use was_pressed unless there's a specific reason to use is_pressed. The letters can be a string too, instead of a list. So here's a simplified version -- you also kind of don't need the "disp" variable anymore because next_letter_time != 0 implies disp = True.

Code: Select all

import microbit
marcel = "MARCEL"
next_letter_time = 0
letter_delay = 1000
index = 0
while True:
  if microbit.button_a.was_pressed():
        next_letter_time = microbit.running_time() + letter_delay
  if microbit.button_b.was_pressed():
        next_letter_time = 0
  if next_letter_time > 0 and microbit.running_time() > next_letter_time:
    microbit.display.show(marcel[index])
    index = (index + 1) % len(marcel)
    next_letter_time = microbit.running_time() + letter_delay
You might want to display.clear() when b is pressed too?

FYI I wrote this blog post about this exact topic a while back for my previous employer -- there might be some useful bits. https://medium.com/groklearning/become- ... b8b4e2d747 You might find their micro:bit simulator useful too (which you can access for free by starting the micro:bit course and going to any problem -- https://groklearning.com/microbit/), I used it to test the above code.

rivandemo
Posts: 4
Joined: Sun Oct 27, 2019 9:52 am

Re: ISR code example gives an error on microbit

Post by rivandemo » Sat Nov 02, 2019 5:53 pm

Thanks a lot Jimmo,

I'll try the solution you recommend (sorry for this late answer, i have been busy these last days), and look at the two links you mention (actually i think i already followed the "Grok learning" course).

I used the "sleep" function to write this little program "quick and dirty" but i agree, i never use the equivalent function on Arduino (delay()) and always prefer the use of millis() combined with two variables (prevStep, increased each time the cycle occurs and cycleInterval, a self explanatory constant)

Thank you again,
Richard

Xarbenence
Posts: 4
Joined: Mon Jul 11, 2022 6:32 pm

Re: ISR code example gives an error on microbit

Post by Xarbenence » Fri Jul 22, 2022 11:05 pm

jimmo wrote:
Sun Oct 27, 2019 11:10 pm
The micro:bit uses a different version of MicroPython -- based on v1.9.2 https://github.com/bbcmicrobit/micropython
Because it's such a small microcontroller and because it's targeted at education, a lot of features are not available, including interrupts.

Depending on how adventurous you're feeling, you can actually compile the upstream version of MicroPython for micro:bit -- https://github.com/micropython/micropyt ... /ports/nrf which will give you access to some core features like interrupts, but you will lose some other features. And you probably won't be able to use Mu, etc.

What are you trying to do, perhaps we can find a way to do it without interrupts? (I've spent a lot of time teaching with the micro:bit and while we certainly did find the lack of interrupts frustrating, we did find a lot of ways around that limitation too).
Hi Jim. I realize this was a post from pretty far back, and a few things might've changed since then, but I have been looking for a way to incorporate interrupts into my code, too. I have a micro:bit v2, but I still don't think that interrupts have been made accessible by means of the standard micro:bit micropython version (at least, I haven't found documentation for constructing an ISR, though I did see that the API shows how to disable/enable IRQs).

I had a few questions I was wonderining if I could ask you.

You attached the link to the "upstream" micropython version. I went to the micro:bit folder, and the json file says that the code was written for the micro:bit v1. Is there a version of code for the micro:bit v2? Also, what features would you lose if you were to use this version of micropython, and what all features would you gain aside from interrupts?

My final question was: what methods do you implement to get around the limitation? I saw that you said you have spent a lot of time teaching with the micro:bit, so any tips, techniques, etc. you'd be willing to share would be highly appreciated.

I am seeking to construct ISRs that are triggered by pins being pulled to digital high. I have considered simply using an if statement that checks the pins' states in an infinite while loop, but I desire to have some level of priority. The micro:bit V2 is pretty fast, at 64MHz, so the if statements would probably work, but I know that using interrupts would be the most efficient approach to what I want to do.

Thanks much.

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

Re: ISR code example gives an error on microbit

Post by jimmo » Thu Aug 11, 2022 1:41 am

Xarbenence wrote:
Fri Jul 22, 2022 11:05 pm
I went to the micro:bit folder, and the json file says that the code was written for the micro:bit v1. Is there a version of code for the micro:bit v2?
We haven't done a microbit v2 board upstream yet. I should have made that more clear sorry. It's not a small amount of work.
Xarbenence wrote:
Fri Jul 22, 2022 11:05 pm
My final question was: what methods do you implement to get around the limitation? I saw that you said you have spent a lot of time teaching with the micro:bit, so any tips, techniques, etc. you'd be willing to share would be highly appreciated.
Most of my teaching experience has been with primary and high school students, where polling hasn't been too much of an issue. The general approach is usually along the lines of having a tick() method that you call from the outer loop that checks for pin changes and calls the appropriate handlers. It's still possible to implement priority by polling.

The other approach is via state machines, where detecting a pin being high (or low) is the trigger to move to the next state. i.e. the change detection is implicit in the state transitions.

Post Reply