Search code examples
bbc-microbit

Why can't the micro:bit detect multiple button presses before returning?


I'm working on a program for the micro:bit when each button calls a different function. I have found that if I press button A twice, it will not fire an event for the second press until the called function has returned. This causes an issue with my program's logic because A is a start function and B is a stop function, so pressing A > A > B results in funcA > funcB > funcA

I have read the page about the reactive system but this doesn't help me understand why this issue occurs. I have stepped through the program and can confirm the sequence.

Here's a screenshot of my code: enter image description here

Steps to reproduce:

  1. Press button A, onButtonAPressed is called, this starts the sequence and the display starts to increment
  2. Press button A, nothing happens
  3. Press button B, onButtonBPressed is called, this triggers the stop sequence and the display starts to decrement
  4. startUp sees that the isStopping flag is set and returns
  5. onButtonAPressed is called and the sequence starts increment again until it reaches the limit

This isn't the desired behaviour and I guess I need to find a workaround, but I'd like to understand why onButtonAPressed isn't called until after startUp returns. Any help would be appreciated.


Solution

  • From the micro:bit documentation at: https://lancaster-university.github.io/microbit-docs/concepts/#queued-events

    By default, the runtime will queue any events for your event handler until it has finished what its already doing. As soon as your handler is finished processing an event, the next one will be delivered (any other event handlers will be unaffected though - just because one event handler is busy, doesn't mean that another one can't receive its events!).

    The way you have written the code you are starting a long sequence of commands with the button presses that doesn't return until the count is complete or the other button is pressed.

    Meaning that when you press button A for the second time it can't be executed because the first execution hasn't finished so it is put in a queue.

    When you press button B that is executed while button A code is still executing. Because of the changing of isStarting and isStopping you see the code briefly start to count down. However, as isStopping is now true, button A code will end. This means the button A execution that is in the queue can start which changes the values of isStopping and isStarting. This will cause button B code to end, leaving only the button A code running.

    This can be fixed by having the button A code and button B code be very brief and return quickly. For example, by only changing the values of isStopping and isStarting in the button code blocks. Then having a main loop (a forever block) in your code which will look at the variables and increment/decrement accordingly.

    Below is an example of how you can achieve what you want with a forever block. This allows the direction of the count to be changed before it has completed.

    Example with forever block

    The functions can be called from the forever block if you want to use them. Example with functions