micropython icon indicating copy to clipboard operation
micropython copied to clipboard

Docs - Add discussion on how to detect "simultaneous" press on button a and b

Open kamar535 opened this issue 8 years ago • 5 comments

Problem: In an event loop, detect whether button a and button b was pressed "at the same time", only button a was pressed or only button b was pressed.

First attempt.

while True:
    
    if button_a.was_pressed() and button_b.was_pressed():
        display.show(Image.HAPPY)
    elif button_a.was_pressed():
        display.show(Image.ARROW_W)
    elif button_b.was_pressed():
        display.show(Image.ARROW_E)

This fails for two reasons.

  1. There is not enough time for a human user to press buttons a and b "at the same time", the event loop executes to fast.
  2. If only button a is pressed, button_a.was_pressed() and button_b.was_pressed() evaluates to False but as a result of the call button_a.was_pressed() the next call to button_a.was_pressed() in the elif branch evaluates to False.

The below solution solves both of the above problems.

from microbit import *

while True:
    # Solves issue 1
    sleep(50)  # How long sleep is "just enough"?
    
    # Solves issue 2
    (a, b) = (button_a.was_pressed(), button_b.was_pressed())
    
    if a and b:
        display.show(Image.HAPPY)
    elif a:
        display.show(Image.ARROW_W)
    elif b:
        display.show(Image.ARROW_E)

Would be nice if a discussion about this with a working example could be added to the docs, here http://microbit-micropython.readthedocs.io/en/latest/tutorials/buttons.html or here http://microbit-micropython.readthedocs.io/en/latest/button.html#

kamar535 avatar Sep 22 '17 19:09 kamar535

IMO the docs are not the right place for this. The docs should have a complete reference of available functionality, plus some helpful examples. But if many little use cases are added then the docs will get too big, users will be less likely to read them and less likely to find what they need in them.

Examples like the one here are IMO better suited for a 3rd-party provided tutorial, a blog, forum or stack overflow.

dpgeorge avatar Sep 25 '17 05:09 dpgeorge

You have a point @dpgeorge, especially regarding the API documentation. But IMO examples like this could serve a purpose in the tutorial part of the docs.

kamar535 avatar Sep 25 '17 09:09 kamar535

How does this compare to what the micro:bit does with the blocks API, which does have an "A+B" function already?

nealmcb avatar Oct 09 '19 22:10 nealmcb

This is the only discussion I could find regarding detection of a simultaneous press of buttons A and B. The standard documentation does I think have an "a and b" logical operator example for is_pressed which fails as kamar535 says due to loop execution timing - thanks for starting the thread.

The given example worked, but was still a bit glitchy for me in terms of detection of the simultaneous press. I used the following, which was robust, though more complex. Essentially the logic is that a simultaneous press is not possible in reality - either it's A then quickly B, or B then A, and you need to decide how long to allow for the human to do that in the interval - below example has 3 x 100 = 300ms but pick what works for you. Any longer than that, and it's a press of A then a press of B, not A and B "simultaneously". Obviously, the below blocks during that 300ms interval - not sure this can be worked around, given the need to wait for the human to press the other button.

from microbit import *

while True:
    if button_a.is_pressed():
        for x in range(100):
            sleep(3)
            b_pressed = 0
            if button_b.is_pressed():
                b_pressed = 1
                display.show(Image.SAD)
                sleep(1000)
                display.clear()
                break
        if b_pressed == 0:
            display.show(Image.HAPPY)
            sleep(1000)
            display.clear()
            
    elif button_b.is_pressed():
        for x in range(100):
            sleep(3)
            a_pressed = 0
            if button_a.is_pressed():
                a_pressed = 1
                display.show(Image.SAD)
                sleep(1000)
                display.clear()
                break
        if a_pressed == 0:
            display.show(Image.ASLEEP)
            sleep(1000)
            display.clear()

haksterays avatar Feb 12 '20 22:02 haksterays

what do you mean the first 1 doent work? i just tried it and it works perfectly.

yourgarbagehaha avatar Nov 22 '22 21:11 yourgarbagehaha