Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 2:25 am

I'm trying to make a program to control a printer I made.
I want to be able to manually control it by using the arrow keys, but I can't figure out how to detect the keypresses.
I really want to use strictly a console based controlling method.
I want to use Pygame to detect the keystrokes, but I don't want to have a blank window sitting there detecting the keypresses.

OBJECTIVE: To be able to detect KEYDOWN and KEYUP events in the console using Pygame.

Any ideas anyone?
Thanks in advance!

User avatar
jojopi
Posts: 3290
Joined: Tue Oct 11, 2011 8:38 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 7:56 am

Terminal input is based on ASCII codes. When you press a key its code is sent. For a non-ASCII key such as F1 or €, several bytes are used; an ASCII escape sequence or a UTF-8 sequence of high bytes. You may need to pay attention to the timing to distinguish the up arrow from the three separate keys Esc [ A. When a key is released, nothing is sent on a terminal. It is impossible to detect keys being held or released over SSH, for instance.

To detect key presses and releases you must either connect to the X Window System like pygame, or use the kernel's evdev mechanism. The former method also works remotely over VNC or RDP, whereas the latter always reads the local USB-attached input devices, and may require privilege. X also allows the user to choose which application should receive keystrokes, by giving focus to a particular window.

Sleep Mode zZ
Posts: 319
Joined: Sun Aug 19, 2012 5:56 am
Location: Finland

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 11:24 am

Python's curses module should be able to do what you want.

User avatar
jojopi
Posts: 3290
Joined: Tue Oct 11, 2011 8:38 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 11:58 am

Sleep Mode zZ wrote:Python's curses module should be able to do what you want.
curses is terminal-based, so it cannot detect key release events.

It handles the parsing of ASCII escape sequences back into symbolic key names for you, but it also assumes that your application will take over the whole terminal and has a nasty habit of moving the cursor around. It is not an ideal choice if you only want it for its input handling.

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 4:36 pm

I don't really need the KEYDOWN and KEYUP events, but that seemed, to me, to be the easiest way to sense which keys are pressed. I found somewhere that you can run Pygame without a window.

Basically what I need is just a way to tell which arrow keys are pushed.
Any ideas anyone?

User avatar
davef21370
Posts: 897
Joined: Fri Sep 21, 2012 4:13 pm
Location: Earth But Not Grounded

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 4:59 pm

http://www.pygame.org/wiki/HeadlessNoWi ... t=CookBook
Not in a position to test this but might be useful.

Dave.
Apple say... Monkey do !!

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Fri Jun 27, 2014 5:02 pm

Thanks for posting that! I think that might solve it.


User avatar
davef21370
Posts: 897
Joined: Fri Sep 21, 2012 4:13 pm
Location: Earth But Not Grounded

Re: KEYDOWN and KEYUP events using Pygame without a window

Sat Jun 28, 2014 8:11 am

Sleep Mode zZ wrote:Some posts indicate that the keyboard events won't work with the dummy driver:
On further investigation that would seem to be the case, maybe this would fare better... https://github.com/sangmank/py-showkey

Dave.
Apple say... Monkey do !!

User avatar
Stephanie
Posts: 13
Joined: Tue Jun 17, 2014 12:03 pm
Location: Ontario, Canada
Contact: Website

Re: KEYDOWN and KEYUP events using Pygame without a window

Sat Jun 28, 2014 10:46 pm

Just wondering if it has to be keyboard arrow keys that you are detecting?

Instead of jumping through hoops to monitor headless console keyboard input, have you thought of using some plain old pushbutton switches connected to GPIO pins?

Pygame seems to get along just fine with RPi.GPIO, and it's pretty straightforward in terms of wiring and detection. For that matter, if you're only using pygame for the keyboard events, maybe you can skip it altogether, by just monitoring some GPIO buttons rather than keyboard keys?

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Tue Jul 01, 2014 9:56 pm

Stephanie wrote:Just wondering if it has to be keyboard arrow keys that you are detecting?

Instead of jumping through hoops to monitor headless console keyboard input, have you thought of using some plain old pushbutton switches connected to GPIO pins?

Pygame seems to get along just fine with RPi.GPIO, and it's pretty straightforward in terms of wiring and detection. For that matter, if you're only using pygame for the keyboard events, maybe you can skip it altogether, by just monitoring some GPIO buttons rather than keyboard keys?
No, it doesn't have to be arrow keys, but I would at least like it to be on the keyboard... (that is where all the rest of the controlling is coming from.) I had thought of doing that but almost all the pins will be tied up with all the sensors and motors and stuff.

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Tue Jul 01, 2014 10:54 pm

I finally just gave up and decided to use a window. :'(

brjhaverkamp
Posts: 5
Joined: Tue Oct 06, 2015 6:24 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Wed Mar 23, 2016 2:35 pm

I was wondering if there is an update to this now. what is the best way to detect keypresses/releases?

My set up is a robot cart with a RPi3 on top. I can access it over Wifi with ssh.
On the RPi I have connected the motor controls via GPIO. As a start I want to remote control this via my laptop keyboard via the cursor keys. It has to be able to detect multiple keys, so press "up" to go forward, add "left" to make a turn to the left, release "left" key (leave "up2 pressed) to go forward again. etc.
The pygame library seemed very suited except for the screen requirement and the dummy screen doesn't seem to sufice.
What are the alternatives atm?

Regards,

Bert

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Wed Mar 23, 2016 4:34 pm

brjhaverkamp wrote:I was wondering if there is an update to this now. what is the best way to detect keypresses/releases?

My set up is a robot cart with a RPi3 on top. I can access it over Wifi with ssh.
On the RPi I have connected the motor controls via GPIO. As a start I want to remote control this via my laptop keyboard via the cursor keys. It has to be able to detect multiple keys, so press "up" to go forward, add "left" to make a turn to the left, release "left" key (leave "up2 pressed) to go forward again. etc.
The pygame library seemed very suited except for the screen requirement and the dummy screen doesn't seem to sufice.
What are the alternatives atm?

Regards,

Bert

I actually gave up on that method when I was finding that I was needing to go much more low-level to achieve that. The only thing I could recommend would be to use a different programming language on your laptop that supports the key-down and key-up events natively.

Sorry!

brjhaverkamp
Posts: 5
Joined: Tue Oct 06, 2015 6:24 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Wed Mar 23, 2016 7:08 pm

Hi,

Thanks for your quick reply. Somewhere above here, someone mentioned py-showkey.
Did you try it? Or is it not worth bothering?

Jyclop
Posts: 23
Joined: Wed Jun 18, 2014 11:57 pm

Re: KEYDOWN and KEYUP events using Pygame without a window

Wed Mar 23, 2016 7:34 pm

brjhaverkamp wrote:Hi,

Thanks for your quick reply. Somewhere above here, someone mentioned py-showkey.
Did you try it? Or is it not worth bothering?
It's been such a long time since I was messing with that stuff, I don't remember much about it. I think I messed with the showkey but I think that didn't quite do what I wanted. Like it only gave me key-presses or something like that.

So is your laptop running a python program that controls your RPI on you your robot via Wifi? I guess I'm not quite understanding your whole setup.

fc_key
Posts: 22
Joined: Thu Apr 07, 2016 8:32 pm
Location: Switzerland

Re: KEYDOWN and KEYUP events using Pygame without a window

Tue Apr 12, 2016 12:02 pm

Hello there :D

I figuered it out to control a robot using curses:

Maybe this helps a bith, you can open a new window and not print anything out on it so I dont think this the biggest problem, you can write there Programxy running!

I have the problem that without a time.sleep in the while loop the key pressed are not getting detected. I think this is because the loop is to fast and can't read in the key pressed down so it gets back -1 and the robot stops. Can somebody help me out on this?

Hope I can give you a help :)

Thank you

Here is my code:

Code: Select all

import RPi.GPIO as GPIO # Import the GPIO Library
import os 
import time # Import the Time library
import curses

# Set the GPIO modes
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Set variables for the GPIO motor pins
pinMotorAForwards = 9
pinMotorABackwards = 10
pinMotorBForwards = 8
pinMotorBBackwards = 7

# How many times to turn the pin on and off each second
Frequency = 20
# How long the pin stays on each cycle, as a percent (here, it's 30%)
DutyCycle = 30
# Setting the duty cycle to 0 means the motors will not turn
Stop = 0

# Set the GPIO Pin mode
GPIO.setup(pinMotorAForwards, GPIO.OUT)
GPIO.setup(pinMotorABackwards, GPIO.OUT)
GPIO.setup(pinMotorBForwards, GPIO.OUT)
GPIO.setup(pinMotorBBackwards, GPIO.OUT)

# Set the GPIO to software PWM at 'Frequency' Hertz
pwmMotorAForwards = GPIO.PWM(pinMotorAForwards, Frequency)
pwmMotorABackwards = GPIO.PWM(pinMotorABackwards, Frequency)
pwmMotorBForwards = GPIO.PWM(pinMotorBForwards, Frequency)
pwmMotorBBackwards = GPIO.PWM(pinMotorBBackwards, Frequency)

# Start the software PWM with a duty cycle of 0 (i.e. not moving)
pwmMotorAForwards.start(Stop)
pwmMotorABackwards.start(Stop)
pwmMotorBForwards.start(Stop)
pwmMotorBBackwards.start(Stop)

# Turn all motors off
def StopMotors():
	pwmMotorAForwards.ChangeDutyCycle(Stop)
	pwmMotorABackwards.ChangeDutyCycle(Stop)
	pwmMotorBForwards.ChangeDutyCycle(Stop)
	pwmMotorBBackwards.ChangeDutyCycle(Stop)

# Turn both motors forwards
def Forwards():
	pwmMotorAForwards.ChangeDutyCycle(DutyCycle)
	pwmMotorABackwards.ChangeDutyCycle(Stop)
	pwmMotorBForwards.ChangeDutyCycle(DutyCycle)
	pwmMotorBBackwards.ChangeDutyCycle(Stop)

# Turn both motors backwards
def Backwards():
	pwmMotorAForwards.ChangeDutyCycle(Stop)
	pwmMotorABackwards.ChangeDutyCycle(DutyCycle)
	pwmMotorBForwards.ChangeDutyCycle(Stop)
	pwmMotorBBackwards.ChangeDutyCycle(DutyCycle)

# Turn Right
def Right():
	pwmMotorAForwards.ChangeDutyCycle(Stop)
	pwmMotorABackwards.ChangeDutyCycle(DutyCycle)
	pwmMotorBForwards.ChangeDutyCycle(DutyCycle)
	pwmMotorBBackwards.ChangeDutyCycle(Stop)
# Turn Left
def Left():
	pwmMotorAForwards.ChangeDutyCycle(DutyCycle)
	pwmMotorABackwards.ChangeDutyCycle(Stop)
	pwmMotorBForwards.ChangeDutyCycle(Stop)
	pwmMotorBBackwards.ChangeDutyCycle(DutyCycle)
	
# Here starts the code to make the robot move
stdscr = curses.initscr()
curses.cbreak()
stdscr.keypad(1)

stdscr.addstr(0,10,"Hit 'q' to quit")
stdscr.nodelay(1)  #nodelay(1) give us a -1 back when nothing is pressed
Richtung = ' '
while Richtung != ord('q'):
	#Start of while loop
	stdscr.refresh()
	
	Richtung = stdscr.getch() #Gets the key which is pressed
		
	stdscr.addch(20,25,Richtung)
	
	if Richtung == ord('e'):
		StopMotors()

	if  Richtung == ord('a'):
		Left()

	if Richtung == ord('s'):
		Backwards()

	if Richtung == ord('d'):
		Right()
	
	if Richtung == ord('w'):
		Forwards()
	
	if Richtung == int('-1'):
		StopMotors()
		
	time.sleep(0.04) #I need the timesleep because if not the robot will get a -1 all the time and not move to fast while loop I think, have to work on this.
	#End of while loop
	
#Important to set everthing back by end of the script

curses.nocbreak()
stdscr.keypad(0)
curses.endwin()
StopMotors()
GPIO.cleanup()

Friendly greetings fc_key

Return to “Python”