O
Yes, the event KeyPress is called whenever a key is pressed - and in general the operating system will have an automatic "auto-repeat": that is, if the user does not release the key, various events KeyPress are sent - And even the events that happen while the pause of time.sleep is in effect, will be "encaved" -That is - let's assume that the system key repeat time is "0.1" seconds and your pause is "0.1" 1 second: 10 keypress events would arrive during a single time.sleep, causing 10 calls followed the functions that respond to the directions, even if the keys were loose.And the reverse situation can also be bad from the user's point of view: you have a time.sleep of 0.02 seconds, and the reptition of the system occurs every 0.1 - means that the engine would be triggered by "holes": it is connected 0.02 seconds, it is expected to be 0.08 seconds between one drive and another. Good - what you need is to activate the engine when receiving the first <KeyPress> and stop the same when receiving the evneto <KeyRelease> - and,or do not depend on a time time.sleep, or find another way to account for the time to an automatic stop. (e.g. some mechanism that has to stay exactly the time X on, regardless of the time the key is pressed).Re-write the direction functions this way:def frente():
gpio.output(7, False)
gpio.output(11, True)
gpio.output(13, True)
gpio.output(15, True)
and can maintain function key_input almost as it is, but without passing the sleep parameter - and a new function:def keyup(event):
if event.char in "wasd":
gpio.cleanup()
And of course, associate it with the event to drop a key:janela.bind("<KeyRelease>", keyup)
Now, if the engine should really be connected only for 0.02 seconds, you need something a little more complex - instead of using the team. sleep, use the call after tkinter - and only "release" a key to be "repeated" after the corresponding key is pressed.Create a dictionary in the module, to save the state of each key, "False" to "drop" and "True" to press, and only call the drive functions if the key was not previously presonated.Change the drive functions for this model:def esq(tf):
gpio.output(7, True)
gpio.output(11, True)
gpio.output(13, False)
gpio.output(15, True)
# Faz a pausa sem bloquear o fluxo do programa:
tkinter.after(tf * 1000, gpio.cleanup)
pressed_keys = {
"w": False, "s": False, "a": False, "d": False
}
e aproveitando um atalho em vez dos "if" repetitivos:
movement_funcs = {
"w": frente, "s": tras, "a": esq, "d": dir
}
def key_input(event):
# O "init" realmente tem que ser chaamdo em cada keypress?
# se sim, mova essa chamada para dentro das funções de movimento-
# assim, os keypress repetidos não vão resetar os GPIOs.
# mas me parece que essa chamada deveria ser feita no setup da aplicação
# apenas uma vez:
init()
print 'Key:', event.char
key_press = event.char
sleep_time = (0.02)
if event.char in "wsad" and not pressed_keys[event.char]:
pressed_keys[event.char] = True
movement_funcs[event.char](sleep_time)
def keyup(event):
if event.char in "wsad":
pressed_keys[event.char] = False
E claro:
janela.bind("<KeyRelease>", keyup)