I am using a while loop to power an LED at regular intervals. I want to run the loop as normal, but have it break and clean up when a key is pressed.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(12,GPIO.OUT)
while True:
GPIO.output(12,GPIO.HIGH)
time.sleep(0.2)
GPIO.output(12,GPIO.LOW)
time.sleep(0.2)
Where should I add a keyboard interrupt command?
Well Ctrl-C raises KeyboardInterrupt. So, you just need to catch it:
while True:
try:
#code
except KeyboardInterrupt:
break
To catch all other errors use:
except Exception as ex : # catch other exceptions #
print(ex)
So, applied to your code:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(12,GPIO.OUT)
while True:
try:
GPIO.output(12,GPIO.HIGH)
time.sleep(0.2)
GPIO.output(12,GPIO.LOW)
time.sleep(0.2)
except KeyboardInterrupt:
break
except Exception as ex : # catch other exceptions #
print(ex)
Related
I'm trying to set up my Python script to allow the user to end the program, however the program needs to finish what it's doing first. I have the following code set up:
import sys
import keyboard
import time
prepareToStop = 0;
try:
while prepareToStop == 0:
#Program code here
print(prepareToStop)
time.sleep(0.1)
except KeyboardInterrupt:
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
print("Program shutting down...")
sys.exit()
However, the program still exits the loop as soon as the KeyboardInterrupt is received. I've seen advice that this could be fixed by placing the 'try, except' inside the while loop, however this causes the program to fail to detect the KeyboardInterrupt at all.
If I understand your problem correctly, maybe threading can help you. Note how end do something appears even after KeyboardInterrupt.
EDIT : I placed t.join() in the try
import sys
import time
import threading
def do_something(prepareToStop):
print(prepareToStop)
time.sleep(1)
print('end do something')
prepareToStop = 0
while prepareToStop == 0:
t = threading.Thread(target=do_something, args=[prepareToStop])
try:
t.start()
t.join() # wait for the threading task to end
except KeyboardInterrupt:
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
print('will not appear for last run')
print("Program shutting down...")
sys.exit()
Example of output :
0
end do something
will not appear for last run
0
^C
Program will shut down after current operation is complete.
will not appear for last run
Program shutting down...
end do something
The keyboard interrupt that you were trying to use works like any system interrupt and will jump immediately to the exception block, without going back to where it was when the interrupt has occurred.
You can confirm this by using the debugger in your IDE (ie. Press F5 in VSCODE).
The code below works like you want, but the user has to hold ESC key pressed in the keyboard for it to be captured from the program in the proper time.
import sys
import keyboard
import time
prepareToStop = 0;
while prepareToStop == 0:
if keyboard.is_pressed('Esc'):
prepareToStop = 1
print("\nProgram will shut down after current operation is complete.\n")
#Program code here
print('Sleeping 5 sec - hold the ESC key for some time to exit')
time.sleep(5)
print('This prints only after the delay')
#end code here
print(prepareToStop)
time.sleep(0.1)
print("Program shutting down...")
sys.exit()
And then I would recommend to change into this:
import sys
import keyboard
import time
while not keyboard.is_pressed('Esc'):
#Program code here
print('Sleeping 5 sec - hold the ESC key for some time to exit')
time.sleep(5)
print('This prints only after the delay')
#end code here
time.sleep(0.1)
print("Program shutting down...")
sys.exit()
The above solution is not better than using threading, but it is much more simpler.
Write this code with python3. But don't work. Only the relay comes on but it does not turn off.
I need this turn on and after 3 seconds to turn off.
This is my code:
import RPi.GPIO as GPIO
import time
channel = 23
# GPIO setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(channel, GPIO.OUT)
def motor_on(pin):
GPIO.output(pin, GPIO.HIGH) # Turn motor on
def motor_off(pin):
GPIO.output(pin, GPIO.LOW) # Turn motor off
if __name__ == '__main__':
try:
motor_on(channel)
time.sleep(2)
motor_off(channel)
time.sleep(2)
GPIO.cleanup()
motor_on(channel)
time.sleep(2)
motor_off(channel)
time.sleep(2)
GPIO.cleanup()
except KeyboardInterrupt:
GPIO.cleanup()
There are a couple problems with your code in general -- the indentation at the end should be like this
try:
motor_on(channel)
time.sleep(2)
motor_off(channel)
time.sleep(2)
GPIO.cleanup()
motor_on(channel)
time.sleep(2)
motor_off(channel)
time.sleep(2)
GPIO.cleanup()
except KeyboardInterrupt:
GPIO.cleanup()
and as above, running motor_on() and motor_off() after GPIO.cleanup() will give you errors if you don't run GPIO.setmode() and GPIO.setup() again first -- but with those things fixed, your code works perfectly fine to turn an LED on and off, so there may be a problem with your circuit.
I am trying to have a main thread wait for its worker threads to finish using the following code, but when I try to interrupt it with Ctrl+C it doesn't stop
import threading
import sys
exit = threading.Event()
#pass it to the threads
try:
exit.wait()
print('Goodbye')
sys.exit()
except KeyboardInterrupt:
print('Interrupted')
sys.exit()
UPDATE
Nothing prints. All background threads are daemons.
import threading
import sys
import time
exit = threading.Event()
#pass it to the threads
try:
print("hi")
time.sleep(20)
print('Goodbye')
sys.exit()
except KeyboardInterrupt:
print('Interrupted')
sys.exit()
Please try the above statement to test your code. i have tested it and its working fine for me.
As you are using exit.wait() without giving any timeouts, its running for infinite seconds. So please put some time as an agument.
Follow the below code:
exit = threading.Event()
#pass it to the threads
try:
print("hi")
exit.wait(5)
print('Goodbye')
sys.exit()
except KeyboardInterrupt:
print('Interrupted')
sys.exit()
I have a small piece of code detecting event on a specific GPIO of my raspberry. When the event is detected, a function named increase_counter is called, if inside the function i only keep the "print('Flash ... ')" i only have one print per event,but if i call a url with urllib2 the whole increase_counter is executed twice, so i will have 2 flashes counted.
import RPi.GPIO as GPIO
import time
import urllib2,json
def increase_counter(ch):
print('Flash ... ')
requete='http://192.168.1.20:8080/json.htm?type=command¶m=udevice&idx=52&svalue=1'
response=urllib2.urlopen(requete)
data = json.loads(response.read())
print data
IRPIN = 4
GPIO.setmode(GPIO.BCM) #GPIO SETUP
GPIO.setup(IRPIN,GPIO.IN) #GPIO SETUP
GPIO.add_event_detect(IRPIN, GPIO.FALLING, callback=increase_counter, bouncetime=3) #Calling event when flash is detected
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print(' Stopped !!!')
except:
print(' Stopped !!!')
raise
finally:
GPIO.remove_event_detect(IRPIN)
GPIO.cleanup(IRPIN) # GPIO cleanup
I have a problem with my code working with raspberry pi.
I just started with python so i need some help.
This is the code:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
led1=22
led2=17
GPIO.setup(led1, GPIO.OUT)
GPIO.setup(led2, GPIO.OUT)
def blink():
GPIO.output(led1, 1)
time.sleep(1)
GPIO.output(led1, 0)
GPIO.output(led2, 1)
time.sleep(1)
GPIO.output(led2, 0)
while(blink):
blink()
try:
main()
except KeyboardInterrupt:
GPIO.cleanup()
when I run this error appear in the console:
RuntimeWarning: This channel is already in use, continuing anyway. Use
GPIO.setwarnings(False) to disable warnings. GPIO.setup(led1,
GPIO.OUT) and:
RuntimeWarning: This channel is already in use, continuing anyway. Use
GPIO.setwarnings(False) to disable warnings. GPIO.setup(led2,
GPIO.OUT)
If I understand correctly the command GPIO.cleanup() should reset all pin of GPIO port and turn off the led.
but this in not happening in fact one of the led remain on.
How can change my code to resolve this issue?
Here is a little help, how to effectively separate your functions, and make them more general. Although this is a working Python script I provided, I didn't tested it on my raspi, but I think it will work -- anyway, let me know if there were any problems!
import RPi.GPIO as GPIO
import time
# Module level constants
LED1 = 22
LED2 = 17
# Sets up pins as outputs
def setup(*leds):
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)
for led in leds:
GPIO.setup(led, GPIO.OUT)
GPIO.output(led, GPIO.LOW)
# Turn on and off the leds
def blink(*leds):
# Blink all leds passed
for led in leds:
GPIO.output(led, GPIO.HIGH)
time.sleep(1)
GPIO.output(led, GPIO.LOW)
if __name__ == '__main__':
# Setup leds
setup(LED1, LED2)
# Run blinking forever
try:
while True:
blink(LED1, LED2)
# Stop on Ctrl+C and clean up
except KeyboardInterrupt:
GPIO.cleanup()
A friendly recommendation:
There is a dedicated Raspberry Pi StackExchange site too: https://raspberrypi.stackexchange.com/
You don't seem to have included main in your question. However the problem may occur if the programs exits for some reason other than KeyboardInterrupt. It's better to free the resource in a finally block
try:
main()
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
You are calling main() function but it's not declared (defined), you are using while(blink). So You need to delete the "main()" and put the "Try" before your main function which is the while(blink) loop. Don't forget the proper tabs there.