Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Button presses register multiple times

    Scheduled Pinned Locked Moved Expansion Board
    8 Posts 2 Posters 381 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R Offline
      robertsehlstedt
      last edited by

      Hello!
      I am right now making my LoPy4 send some data to a LoRa-gateway and change the color of the rgb light whenever I press the S1 button on my expansion board v3.1. However, it's not very responsive. The LoRa payload seems to be pretty quick, but it sometimes takes several seconds before the light changes color. Also the biggest issue is that for whatever reason, one click can sometimes register twice??

      Look here in my LoRa gateway data, this is the result of ONE button press.

      f11c4767-a06f-4114-8e1f-8c9dcca8112f-image.png

      So I pressed the button, it sent a message, and then for whatever reason it had a rising edge also 3 seconds later. This is very odd, and I am certain I did not press the button, and I have seen the same behavior when just printing inside the button callback function.

      This is the code for the button. I have tried using PULL_DOWN instead to see if there were some floating values fucking me over, but it had the same behavior.

      btn = Pin('G17', mode=Pin.IN, pull=Pin.PULL_UP)
      btn.callback(trigger=Pin.IRQ_RISING, handler=rnd_triage)
      
      robert-hhR 1 Reply Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @robertsehlstedt
        last edited by

        @robertsehlstedt buttons use to bounce, so there may be various events in ms time distance, which have bee registered and processed later. Since a server may respond to any message after one or two seconds, the LoRa stack most likely waits for that time before sending the next message. The three seconds you see is well within the uncertainty of the time taking.

        R 2 Replies Last reply Reply Quote 2
        • R Offline
          robertsehlstedt @robert-hh
          last edited by

          @robert-hh Alright thanks! Is there some way to avoid it?

          1 Reply Last reply Reply Quote 0
          • R Offline
            robertsehlstedt @robert-hh
            last edited by

            @robert-hh Also I do want to say, to clear up any confusions here - that if I just make a button callback function which prints "Button pressed" or something like that, actually I can clearly see that sometimes when I click the button, it will register once, and then again a few seconds later. Which means that the delay probably isn't on the server end.

            robert-hhR 1 Reply Last reply Reply Quote 0
            • robert-hhR Offline
              robert-hh @robertsehlstedt
              last edited by

              @robertsehlstedt So you tried a callback that just prints the message? Using that little script, I get quite a few responses. And the sleep in the callback causes events to seem happening later.

              #
              from machine import Pin
              from time import sleep_ms
              
              count = 0
              def rnd_triage(p):
                  global count
                  print("callback fired", count)
                  sleep_ms(1000)
                  count += 1
              
              
              while True:
                  btn = Pin('P10', mode=Pin.IN, pull=Pin.PULL_UP)
                  btn.callback(trigger=Pin.IRQ_FALLING, handler=rnd_triage)
                  sleep_ms(100)
              
              

              Besides that, I'm not saying the the problem is at the server end. The problem is local, but LoRa might not send a second message before the RX2 periods of the first message has passed, and the scheduler for callbacks might not schedule the next callback before the message sending has been finished.
              The callbacks a not ISR's. Whenever an interrupt happens, it is just registered and the callback is added to a queue and executed whenever it's time to do so. There is no guarantee for a timely service.

              R 1 Reply Last reply Reply Quote 0
              • R Offline
                robertsehlstedt @robert-hh
                last edited by

                @robert-hh I tried something similar to you and yeah I keep getting similar results where there are two button presses registered. I am not sure if I am following you, but it seems like there is nothing to be done about it? For the moment I am using the button to just demo some functionality, but in the future we will use other pins. I hope they won't have the same behaviour!

                robert-hhR 1 Reply Last reply Reply Quote 0
                • robert-hhR Offline
                  robert-hh @robertsehlstedt
                  last edited by

                  @robertsehlstedt There are many attempts for debouncing, both in software and hardware. As an example, I quick-hacked together some code, based on a time interrupt and a low pass filter.

                  #
                  from machine import Pin, Timer
                  from time import sleep_ms
                  
                  btn = Pin('P10', mode=Pin.IN, pull=Pin.PULL_UP)
                  
                  state = False
                  btn_state = 1
                  
                  LIMIT_ON = 0.1
                  LIMIT_OFF = 0.9
                  TIME_CONSTANT = 0.25
                  
                  def switch_state(p):
                      global btn_state, state
                      # low pass filtering of the input valeue
                      btn_state += TIME_CONSTANT * (btn.value() - btn_state)
                      if btn_state < LIMIT_ON:
                          if state == False:
                              print("Button pressed")
                          # may schedule something else here, like sending a message
                          state = True
                      elif btn_state > LIMIT_OFF:
                          if state == True:
                              print("Button released")
                          state = False
                  
                  alarm = Timer.Alarm(switch_state, 0.01, periodic = True)
                  
                  while True:
                      sleep_ms(100)
                  
                  
                  R 1 Reply Last reply Reply Quote 1
                  • R Offline
                    robertsehlstedt @robert-hh
                    last edited by

                    @robert-hh Thanks! I tried pulling a cable between two pins using the following code.

                    count = 0
                    def rnd_triage(arg):
                        global count
                        print("callback fired", count)
                        count += 1
                    
                    p = Pin('P13', mode=Pin.IN, pull=Pin.PULL_DOWN)
                    p.callback(trigger=Pin.IRQ_RISING, handler=rnd_triage)
                    
                    t = Pin('P12', mode=Pin.OUT, pull=None, alt=-1)
                    
                    while True:
                        time.sleep(3)
                        t.value(0)
                        time.sleep(3)
                        t.value(1)
                    

                    It seems to be working quite well at least, so maybe I will just endure the button performance for now. Thanks a lot for the help!

                    1 Reply Last reply Reply Quote 1

                    Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                    Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                    With your input, this post could be even better 💗

                    Register Login
                    • 1 / 1
                    • First post
                      Last post

                    Pycom on Twitter

                    Pycom