Search code examples
micropythonraspberry-pi-picorp2040

Button Inputs and polling I2C data in While loop


How can I handle button inputs in a while loop and at the same time refresh i2c data in a timely manner?

A while loop that watches for changes on the button pins can be run very quickly so that it is responsive, but I also want to update the i2c data once second. If I use time.sleep(1) at the end of the while loop, this is too slow of a reaction time for the buttons.

Code would look something like:

from machine import Pin
from time import sleep

up_button = Pin(13, Pin.IN)  

while True: 
  
  logic_state = up_button.value()
  if logic_state == True:
        print("Button Pressed") 
  else:

  update_ic2_data() # polling the i2c device for new data
  time.sleep(1) # sleeping for 1 second which is a good speed for i2c, but not very responsive for the button inputs. 

Solution

  • You can use an interrupt handler to detect the button press and change the state of a global variable to let the code inside your while loop know when to respond to it.

    up_pressed = False
    
    def handle_up_press:
      global up_pressed
      up_pressed = True
    
    up_button = Pin(13, Pin.IN, Pin.PULL_UP)
    up_button.irq(trigger=Pin.IRQ_FALLING, handler=handle_press)
    
    while True:
      if up_pressed:
        print("Button Pressed")
        up_pressed = False
      update_ic2_data()
      time.sleep(1)
    

    Or if the code to respond to the button press executes quickly (like changing the state of a GPIO output), you can just put it directly in the handler function. But things like longer running things print() are generally not recommended.

    See this doc for more info: https://docs.micropython.org/en/latest/reference/isr_rules.html