Getting the rate of change of a variable - python

I'm fairly new to Python.
My goal is to press a button and a counter (counta) goes up by 1 every time I press 'a'.
Now I want - for example print out - how many times I've pressed the 'a' button within 10 seconds (for example).
The code is working fine like this. Now i only want to add this feature to print the chagne rate. Any ideas?
Until now my code looks like this:
from pynput.keyboard import Listener
import sched, time
s = sched.scheduler(time.time, time.sleep)
counta = 0
Timer = 0
On = True
def on_press(key):
if key.char == 'a':
#print("")
global counta
counta += 1
#print("Aktuell" + str(counta))
elif key.char == 'p':
print(int(counta/3))
else:
print("wrong button")
print("a = counta")
listener = Listener(on_press=on_press)
listener.start()
while On:
print(int(counta//3))
print(counta)
time.sleep(1)
listener.join()

Is that what you are looking for? And what do you mean by change rate?
from pynput.keyboard import Listener
import time
counta = 0
end = time.time() + 10
def on_press(key):
global counta
if key.char == 'a':
counta += 1
elif key.char == 'p':
print(int(counta/3))
else:
print("Falsche Taste!")
print("a = counta")
listener = Listener(on_press=on_press)
listener.start()
while True:
if end - time.time() >= 0:
pass
# print(end - time.time())
else:
print(counta)
counta = 0
end = time.time() + 10
listener.join()

Related

Detecting when a key is pressed and break when another key is pressed[Python]

So I'm making a game without PyGame, and I want to add a section where you try to press the correct keyboard letters given the "number" of the letter, which would mean A - 1, B - 2, C - 3, etc. I want to make it so you can't mash every key, so I added a counter. However - the counter doesn't work. Help!
def keyboardpart(l,x,num):
for i in range(num):
keypress = False
c = 0
dn = random.randint(0,25)
var = l[dn]
print(dn+1)
flag1 = False
start = time.time()
while time.time()-start < x:
if keypress and not keyboard.is_pressed(var):
if c > 3:
break
c+=1
elif keyboard.is_pressed(var) and not keypress:
keypress = True
print(keypress,c)
if not keypress:
print("Sorry, you missed that key.")
flag1 = True
break
if flag1:
keyboardpart(l,x,num)
Check if any keys are pressed then check if the target key is pressed. Also wait until all keys are released before retry.
Try this code:
import random, keyboard, time
l = [chr(65+i) for i in range(26)] # A-Z
def keyboardpart(l,x,num):
for i in range(num):
keyboard.is_pressed(65) # process OS events
while len(keyboard._physically_pressed_keys): pass # wait until keys released
keypress = False
c = 0
dn = random.randint(0,25)
var = l[dn]
print(dn+1, l[dn])
flag1 = False
start = time.time()
while time.time()-start < x:
if len(keyboard._physically_pressed_keys): # any key down
if keyboard.is_pressed(var): # check target key
keypress = True
break
else: # wrong key
c+=1
if c >= 3: break # allow 3 tries
while len(keyboard._physically_pressed_keys): pass # wait until keys released
print(keypress, c)
print(keypress,c)
if not keypress:
print("Sorry, you missed that key.")
flag1 = True
break
if flag1:
keyboardpart(l,x,num)
keyboardpart(l,100,4)

Pyboard: Changing LED colour on USR button press

I got these this board Pyboard D-series which has internal LED diode with three different colours.
My goal is to make it change the LED colour on button press so basically if u press for the first time, red goes red, second time led goes green, third time led goes blue and at the fourth time I would love it to ("reset") and go back to red.
I tried making this fucntion based on stuff I found online, but it doest seem to be working.
I am new to IoT and micropython so I might be missing something important, but have no clue what.
Thanks for any advice
from pyb import Switch
from pyb import LED
led_R = LED(1)
led_G = LED(2)
led_B = LED(3)
# 1=red, 2=green, 3=blue
sw = pyb.Switch()
def cycle():
counter = 0
buttonState = ''
buttonState = sw.value()
print(buttonState)
if buttonState == True:
counter = counter + 1
print(counter)
elif counter == 0:
led_R.off()
led_G.off()
led_B.off()
elif counter == 1:
led_R.on()
led_G.off()
led_B.off()
elif counter == 2:
led_R.off()
led_G.on()
led_B.off()
elif counter == 3:
led_R.off()
led_G.off()
led_B.on()
else:
counter = 0
sw.callback(cycle())
Your callback cycle is called when button state transitions from off to on
In the callback sw.value() will always evalluate into true so it does not make sense to check it.
your counter should be initialized outside of callback
from pyb import Switch
from pyb import LED
led_R = LED(1)
led_G = LED(2)
led_B = LED(3)
# 1=red, 2=green, 3=blue
sw = pyb.Switch()
counter = 0
def cycle():
counter = counter + 1
if counter == 4:
counter = 0
print(counter)
if counter == 0:
led_R.off()
led_G.off()
led_B.off()
elif counter == 1:
led_R.on()
led_G.off()
led_B.off()
elif counter == 2:
led_R.off()
led_G.on()
led_B.off()
elif counter == 3:
led_R.off()
led_G.off()
led_B.on()
sw.callback(cycle())

Don't understand this timed while loop attribute error

So I have been trying to make a while loop that will run for 10 minutes. But is keeps erroring out on the line with the while loop. It says 'str' object has no attribute 'time'.
I have discovered that if i remove the lines with now.strftime() in them that the code runs but I don't know why it runs without those lines or how to fix it.
I did also try to do something using the datetime module instead of importing the time module but this also fails.
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
time = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass
As #CoryKramer pointed out, you named a variable time, which is also the name of the module you are importing. All I really did was change the time variable to something like currTime. Try the code below (runs for me):
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
currTime = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass
Additionally, consider reading up on:
How to name a module without conflict with variable name?
https://en.wikipedia.org/wiki/Variable_shadowing
dont name your variable in your while loop time when you import the time library:
time = now.strftime("%H:%M:%S")
in your while loop you want to use the time function of the time library but as soon as you run the while loop once it will try to use time() on the string time you defined in the while loop.
I think the problem is here:
time = now.strftime("%H:%M:%S")
Thus, you converted time into a string variable. Name this variable in a different way!
Apart from this, running for 10 minutes at "full throttle" is a lot! Consider to introduce a "sleep" time at the end of the while loop (just suggesting)

Wait for input for 1 second in python

I'm trying to make a note application in Python using curses.
To the bottom left, should be a clock that updates every second.
The issue I now have is that it either has to sleep 1 second, or wait for input.
Is it possible to wait for input for 1 second and continue if no input it registered?
The reason I want to do this, is to prevent delay when moving around in the application.
I was thinking something like multi-threading would do the job, but got some issues there too.
This is the code I have so far:
#!/usr/bin/env python3
import curses
import os
import time
import datetime
import threading
def updateclock(stdscr):
while True:
height, width = stdscr.getmaxyx()
statusbarstr = datetime.datetime.now().strftime(' %A')[:4] + datetime.datetime.now().strftime(' %Y-%m-%d | %H:%M:%S')
stdscr.addstr(height-1, 0, statusbarstr)
time.sleep(1)
def draw_menu(stdscr):
k = 0
stdscr.clear()
stdscr.refresh()
threading.Thread(target=updateclock, args=stdscr).start()
cursor_y = 0
cursor_x = 0
while (k != ord('q')):
#while True:
stdscr.clear()
height, width = stdscr.getmaxyx()
stdscr.addstr(height//2, width//2, "Some text in the middle")
if k == curses.KEY_DOWN:
cursor_y = cursor_y + 1
elif k == curses.KEY_UP:
cursor_y = cursor_y - 1
elif k == curses.KEY_RIGHT:
cursor_x = cursor_x + 1
elif k == curses.KEY_LEFT:
cursor_x = cursor_x - 1
stdscr.refresh()
#time.sleep(1)
# Wait for next input
k = stdscr.getch()
curses.wrapper(draw_menu)
The code looks pretty messy, and it's the first time I've mainly focused on the curses function.
Is it possible to only wait for input k = stdscr.getch() for 1 second?
By default getch will block until you have a character input ready. If nodelay mode is True, then you will either get the character value (0-255) of the character that is ready, or you will get a -1 indicating that no character value is ready.
stdscr.nodelay(True) #Set nodelay to be True, it won't block anymore
k = stdscr.getch() #Either the next character of input, or -1

epoll() for /dev/input device?

I am working with events coming from /dev/input/event0, buttons. I'm currently polling in an infinite loop but would prefer to wait for an event.
import struct
# https://docs.python.org/3/library/struct.html#format-characters
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
EV_KEY = 0x01
KEY_UP = 0
KEY_DOWN = 1
KEY_AUTO = 2
with open('/dev/input/event0', 'rb') as infile:
state = 0
while True:
event = infile.read(EVENT_SIZE)
(tv_sec, tv_usec, typ, code, value) = struct.unpack(FORMAT, event)
if 0 == state:
if EV_KEY == typ and KEY_DOWN == value:
print('You pressed a button')
state = 1
elif 1 == state:
if EV_KEY == typ and KEY_UP == value:
print('You released a button')
state = 0
Can I use epoll() with python to accomplish this in much less code?

Categories

Resources