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:
Steps to reproduce:
onButtonAPressed
is called, this starts the sequence and the display starts to incrementonButtonBPressed
is called, this triggers the stop sequence and the display starts to decrementstartUp
sees that the isStopping
flag is set and returnsonButtonAPressed
is called and the sequence starts increment again until it reaches the limitThis 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.
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.
The functions can be called from the forever
block if you want to use them.