简体   繁体   中英

How can I use the gpiozero button.when_pressed function to use a function that inputs and outputs integers?

I'm trying to program a button on a Raspberry Pi to add an integer to another integer so that I can flip back and forth between conditions in a while loop by checking if the variable mod 2 is 0 or not. I'm essentially trying to flip the condition in the while loop by checking whether the variable is odd or even.

I'm trying to use the gpiozero library's when_pressed function, but it doesn't seem to be able to call a function that adds and outputs integers.

So, my code is:

from gpiozero import Button
btn = Button(17) #the button is wired to GPIO pin 17

def addSurf(a):
    a = a + 1
    return(a)

x = 0
btn.when_pressed = addSurf(x)

while True:
    if x == 0:
        #do some stuff
    else:
        #do some other stuff

Why I try to run this, I get TypeError: unsupported operand type(s) for +: 'Button' and 'int' .

How can I use the btn.when_pressed function to use a function that inputs and outputs integers?

Alternatively, is there some other [better?] method to make a button toggle the two states in the while loop?

It is possible to pass parameters into the gpiozero button 'when_pressed' property, but it's not very well documented. I couldn't find any examples. (Cue call for help to gpiozero creators!)

What I have done is pass a lambda function into 'when_pressed' which contains variables that I want the function to access.

Here's my version of your program:

from gpiozero import Button
from signal import pause

btn = Button(17) #the button is wired to GPIO pin 17

class X():
    value = 0


def addSurf(x):
    x.value += 1
    print('Adding 1')

def do_something_when_button_is_released(x):
    print('x = ',x.value)


x = X()
btn.when_pressed = lambda : addSurf(x)
btn.when_released = lambda : do_something_when_button_is_released(x)
pause()

I have used a class as a container for your original 'x' variable. This is probably overkill, but I tried to do the same thing with x as an integer but it didn't work! Don't really understand why. Anyway a class allows you to add more than one variable.

The other point is that the 'while True' loop won't work with this method because it hogs all the CPU time. It's better to use the function that I call 'do_something_when_button_is_released' to trigger doing other stuff.

I changed the lambda-example. It took me very long to understand the meaning of "mandatory variable" in the documentary of gpiozero. Also I googled everywhere and was disapointed about the lambda-solution here. Since I am a beginner, I like this option for parameter-transfer better than learning lambda.

from gpiozero import Button
from signal import pause

class X():
    value = 0

def addSurf(obtained_but):
    obtained_but.x.value += 1
    print('Adding 1')

def do_something_when_button_is_released(obtained_but):
    print('x = ',obtained_but.x.value)

#attach the x to the class Button before initializing it 
Button.x = X()
btn = Button(24)  #my button is wired to GPIO pin 24

btn.when_pressed = addSurf
btn.when_released = do_something_when_button_is_released
pause()

I realized that the button.when_pressed function can't take any arguments.

To accomplish my original goal of having the button toggle between two different states in a while loop, I ended up having the button toggle the sign of an integer as a global variable in its own thread in a while loop, and having that sign of the global variable toggle the conditions in another thread in the original while loop. This isn't really a proper way to do it, but I got it working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM