0

我正在气象站(树莓派)上工作,我正在使用 python。我开发了一个正在运行的程序,但现在我决定更新我的代码并构建所有内容(制作类等)。但是现在我从 gpiozero 遇到了关于 Button 的两个问题。
首先,当我尝试将函数分配给Button.when_pressed 函数或类时,按下按钮时不会调用该函数。

以下代码只是一个示例,以使代码尽可能少:

from gpiozero import Button
import time

number = 0
def function_that_gets_called():
    global number
    number += 1

def main():
    wind_sensor = Button(6)
    wind_sensor.when_pressed = function_that_gets_called

main()

while True:
    # Sleep, so the program doesn't exit immediately
    time.sleep(60)
    

# Do some other stuff with number

function_that_gets_called为什么按下按钮时不调用。同样,当我尝试when_pressed在课堂上分配时,它也不起作用。

其次,为什么我必须使用global number?否则数字变量不会被改变,但有没有另一种解决方案以更好的方式做到这一点?

十分感谢!

编辑:编辑 time.sleep(60)。我指定了,我的意思是不起作用。这是我在stackoverflow上的第一个问题,所以如果不准确,请原谅,很高兴告诉我如何改进我的问题。

4

1 回答 1

1

I'm not sure what happens to the wind_sensor when the main funtion exits after you call main(). My guess is that it will be destroyed. Anyway if you remove the main and the call to it, your code shall work. Try add a print(number) after you increment it so you can see something when you press the button

About classes for this...

I also struggled with this when_pressed inside a class. But I've made it work in my case. My application can have a variable number of buttons and they are all managed with an object that is instantiated on the beginning of the code. The application doesn't exit because has an underlying websocket client with ws.runForever(). In your case you can use a loop like while 1: pass that shall use some 12% to 15% of your CPU or pause() to keep the code running, without using processor (exit with ctrl+c)

Now I used a dict to handle the variable nº of buttons that sits inside my class, as well as my handler. Something like this can use classes, keep running and you can expand your code to have a dynamic number of buttons.

from gpiozero import Button
import json

class myController()
   theButtons={}
   yourNumber=0

   def __init__(self):
      self.yourNumber=0 #here is the right place to initialize the variables!

   def handler(self,Button): # here the first parameter is the class itself and then the button that generated the interrupt --> this works like that, but could not confirm that self needs to exist before the mandatory arg "Button" because it is inside the class, or by other reason. Can somebody confirm? not clear in documentation.
      print("Pressed button in pin: ",str(Button.pin.number))
      self.yourNumber +=1
   
   def addButton(msg): # Example json: '[{"id":"button1","pin":2},{"id":"button2","pin":4}]' the msg is the message that is received via websocket with the configuration of buttons. you can make it at you own needs. id and pin are string that I choose for machines dialog
      btns=json.loads(msg)
      for b in btns:
         theButtons[b.get('id')]=Button(b.get('pin'))
         theButtons[b.get('id')].when_pressed=self.handler 

#and that's it for the class no let's instantiate and make the code persist running

if __name__ == "__main__": # this is executed only if you call this file. if you use it as import it will not run. it's a best practice, should you need to import the class in other file and don't want the code to execute. 
   btnController=myController() 
   pause()

Classes are a bit overkill on this usecase, but I believe it solves your problem without using global variables.

于 2021-02-16T00:44:09.423 回答