Python if statement delay - python

I am trying to make a 'game' while learning about both Python and GPIO on the Raspberry Pi. This is what I have ATM:
while playing == 1:
if (GPIO.input(9) == 0):
GPIO.output(18, GPIO.LOW)
print("Well done!!")
time.sleep(1)
else:
print("Wrong!")
lives = lives - 1
time.sleep(1)
playing = 0
Now, my problem is that the program is hitting the if statement and is going straight to the else (as you would expect), however, I want the program to wait on the first part of the if statement for a second, then go to the else.
Thanks in advance!

Perhaps you could rewrite it like so:
while playing == 1:
for _ in range(10):
if GPIO.input(9) == 0:
GPIO.output(18, GPIO.LOW)
print("Well done!!")
break
time.sleep(0.1)
else:
print("Wrong!")
lives = lives - 1
This polls the GPIO pin ten times 100ms apart. The else is hit if the GPIO pin stays high throughout the ten attempts.
(If you haven't come across Python's for-else construct, see Why does python use 'else' after for and while loops?.)
Alternatively, you could use GPIO module's more advanced features, such as edge detection and callbacks. See the documentation.

Related

Python - Never-ending time.sleep(1) - Possible to end it?

So I have been playing around with schedule and finally got it to work. I was too excited to relized that there came ANOTHER problem haha. However the issue is now that it doesn't end whenever the main is finished and I can't really find the solution. I know the issue sits on the row Time.sleep(1) because whenever I keyboardInterrput then there comes a error saying Time.sleep(1) was the "Issue" and I can't really find a soulution to end it.
Im using a schedule from a github : Github schedule
while True:
UserInput = input('To run Schedule task - Press y\nTo run directly - Press n\n')
if(UserInput == 'y' or UserInput == 'Y'):
print(Fore.RESET + space)
TimeUser = input('What time to start script? Format - HH:MM\n')
schedule.every().day.at(TimeUser).do(main)
wipe()
print('Schedule starts at: ''' + TimeUser + ' - Waiting for time...')
idle = int(round(schedule.idle_seconds()))
while True:
schedule.run_pending()
time.sleep(1)
idle = int(round(schedule.idle_seconds()))
if(idle < 6.0) and (idle >= 0.0):
print('Starting in: ' + str(idle))
elif(UserInput == 'n' or UserInput == 'N'):
main()
print("Wrong input - Try again")
You could use the for keyword. The for statement can define your iterations and the halting conditions. Or using the range() function to iterate over your numerical sequence.
Being used to traditional if-then-else statements, the break statement will break you out of your while loop. It needs to be with your innermost for or while loop. Your else clause needs to belong to your for loop and not part of the if statement. And the continue statement will move your loop forward.
There are examples here: https://docs.python.org/3/tutorial/controlflow.html
You code is encapsulated in while loops with true as the argument. Either you did this by mistake or this is poor structure. This is the problem.
If you don't want to remove the while loops then atleast add a break somewhere.
If you need help structuring your code, go to Code Review.

raspberry pi python gpio timer

Hi I'm learning to code python on raspberry pi 3 model B. and playing around with GPIO.
My script makes a LED turns on when the receiving input==1 and turn off when input!=1.
I also want to record the time when LED is turned on and time when it's turned off. (start time and end time).
I end up using multiple if/elif condition, but I'm sure there are better ways of doing this. Please enlighten me!
import RPi.GPIO as GPIO
import time
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11,GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(7,GPIO.OUT)
GPIO.output(7,0) #set ping 7 to be 0 at default
CatchTime = True
startTime = []
startTimeRead = []
endTime = []
try:
while True:
time.sleep(0.25)
if (GPIO.input(11) ==1)and CatchTime==True : #start counting
GPIO.output(7,1)
print(time.ctime())
startTime.append(time.time())
startTimeRead.append(time.ctime())
CatchTime = False
elif (GPIO.input(11) ==1)and CatchTime != True : #within count
GPIO.output(7,1)
print(time.ctime())
elif (GPIO.input(11) !=1) and CatchTime != True : #end of count
GPIO.output(7,0)
CatchTime = True
endTime.append(time.time())
else: #steady not count
GPIO.output(7,0)
CatchTime = True
except KeyboardInterrupt:
GPIO.cleanup()
print('start time:',startTimeRead)
print('end time:',endTime)
Generally the better way to do it would be to create interrupt functions for the rising and falling events. what you're doing now is referred to as busy waiting while polling for an input. Interrupts are generally cleaner and more reliable. Computerphile has a nice overview on interrupts in general (more from the computer aspect of things), and a quick google search found this tutorial on how to use gpio interrupts with the rasberry-pi.
I'd recommend looking at this post (Raspberry Pi- GPIO Events in Python) on the Raspberry Pi SO. That solution shows how to use events so you don't have to run a constant loop - it will just notify you when there is a change.

Is there any other way to stop a Python code mid-way without using sys.exit() etc

This is my code:
sleep = input("Commander, would you like to sleep now? If yes then we can take out your bed. ")
if sleep == "yes":
Energy = Energy + 5
print("We have taken out your bed. The spaceship is on autopilot and you may now sleep.")
time.sleep(4)
print("2 weeks later...")
else:
Energy = Energy - 5
print("Ok. It is all your choice. BUT you WILL lose energy. Lets carry on with the journey. You have",Energy,"energy remaining.")
time.sleep(4)
print("Commander, you have been extremely successful so far. Well done and keep it up!")
time.sleep(6)
direction = input("Oh no Sir! There is trouble ahead! Please make your decision quick. It's a matter of life and death. It is also a matter of chance! There are many asteroids ahead. You may either go forwards, backwards, left or right. Make your decision...before it's too late! ")
if direction == "left":
Coins = Coins + 15
Fuel = Fuel - 15
while True:
print ("You have managed to pass the asteroids, you may now carry on. You have",Fuel,"fuel left.")
break
continue
elif direction == "backwards":
print("You have retreated and gone back to Earth. You will have to start your mission all over again.")
time.sleep(2.5)
print("The game will now restart.")
time.sleep(2)
print("Please wait...\n"*3)
time.sleep(5)
keep_playing = True
while True:
script()
elif direction == "forwards":
Fails = Fails + 1
print("You have crashed and passed away. Your bravery will always be remembered even if you did fail terribly. You have failed",Fails,"times.")
time.sleep(3)
ans = input("Do you want to play again? ")
if ans == "yes":
time.sleep(3)
script()
else:
print("Our Earth is now an alien world...")
# Program stop here...
On the last line I want the program to stop: print("Our Earth is now an alien world...")
However, I know that there are ways to stop like quit(),exit(), sys.exit(), os._exit(). The problem is that sys.exit() stops the code but with the following exception message:
Traceback (most recent call last):
File "C:\Users\MEERJULHASH\Documents\lazy", line 5, in <module>
sys.exit()
SystemExit
On the other hand when I try to use the os._exit() on that last line line of code an error message comes up stating that TypeError: _exit() takes exactly 1 argument (0 given). exit() and quit() are not recommended for production code.
My question: are there any exiting commands that stop your code from carrying on without showing any message or ending with >>> or that it just closes the program?
You don't need a specific command. Just let your program reach its end and it will quit by itself. If you want to stop your program prematurely you can use sys.exit(0) (make sure you import sys) or os._exit(0) (import os) which avoids all of the Python shutdown logic.
You can also try a slightly safer way imo. The way I'm talking about is wrapping your main code in a try/except block, catch SystemExit, and call os._exit there, and only there!
This way you may call sys.exit normally anywhere in the code, let it "bubble-up" to the top level, gracefully closing all files and running all cleanups, and then finally calling os._exit. This is an example of what I'm talking about:
import sys
import os
emergency_code = 777
try:
# code
if something:
sys.exit() # normal exit with traceback
# more code
if something_critical:
sys.exit(emergency_code) # use only for emergencies
# more code
except SystemExit as e:
if e.code != emergency_code:
raise # normal exit
else:
os._exit(emergency_code) # you won't get an exception here!
The simple way to do this is:
Wrap all of your code in a function, which is typically called main
def main():
sleep = input("Commander, would you like to sleep now? If yes then we can take out your bed. ")
[more code snipped]
if someConditionThatShouldMakeTheScriptEnd:
return
[more code if the player keeps going]
At the bottom of your script, do
if __name__ == '__main__':
main()
[optionally print an exit message]
Anywhere you want to exit cleanly, just return out of your main function
As #MorganThrapp stated, the program will automatically exit cleanly when it finishes running.
The reason exit() and quit() are not recommended for production code are because it terminates your program outright. A better practice is to place your code in a try-except block (https://wiki.python.org/moin/HandlingExceptions). If the condition is met in the except block, the program will end cleanly and, if programmed to, spit out the exception/error raised. That is the "better" way. For all intents are purposes, quit() should work just fine.

Raspberry Pi input reading through endless while loop

I'm detecting a touch throuth a ttp223b touch sensor via python on a raspberry pi. It works pretty good but i need to wait for a second after a touch detection to prevent more than one execution so i just added a "time.sleep(1)".
The problem is that i also get multiple outputs, they are just time offset to 1 second, it seems that the routine is triggering multiple times at once.
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3, GPIO.IN)
while 1:
if GPIO.input(3) == GPIO.HIGH:
print "touched :3"
time.sleep(1)
Any suggestions how i could solve the issue?
add a sentinal
last_update = 0
while 1:
if time.time() - last_update > 1.5 : #1 and a half seconds
if GPIO.input(3) == GPIO.HIGH:
print "touched :3"
this will allow the GPIO to continue flushing so you dont pick up the old press (at least I think im not entirely sure how GPIO buffers work here)

English command [text RPG] - python

I am creating a text-RPG taking inspiration from older text adventures where the player enters an English command; such as 'pick up sword' and the like.
I have established a simple; enter 'A' to do this and enter 'B' to do this, but I would like to expand my system for more freedom.
I need to create a system that; when the player types in a command the program picks out key words.
I assume this would be achievable via the 'in' command.
Here is my code:
print "What would you like to do??"
input_loop_sleep = str('')
choice_sleep = raw_input(str('>>>'))
loop_sleep = False
table_time = False
bed_time = False
error_time = False
while loop_sleep == False:
if str('sleep') in choice_sleep or str('bed') in choice_sleep or str('goodnight') in choice_sleep or str('Sleep') in choice_sleep or str('tired') in choice_sleep:
while bed_time == False:
print "you decide to go back to sleep"
time.sleep(1)
print "..."
time.sleep(1)
print ""
time.sleep(1)
print "darkness"
time.sleep(1)
print ""
print "you wake up..."
time.sleep(1)
print "it is now 9:15am"
time == int(9.15)
time.sleep(1)
print "You are standing in your room, slightly more refreshed."
time.sleep(1)
print "there is a table with some things on it, stairs, and a wardrobe... with the doors wide open..."
time.sleep(1)
print "that's strange... you swear that they were shut when you went to sleep..."
break
else:
bed_time == True
break
bed_loop_choice = raw_input('>>>')
elif str('bedside') in choice_sleep or str('table') in str(choice_sleep):
while table_time == False:
print "You rub your eyes and pick up some belongings from a"
print "bedside table."
time.sleep(1)
print "Map added!"
time.sleep(1)
print "100 gold added!"
time.sleep(1)
print "Leather Bag added!"
cash == int(100)
time.sleep(1)
Map == str('map of', str(province))
Inventory == [str(Map)]
container == str('leather bag')
print "your", str(container), str("contains a"), str(Map), str('and'), str(cash)
break
else:
table_time == True
break
else:
print "invalid command!"
when I run the code, no matter what I type in it always goes with the 'sleep' option.
I probably just made some simple mistake!
can you please help me with what I did wrong and how I can fix it.
To answer your question about why the sleep loop is repeated all the time:
You're controlling the loop via
while bed_time == False:
but you never set bed_time to True in your loop (only in the else clause, but that clause is only executed when the loop exits normally, not when it's exited via break, as you're now doing - therefore bed_time will never change).
Furthermore, direct comparisons to a boolean value are usually frowned upon. The idiomatic way (in most languages, not just Python) would be while not bedtime:.
You should probably read some beginners' programming books and/or the Python tutorial before embarking on such a big project. There are several issues in your code that convey the impression that you really need to get a grasp on some basic programming principles and Python idioms.
For example,
int(9.15)
is not a good way to store a time - the result will be 9.
You're then using time == int(9.15), which means "compare the module time to the integer 9". I guess you meant time = int(9.15) which is already bad for the reasons stated above, but there would be even another problem: You would be overwriting the module name time, which will cause the subsequent time.sleep(1) command to fail with an AttributeError.
There's no need for most str() calls in your code because you're using it on objects that already are strings. Where you're not, it's incorrect: str('map of', str(province)) will raise TypeError (str takes only one argument).
You're using uppercase variable names for objects that aren't class instances.
Etc., etc...
I think this should be sufficient to sort out the problem
In [1]: str('bed') in "bedside"
Out[1]: True
So when you write bedside it gets inside the sleep option if condition and hence you are getting wrong answer .
You should write :
if str('bed') == choice_sleep or *other conditions* :
then got inside the sleep option
P.S: I am assuming you have imported the time module .
P.P.S: I checked the code with entering table it is working fine .

Categories

Resources