smalldragoon
Posts: 6
Joined: Mon Sep 18, 2017 4:02 pm

GPIOZero - 2 fonction for same GPIO ?

Mon Sep 18, 2017 4:16 pm

Hello !
I'm a new user of Raspberry and I'm now playing with the GPIOZero library.
So far so good, when I try to use 4 different pin to simulate 4 arrow keys with buttons, everything works properly.
Now, I would like to use as well 2 of the pins keeping them old let's say for 1 sec .

first , I'm already blocked using only 1 button :
When I define a second check for my GPIO pin, it says that it is already use ( indeed as it is monitoring for a single push )

My final goal is : if I press the 2 button simulteanously during 1 sec, it generate "enter" as ex ( through the pyautogui library )

Is there something I'm missing here ? a trick to have both working ? Code below to be more understandable
Thx !!

Code: Select all


from gpiozero import Button
from signal import pause
import pyautogui

def send_l():
   pyautogui.press('left')

def send_r():
   pyautogui.press('right')

def send_u():
   pyautogui.press('up')


def send_d():
   pyautogui.press('down')

def send_ok():
   pyautogui.press('enter')

bleft = Button(4)
bright = Button(17)
bup = Button(27)
bdown= Button(22)
b_ok = Button(4, hold_time=1)

bleft.when_pressed = send_l
bright.when_pressed = send_r
bup.when_pressed = send_u
bdown.when_pressed = send_d

b_ok.when_held = send_ok

pause()


User avatar
thagrol
Posts: 1777
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Mon Sep 18, 2017 7:50 pm

You can use when_pressed and when_held on the same Button object. But you will get both on a hold.

Have a look at the cmdbutton class here https://github.com/thagrol/pwdgen/blob/master/pwdgen.py for one way to detect short and long button presses.

There's code in there you won't need but it should point you in one possible direction.

Haven't needed to solve you final step so not able to help with that.

In my code referenced above, the when_pressed callback function stores the time. The when_released function calculates the elapsed time and fires the short press action or does nothing depending on how much time has elapsed. The hold action is handled by the when_held callback though you could do this within the when_released function.
This space unintentionally left blank.

User avatar
LetHopeItsSnowing
Posts: 357
Joined: Sat May 26, 2012 6:40 am
Location: UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Tue Sep 19, 2017 8:29 am

You need to use the same Button object for both the pressed and held events. i.e.there is only 1 button so you only have 1 object.

Code: Select all

from gpiozero import Button
from signal import pause
import pyautogui

def send_l():
   pyautogui.press('left')

def send_r():
   pyautogui.press('right')

def send_u():
   pyautogui.press('up')

def send_d():
   pyautogui.press('down')

def send_ok():
   pyautogui.press('enter')

bleft = Button(4, hold_time=1)
bright = Button(17)
bup = Button(27)
bdown= Button(22)

bleft.when_pressed = send_l
bright.when_pressed = send_r
bup.when_pressed = send_u
bdown.when_pressed = send_d

bleft.when_held = send_ok

pause()
When you press and hold the left button you are going to get 2 messages, 1 saying "left" and 1 saying "ok".

If you want to differentiate between a short press and a long press, you might be better using when_released rather than when_pressed. If you use when_released you can check the active_time to see how long the pressed was pressed for. If the time it was pressed for is less than the hold_time you could consider it a short press.

Code: Select all

def released():
    print("released after {} seconds".format(but.active_time))
    if but.active_time < but.hold_time:
        print("this is a short press")

def held():
    print("button held")
    print("this is a long press")

but = Button(4, hold_time=1)
but.when_released = released
but.when_held = held

Fyi - I wrote the code blind and it hasnt been tested, but hopefully you get the idea.

Mart
"am I getting slower, or is stuff more complicated; either way I now have to write it down - stuffaboutcode.com"

User avatar
thagrol
Posts: 1777
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Tue Sep 19, 2017 3:47 pm

There's an active_time property? Didn't see that in the documentation! Would simplify my code referenced above.
This space unintentionally left blank.

User avatar
LetHopeItsSnowing
Posts: 357
Joined: Sat May 26, 2012 6:40 am
Location: UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Wed Sep 20, 2017 7:51 am

Yes.

Its a little 'hidden' in the documentation but it is there. Its actually part of the EventsMixin which is inherited by DigitalInputDevice which is inherited by Button!

There is a clue on the held_time property of button https://gpiozero.readthedocs.io/en/stab ... .held_time.

One of the challenges is that the gpiozero docs dont show inherited methods and properties, I assume, to make them simpler to read and digest as they would be considerably bigger.

Fyi - I knew it was there as I submitted the pull request for the Button 'held' events, although I'm not sure I would recognise any of my code (it was changed a lot)!
"am I getting slower, or is stuff more complicated; either way I now have to write it down - stuffaboutcode.com"

User avatar
thagrol
Posts: 1777
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Wed Sep 20, 2017 12:15 pm

Excelent. Thanks.
This space unintentionally left blank.

smalldragoon
Posts: 6
Joined: Mon Sep 18, 2017 4:02 pm

Re: GPIOZero - 2 fonction for same GPIO ?

Mon Sep 25, 2017 3:27 pm

Hello All,
Thanks for all the answers ! I did a lot of tests before re-posting ...
I tried to do few tests and seems that I have an issue in my GPIOZERO
here is the status :

I'm using python3 ( ie: python3 {name of my script} )
I indeed run it as root
I though to a failure of my GPIO, so tried again with an old sript, it's working perfectly
I checked and my gpiozero version is 1.4.0
pigpio/stable,now 1.60-1 armhf [installed]
python-gpiozero/stable,now 1.4.0 all [installed]
python-gpiozero-doc/stable 1.4.0 all
python-pigpio/stable,now 1.60-1 all [installed]
python-rpi.gpio/stable,now 0.6.3~jessie-1 armhf [installed]
python3-gpiozero/stable,now 1.4.0 all [installed]
python3-pigpio/stable,now 1.60-1 all [installed]
python3-rpi.gpio/stable,now 0.6.3~jessie-1 armhf [installed]
raspi-gpio/stable,now 0.20170105 armhf [installed]
running this code below , as soon as I generate my input on pin 4 , I have :

Code: Select all

def released():
    print("released after {} seconds".format(but.active_time))
    if but.active_time < but.hold_time:
        print("this is a short press")

def held():
    print("button held")
    print("this is a long press")

but = Button(4, hold_time=1)
but.when_released = released
but.when_held = held
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 213, in _call_when_changed
super(RPiGPIOPin, self)._call_when_changed()
File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 268, in _call_when_changed
method()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 327, in _fire_events
self._fire_deactivated()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 360, in _fire_deactivated
super(HoldMixin, self)._fire_deactivated()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 306, in _fire_deactivated
self.when_deactivated()
File "forum.py", line 6, in released
if but.active_time < but.hold_time:
TypeError: unorderable types: NoneType() < float()

What does it mean ? it is not explicitley stating an error, but I guess it shouldn't list all this ...
what am I missing ?
Thx !

scotty101
Posts: 3680
Joined: Fri Jun 08, 2012 6:03 pm

Re: GPIOZero - 2 fonction for same GPIO ?

Mon Sep 25, 2017 3:49 pm

What is the output of the following line from your code?

Code: Select all

print("released after {} seconds".format(but.active_time))
I'm no gpiozero expert but I think you need to do something with EventsMixin to use active_time.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

smalldragoon
Posts: 6
Joined: Mon Sep 18, 2017 4:02 pm

Re: GPIOZero - 2 fonction for same GPIO ?

Wed Sep 27, 2017 7:56 am

Hi
From my understanding, there is no output as the code is not able to calculate the time , no ?

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: GPIOZero - 2 fonction for same GPIO ?

Wed Sep 27, 2017 8:13 am

The error message is quite clear in explaining the problem.

You are trying to see if but.active_time is less than but.hold_time. The problem is that but.active_time has a value of None. You can't compare None to a numerical value hence the error (actually, I think python 2 allows this but python 3 doesn't...).

You may need to follow Scotty101's advice to get active_time working.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

smalldragoon
Posts: 6
Joined: Mon Sep 18, 2017 4:02 pm

Re: GPIOZero - 2 fonction for same GPIO ?

Fri Sep 29, 2017 2:45 pm

Hello All,
I still don't get it, sorry
searched on official document from GPIOZero :
The length of time (in seconds) that the device has been active for. When the device is inactive, this is "none"
-> my undestanding is that when the button is released, value is set back to none
So, I tried to define a variable to store the value of active_time, but still get "none" as value
I guess there is something in the basis I'm not understanding.
Help much appreciated :D
thx !

@elpapaguayo : I understand the comparison, what I don't get is why active_time is always set to none

CyberGyver
Posts: 2
Joined: Sat Sep 30, 2017 1:09 am

Re: GPIOZero - 2 fonction for same GPIO ?

Sat Sep 30, 2017 2:14 am

The value of active_time is always "None" for me, but this code does the job:

Code: Select all

#!/usr/bin/env python3
from gpiozero import Button
from signal import pause
import time

# Physical pin 40 = BCM pin 21. Button hold time 2 seconds.
button = Button(21, hold_time=2)

def pressed():
    global press_time
    press_time = time.time()
    print("pressed at %s" % (press_time))

def released():
    release_time = time.time()
    pressed_for = release_time - press_time
    print("released at %s after %.2f seconds" % (release_time, pressed_for))
    if pressed_for < button.hold_time:
        print("this is a short press")
        # do stuff

def held():
    print("this is a long press")
    # do different stuff

button.when_pressed = pressed
button.when_released = released
button.when_held = held

pause()
Last edited by CyberGyver on Mon Oct 02, 2017 4:47 pm, edited 1 time in total.

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: GPIOZero - 2 fonction for same GPIO ?

Sat Sep 30, 2017 10:08 am

I guess I'm missing something here. Wouldn't active_time return the amount of time the button has been held while it is being held and, once the button is released, the relevant time is now in hold_time (and active_time is None as the button is now inactive)? If that's the case then comparing them doesn't make much sense to me.

I've never used gpiozero so I'm happy to be educated but I've taken a quick look at the source and docs and that's my understanding.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

User avatar
thagrol
Posts: 1777
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Sat Sep 30, 2017 10:54 am

held_time only counts "from the first execution of the when_held event" so will likely be None if the button is released before hold_time has passed. Or indeed once the button has been released at all.

You might have better luck with my code referenced above. (Store the time on press, compare to time on release and fire action depending on how much time has passed).
This space unintentionally left blank.

User avatar
thagrol
Posts: 1777
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK
Contact: Website

Re: GPIOZero - 2 fonction for same GPIO ?

Sat Sep 30, 2017 11:03 am

smalldragoon wrote:
Fri Sep 29, 2017 2:45 pm
@elpapaguayo : I understand the comparison, what I don't get is why active_time is always set to none
Just my 2 cents worth but, because once the button has been released it's no longer active so active_time will be None?
This space unintentionally left blank.

smalldragoon
Posts: 6
Joined: Mon Sep 18, 2017 4:02 pm

Re: GPIOZero - 2 fonction for same GPIO ? [ SOLVED ]

Mon Oct 02, 2017 2:07 pm

HI
Thanks to all, specially to CyberGyver !
Obvisouly, the active_time is not a such usefull parameter... but at least I understand that everybody get it to none ;-)
Regarding the solution, I coded badly my value storage but with the code shared, works lovely !
Thx a lot again !
[ Edit] @ thagrol : yes, that's it ... tried to store the value , but improperly ... :roll:

CyberGyver
Posts: 2
Joined: Sat Sep 30, 2017 1:09 am

Re: GPIOZero - 2 fonction for same GPIO ?

Mon Oct 02, 2017 8:19 pm

I'm glad we could help. The python code is now on GitHub: https://github.com/CyberGyver/Raspberry ... eleased.py.


Return to “Python”