I have some Python for a Raspberry Pi where I test for a button press (first loop) and use it to start and stop a timer (second loop). However, if I run this program only the first loop in the sequence runs. How can I make it so both run at the same time? Code:
EDIT: made changes to code in attempt to accommodate threading. Would this work?
import os
os.chdir('/home/pi/Desktop/Python')
import lcd
lcd.lcd_init()
import time
import threading
from threading import Thread
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN, pull_up_down=GPIO.PUD_UP)
latest_state = None
status = False
seconds = 0
minutes = 0
hours = 0
def button():
while True:
if status == True:
seconds +=1
if seconds == 59:
seconds = 0
minutes = minutes + 1
if minutes == 59:
minutes = 0
hours = hours + 1
tup = " H:",hours," M:",minutes," S:",seconds
display = ''.join(map(str, tup))
lcd.lcd_string(display,2)
time.sleep(0.99)
Thread(target = button).start()
while True:
inputValue = GPIO.input(23)
if inputValue != latest_state:
latest_state = inputValue
if latest_state:
print " "
else:
status = not status
print status
print " "
Related
I am making a stop watch in python which prints out the seconds passed and as soon as the user presses enter, it stops.
I am using multiprocessing to ask for an input and keep printing until an input is received. but the code is giving an EOF error for the input statement when I run it, what am I doing wrong?
import os
import multiprocessing
end = multiprocessing.Value('i',0)
def get_input(end):
x = input('')
end.value = 1
def print_time(end):
secs = 0
mins = 0
hrs = 0
x = input('start: ')
while True:
mins, secs = divmod(secs, 60)
hrs = 0
if mins > 60:
hrs, mins = divmod(mins, 60)
timer_display = '{:02d}:{:02d}:{:02d}'.format(hrs, mins, secs)
print(timer_display)
if end.value == 1:
break
time.sleep(1)
secs += 1
if __name__ == "__main__":
func1 = multiprocessing.Process(target = get_input, args = (end,))
func2 = multiprocessing.Process(target = print_time, args = (end,))
func1.start()
func2.start()
func1.join()
func2.join()
It's probably better to start/stop the stopwatch in the main program and just use one Process to display the timer. Something like this:
from multiprocessing import Process, Value
import time
def showTime(end):
start = time.time()
while end.value == 0:
elapsed = int(time.time() - start)
ss = elapsed % 60
mm = elapsed // 60 % 60
hh = elapsed // 3600
print(f'{hh:02d}:{mm:02d}:{ss:02d}')
time.sleep(1)
def main():
input('Press enter to start: ')
end = Value('i', 0)
Process(target=showTime, args=(end,)).start()
input('Press enter to stop: ')
end.value = 1
if __name__ == '__main__':
main()
Also, this technique allows for any potential drift due to processing time
Background: I'm using as Raspberry Pi rev 2 B to run a nature sound white noise generator of sorts that will randomly play audio tracks of varying length based on the time of night/morning. Some tracks are only a minute, some are several hours long. I'm looking for a way to check the time and change which type of sounds play based on time.
Current issue: I can start the appropriate audio for the time when the program first executes, but the timeloop execution stops polling once omxplayer starts up.
I have tried to call OMXPlayer without interrupting the time checker that determines what kind of audio to play, but once the audio playback starts I have been unable to continue checking time. Even if the play_audio() function wasn't recursive I would still like a way for the time checker to continue executing while the audio plays
#!/usr/bin/env python
import datetime, time, os, subprocess, random
from timeloop import Timeloop
from datetime import timedelta
from time import sleep
from omxplayer.player import OMXPlayer
from pathlib import Path
tl = Timeloop()
running_cycle = "off" # default value for the time cycle currently running
#function to check current time cycle
def check_time () :
dt_now = datetime.datetime.now()
t_now = dt_now.time()
t_night = datetime.time(hour=2,minute=0)
t_twilight = datetime.time(hour=4,minute=45)
t_morning = datetime.time(hour=7,minute=0)
t_end = datetime.time(hour=10,minute=0)
if t_night <= t_now < t_twilight:
return "night"
elif t_twilight <= t_now < t_morning:
return "twilight"
elif t_morning <= t_now < t_end:
return "morning"
else:
return "off"
# function that plays the audio
def play_audio (time_cycle):
subprocess.call ("killall omxplayer", shell=True)
randomfile = random.choice(os.listdir("/home/pi/music/nature-sounds/" + time_cycle))
file = '/home/pi/music/nature-sounds/' + time_cycle + '/' + randomfile
path = Path(file)
player = OMXPlayer(path)
play_audio (time_cycle)
# function that determines whether to maintain current audio cycle or play another
def stay_or_change():
global running_cycle
current_cycle = check_time()
if running_cycle != current_cycle:
if current_cycle == "off" :
player.quit()
else:
running_cycle = current_cycle
print "Now playing: " + running_cycle + " #{}".format(time.ctime())
play_audio(running_cycle)
#starts timeloop checker to play audio - works until stay_or_change() calls play_audio
#tl.job(interval=timedelta(seconds=10))
def job_10s():
print "10s job - running cycle: " + running_cycle + " - current time: {}".format(time.ctime())
stay_or_change()
# starts the timeloop
if __name__ == "__main__":
tl.start(block=True)
I have also tried running OMXPlayer with subprocess.run() but it still seems to hang up after the player starts. I'm completely open to any recommendations for background threading media players, process daemons, or time based execution methods.
I'm new to Python.
I had the recursion all wrong so it got caught in an infinite loop and the timeloop function wasn't really viable for this solution. Instead I had a function that played the sound, and then called the function that checked the time and plays from the appropriate sub-directory (or play nothing and wait).
Here's what I managed to come up with:
#!/usr/bin/env python
import datetime, time, os, subprocess, random
from datetime import timedelta
from time import sleep
from omxplayer.player import OMXPlayer
def check_time () :
dt_now = datetime.datetime.now()
t_now = dt_now.time()
t_night = datetime.time(hour=0,minute=0)
t_twilight = datetime.time(hour=5,minute=45)
t_morning = datetime.time(hour=7,minute=45)
t_end = datetime.time(hour=10,minute=0)
if t_night <= t_now < t_twilight:
return "night"
elif t_twilight <= t_now < t_morning:
return "twilight"
elif t_morning <= t_now < t_end:
return "morning"
else:
return "off"
def play_audio (time_cycle):
randomfile = random.choice(os.listdir("/home/pi/music/nature-sounds/" + time_cycle))
file = '/home/pi/music/nature-sounds/' + time_cycle + '/' + randomfile
print "playing track: " + randomfile
cmd = 'omxplayer --vol -200 ' + file
subprocess.call (cmd, shell=True)
what_to_play()
def what_to_play():
current_cycle = check_time()
if current_cycle == "off" :
print "sounds currently off - #{}".format(time.ctime())
time.sleep(30)
what_to_play()
else:
print "Now playing from " + current_cycle + " #{}".format(time.ctime())
play_audio(current_cycle)
what_to_play()
So basically we're using raspberry pi for a project and a part of it includes the usage of ultrasonic sensors. We have three, and we've been able to get readings from all of them (I actually came from multi-threading but decided to move to multiprocessing). Here is my code:
#Libraries
from multiprocessing import Process, Lock
import RPi.GPIO as GPIO
import time
#GPIO Mode (BOARD / BCM)
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#set GPIO Pins
GPIO_TRIGGER1 = 23
GPIO_ECHO1 = 24
GPIO_TRIGGER2 = 27
GPIO_ECHO2 = 22
GPIO_TRIGGER3 = 25
GPIO_ECHO3 = 17
#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER1, GPIO.OUT)
GPIO.setup(GPIO_ECHO1, GPIO.IN)
GPIO.setup(GPIO_TRIGGER2, GPIO.OUT)
GPIO.setup(GPIO_ECHO2, GPIO.IN)
GPIO.setup(GPIO_TRIGGER3, GPIO.OUT)
GPIO.setup(GPIO_ECHO3, GPIO.IN)
def sense_distance(lock, processName):
#lock.acquire()
gpio_echo_var = ''
gpio_trigger_var = ''
if processName == "Sensor-1":
gpio_echo_var = GPIO_ECHO1
gpio_trigger_var = GPIO_TRIGGER1
elif processName == "Sensor-2":
gpio_echo_var = GPIO_ECHO2
gpio_trigger_var = GPIO_TRIGGER2
elif processName == "Sensor-3":
gpio_echo_var = GPIO_ECHO3
gpio_trigger_var = GPIO_TRIGGER3
print "%s process created." % (processName)
try:
while True:
# set Trigger to HIGH
GPIO.output(gpio_trigger_var, True)
# set Trigger after 0.01ms to LOW
time.sleep(0.00001)
GPIO.output(gpio_trigger_var, False)
StartTime = time.time()
StopTime = time.time()
# save StartTime
while GPIO.input(gpio_echo_var) == 0:
StartTime = time.time()
# save time of arrival
while GPIO.input(gpio_echo_var) == 1:
StopTime = time.time()
# time difference between start and arrival
TimeElapsed = StopTime - StartTime
# multiply with the sonic speed (34300 cm/s)
# and divide by 2, because there and back
distance = (TimeElapsed * 34300) / 2
if distance <= 10:
print "%s has read less than 10 cm." % (processName)
else:
pass
# Reset by pressing CTRL + C
except KeyboardInterrupt:
print("Measurement stopped by User")
GPIO.cleanup()
#lock.release()
if __name__ == '__main__':
lock = Lock()
Process(target=sense_distance, args=(lock, "Sensor-1")).start()
Process(target=sense_distance, args=(lock, "Sensor-2")).start()
Process(target=sense_distance, args=(lock, "Sensor-3")).start()
It successfully reads the input and prints out the text when input goes smaller than 10 cm. However, after some time, they stop. I have run out of ideas and have searched all over only to come up short. Any sort of help will be appreciated.
I am trying to create a stopwatch that starts and stops through the user pressing the enter. Once to start and again to stop. The start works perfectly but the stopping section is not working. I've tried creating a variable called stop that is like so:
stop = input("stop?")
But it's still not working.
import time
def Watch():
a = 0
hours = 0
while a < 1:
for minutes in range(0, 60):
for seconds in range(0, 60):
time.sleep(1)
print(hours,":", minutes,":", seconds)
hours = hours + 1
def whiles():
if start == "":
Watch()
if start == "":
return Watch()
def whiltr():
while Watch == True:
stop = input("Stop?")
#Ask the user to start/stop stopwatch
print ("To calculate your speed, we must first find out the time that you have taken to drive from sensor a to sensor b, consequetively for six drivers.")
start = input("Start?")
start = input("Stop")
whiles()
Perhaps all you need is something simple like:
import time
input('Start')
start = time.time()
input('Stop')
end = time.time()
print('{} seconds elapsed'.format(end-start))
Should probably use the time function instead of
def Watch():
import time
def timer():
now = time.localtime(time.time())
return now[5]
run = raw_input("Start? > ")
while run == "start":
minutes = 0
current_sec = timer()
#print current_sec
if current_sec == 59:
mins = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
I want to create a kind of stopwatch that when minutes reach 20 minutes, brings up a dialog box, The dialog box is not the problem. But my minutes variable does not increment in this code.
See Timer Objects from threading.
How about
from threading import Timer
def timeout():
print("Game over")
# duration is in seconds
t = Timer(20 * 60, timeout)
t.start()
# wait for time completion
t.join()
Should you want pass arguments to the timeout function, you can give them in the timer constructor:
def timeout(foo, bar=None):
print('The arguments were: foo: {}, bar: {}'.format(foo, bar))
t = Timer(20 * 60, timeout, args=['something'], kwargs={'bar': 'else'})
Or you can use functools.partial to create a bound function, or you can pass in an instance-bound method.
You can really simplify this whole program by using time.sleep:
import time
run = raw_input("Start? > ")
mins = 0
# Only run if the user types in "start"
if run == "start":
# Loop until we reach 20 minutes running
while mins != 20:
print(">>>>>>>>>>>>>>>>>>>>> {}".format(mins))
# Sleep for a minute
time.sleep(60)
# Increment the minute total
mins += 1
# Bring up the dialog box here
I'd use a timedelta object.
from datetime import datetime, timedelta
...
period = timedelta(minutes=1)
next_time = datetime.now() + period
minutes = 0
while run == 'start':
if next_time <= datetime.now():
minutes += 1
next_time += period
Your code's perfect except that you must do the following replacement:
minutes += 1 #instead of mins = minutes + 1
or
minutes = minutes + 1 #instead of mins = minutes + 1
but here's another solution to this problem:
def wait(time_in_seconds):
time.sleep(time_in_seconds) #here it would be 1200 seconds (20 mins)
mins = minutes + 1
should be
minutes = minutes + 1
Also,
minutes = 0
needs to be outside of the while loop.
I want to create a kind of stopwatch that when minutes reach 20 minutes, brings up a dialog box.
All you need is to sleep the specified time. time.sleep() takes seconds to sleep, so 20 * 60 is 20 minutes.
import time
run = raw_input("Start? > ")
time.sleep(20 * 60)
your_code_to_bring_up_dialog_box()
# this is kind of timer, stop after the input minute run out.
import time
min=int(input('>>'))
while min>0:
print min
time.sleep(60) # every minute
min-=1 # take one minute
import time
...
def stopwatch(mins):
# complete this whole code in some mins.
time.sleep(60*mins)
...
import time
mintt=input("How many seconds you want to time?:")
timer=int(mintt)
while (timer != 0 ):
timer=timer-1
time.sleep(1)
print(timer)
This work very good to time seconds.
You're probably looking for a Timer object: http://docs.python.org/2/library/threading.html#timer-objects
Try having your while loop like this:
minutes = 0
while run == "start":
current_sec = timer()
#print current_sec
if current_sec == 59:
minutes = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
import time
def timer(n):
while n!=0:
n=n-1
time.sleep(n)#time.sleep(seconds) #here you can mention seconds according to your requirement.
print "00 : ",n
timer(30) #here you can change n according to your requirement.
import time
def timer():
now = time.localtime(time.time())
return now[5]
run = raw_input("Start? > ")
while run == "start":
minutes = 0
current_sec = timer()
#print current_sec
if current_sec == 59:
mins = minutes + 1
print ">>>>>>>>>>>>>>>>>>>>>", mins
I was actually looking for a timer myself and your code seems to work, the probable reason for your minutes not being counted is that when you say that
minutes = 0
and then
mins = minutes + 1
it is the same as saying
mins = 0 + 1
I'm betting that every time you print mins it shows you "1" because of what i just explained, "0+1" will always result in "1".
What you have to do first is place your
minutes = 0
declaration outside of your while loop. After that you can delete the
mins = minutes + 1
line because you don't really need another variable in this case, just replace it with
minutes = minutes + 1
That way minutes will start off with a value of "0", receive the new value of "0+1", receive the new value of "1+1", receive the new value of "2+1", etc.
I realize that a lot of people answered it already but i thought it would help out more, learning wise, if you could see where you made a mistake and try to fix it.Hope it helped. Also, thanks for the timer.
from datetime import datetime
now=datetime.now()
Sec=-1
sec=now.strftime("%S")
SEC=0
while True:
SEC=int(SEC)
sec=int(sec)
now=datetime.now()
sec=now.strftime("%S")
if SEC<sec:
Sec+=1
SEC=sec
print(Sec) #the timer is Sec