Python Key press and Key Release Listener
Asked Answered
B

2

7

I am controlling a remote toy car using python code. As of now, the code is as below:

def getkey():
        fd = sys.stdin.fileno()
        old = termios.tcgetattr(fd)
        new = termios.tcgetattr(fd)
        new[3] = new[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO
        new[6][TERMIOS.VMIN] = 1
        new[6][TERMIOS.VTIME] = 0
        termios.tcsetattr(fd, TERMIOS.TCSANOW, new)
        c = None
        try:
                c = os.read(fd, 1)
        finally:
                termios.tcsetattr(fd, TERMIOS.TCSAFLUSH, old)
        return c

def car():
    while True:
        key = getkey()
        if key == 's': #Down arrow
            print "Down"
            Backward()
        elif key == 'w': #Up arrow
            print "Up"
            forward()
        elif key == 'a': 
            print "left"
            Left()
        elif key == 'd': 
            print "Right"
            Right()
        elif key == 'q': #Quit
            print "That's It"
            break
def forward():
    GPIO.output(11,True)  #Move forward

When I press 'w' forward() method is called and the car moves forward but wont stop until I quit the program or call GPIO.output(11, False) from some other method.

Is there any key Listener which detects the key release of any particular key?

For example, if 'w' pressed called this method and if released call some other method

Sudo code:

if w_isPressed()
   forward()
else if w_isReleased()
    stop()
Berth answered 22/6, 2014 at 15:29 Comment(2)
You can't do this without actual keyboard access. Your terminal only sends key presses, so you can't tell when a key has been released.Brevity
You might be able to do it using PyGame.Fcc
A
3

I've seen Pygame game development library being successfully used in similar scenarios before, handling realtime systems and machinery in production, not just toy examples. I think it's a suitable candidate here too. Check out pygame.key module for what is possible to do with the keyboard input.

In short, if you are not familiar with game development, you basically continuously poll for events such as input state changes inside an 'infinite' game loop and react accordingly. Usually update the parameters of the system using deltas per time elapsed. There's plenty of tutorials on that and Pygame available around and Pygame docs are pretty solid.

A simple example of how to go about it:

import pygame

pygame.init()

# to spam the pygame.KEYDOWN event every 100ms while key being pressed
pygame.key.set_repeat(100, 100)

while 1:
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                print 'go forward'
            if event.key == pygame.K_s:
                print 'go backward'
        if event.type == pygame.KEYUP:
            print 'stop'

You'll need to play with pygame.KEYDOWN, pygame.KEYUP and pygame.key.set_repeat depending on how your car movement is implemented.

Alleyne answered 22/6, 2014 at 17:12 Comment(1)
One limitation to pygame is that it requires a display to be connectecd. That is, this approach does not work if you are connecting to a headless raspberry pi with SSH.Factorize
F
2

Faced a similar problem (I am no Python expert) but this worked for me

import pynput
from pynput import keyboard 

def on_press(key):
    try:
        print('Key {0} pressed'.format(key.char))
        #Add your code to drive motor
    except AttributeError:
        print('Key {0} pressed'.format(key))
        #Add Code
def on_release(key):
    print('{0} released'.format(key))
    #Add your code to stop motor
    if key == keyboard.Key.esc:
        # Stop listener
        # Stop the Robot Code
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()
Fourier answered 20/3, 2019 at 10:18 Comment(1)
It appears that pynput listens even when its window does not have focus. Might be desirable in certain cases.Kaput

© 2022 - 2025 — McMap. All rights reserved.