I'm configuring some leds and buttons on my raspberry pi, and when running the script the system warns me a channel is already in use. I tried looking for a solution, and a tip was to do a GPIO.Cleanup() in a finally clause. I tried, but it keeps failing. Any idea why? The error points to GPIO.setup(button_pin, GPIO.IN) but not sure to add these lines of code in my try clause?
#!/usr/bin/env python
import RPi.GPIO as GPIO
import os
import time
# Hide Warnings
# GPIO.setwarnings(False)
# Assign GPIO pin numbers
button_pin = 3 # Input Pin
button_led = 14 # Output Pin
green_led = 22 # Output Pin
red_led = 27 # Output Pin
# ir_receiver_pin = 17
# Use BCM pin numbering
GPIO.setmode(GPIO.BCM)
# 1. GPIO Setup
GPIO.setup(button_pin, GPIO.IN)
GPIO.setup(button_led, GPIO.OUT)
GPIO.setup(green_led, GPIO.OUT)
GPIO.setup(red_led, GPIO.OUT)
# 2. Button Led Behaviour on Startup
def button_led_on():
GPIO.output(button_led, GPIO.HIGH)
def button_led_off():
GPIO.output(button_led, GPIO.LOW)
def button_flicker_startup():
a = 1
while a < 4:
button_led_on()
time.sleep(0.3)
button_led_off()
time.sleep(0.3)
a = a + 1
button_led_on() # LED is high when Pi is on
# 3. Define front led behaviour on startup
def green_led_on():
GPIO.output(green_led, GPIO.HIGH)
def green_led_off():
GPIO.output(green_led, GPIO.LOW)
def red_led_on():
GPIO.output(red_led, GPIO.HIGH)
def red_led_off():
GPIO.output(red_led, GPIO.LOW)
def boot_flicker():
time.sleep(1.0)
green_led_on()
time.sleep(0.5)
green_led_off()
time.sleep(0.2)
green_led_on()
time.sleep(0.3)
green_led_off()
red_led_on()
time.sleep(0.3)
red_led_off()
time.sleep(0.2)
green_led_on() # LED is high when Pi is on
# 4. Main program
try:
button_flicker_startup()
boot_flicker()
GPIO.wait_for_edge(button_pin, GPIO.FALLING)
os.system("sudo shutdown -h now")
except:
pass
finally:
GPIO.cleanup()
I could use GPIO.setwarnings(False) but this is just hiding the error and would like to avoid that.
EDIT: My Raspberry Pi is using a Hifiberry dac who is using GPIO 2 and 3 for configuration. Could it be related to that?
I would change the main bit to this:
x = True
try:
while x:
button_flicker_startup()
boot_flicker()
GPIO.wait_for_edge(button_pin, GPIO.FALLING)
os.system("sudo shutdown -h now")
except:
pass
finally:
x = False
GPIO.cleanup()
because the functions are running, now we force them to stop running and then we cleanup.
I've used this video to help me, https://www.youtube.com/watch?v=LEi_dT9KDJI&t=257s :
I would watch it if I was you, I goes in depth about what you need/want.
Related
I currently have the problem that when I use the Gpio.setup(17, GPIO.OUT) function, the pin gets power. I have read a lot about this problem, but nothing has worked for me. I have even reinstalled Raspbian.
The script should work like this:
If I get a signal from the server the function messageDecoder() is called. If the message has the topic "rpi/gpio" the function setup_GPIO() should be called and then the function on(channel1) to supply the pin with power. But the pin already has power when setup_GPIO() is called! But I do not know why.
Does anyone have s solution?
Here is my code:
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time
import datetime as datetime
def setup_GPIO(): # !!! when that function is called the pin gets power
GPIO.setmode(GPIO.BCM)
GPIO.setup(channel1, GPIO.OUT)
def on(pin):
print("ON", pin)
GPIO.output(pin, GPIO.HIGH) # !!! here the pin should get power, but it gets it already before
def off(pin):
print("OFF", pin)
GPIO.output(pin, GPIO.LOW)
GPIO.cleanup()
def connectionStatus(client, userdata, flags, rc):
mqttClient.subscribe("time")
mqttClient.subscribe("rpi/gpio")
def messageDecoder(client, userdata, msg):
print("topic: " , msg.topic, "payload: " , msg.payload,)
if msg.topic == "time":
...
elif msg.topic == "rpi/gpio":
messageActiv = str(msg.payload.decode(encoding='UTF-8'))
if messageActiv == "on":
setup_GPIO() # !!! here I call the setup_GPIO() function and the pin gets power
print("System is ON!")
on(channel1) # !!! I could leave out that function and the pin would have power
elif messageActiv == "off":
print("System is OFF!")
off(channel1)
else:
print("Unknown message!")
else:
print("Unknown topic!")
channel1 = 17
clientName = "RPI"
serverAddress = "192.168.8.138"
mqttClient = mqtt.Client(clientName)
mqttClient.connect(serverAddress)
if __name__ == '__main__':
i = 0
try:
now = datetime.datetime.today()
mqttClient.on_connect = connectionStatus
mqttClient.on_message = messageDecoder
mqttClient.loop_forever()
except KeyboardInterrupt:
print("Interrupt")
mqttClient.disconnect()
Thanks in advance :D
It appears the default output once setting the pin to be output is for the value to be high. Based on the docs, you can use the parameter initial=GPIO.HIGH to set the initial value.
GPIO.setup(channel1, GPIO.OUT,initial=GPIO.HIGH)
The code above sets the initial value to low according to the OP. Not sure why this happens. Please fill in if you know.
https://sourceforge.net/p/raspberry-gpio-python/wiki/BasicUsage/
Edited based on info provided in comment by OP
I'm working on PIR sensor in order to detect the movement of human beings. Here is below the code that currently I am using and I just need to make a counter inside the loop in order to count the # of movements. Thanks in advance!!
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN) # PIR motion sensor
GPIO.setup(3, GPIO.OUT) #LED output pin
while True:
i=GPIO.input(11)
if i==0: #sensor is LOW
print "Not Occupied",i
GPIO.output(3, 0) #Turn OFF LED
time.sleep(0.1)
elif i==1: # sensor is HIGH
print "Occupied",i
GPIO.output(3, 1) #Turn ON LED
time.sleep(0.1)
When I was starting with Raspberry Pi, I was using only RPi.GPIO library, but now I am using only gpiozero library. I think, it is more clear than RPi.GPIO
Here is my solution of your problem using library gpiozero instead of RPi.GPIO:
from gpiozero import LED, MotionSensor
from signal import pause
pir = MotionSensor(11)
led = LED(3)
motion_counter = 0
def on_motion():
global motion_counter
led.on()
motion_counter += 1
print(motion_counter)
def on_no_motion():
led.off()
pir.when_motion = on_motion
pir.when_no_motion = on_no_motion
pause()
More about this great library: https://gpiozero.readthedocs.io/en/stable/
Your question is kind of confusing but here is how you would set a counter
counter = 0
while True:
counter += 1
i=GPIO.input(11)
if i==0: #sensor is LOW
print "Not Occupied",i
GPIO.output(3, 0) #Turn OFF LED
time.sleep(0.1)
elif i==1: # sensor is HIGH
print "Occupied",i
GPIO.output(3, 1) #Turn ON LED
time.sleep(0.1)`
print(counter)
I am doing a parking sensor with raspberry pi and python
This is the code :
import RPi.GPIO as GPIO
import time
#from picamera import PiCamera
from time import sleep
from gpiozero import MotionSensor
import smtplib
sender = '*****#gmail.com'
reciever = '*****#gmail.com'
def BlueLED (): #Blue LED Function
GPIO.output(27, GPIO.HIGH)
time.sleep(3)
GPIO.output(27, GPIO.LOW)
def RedLED (): #Red LED Function
GPIO.output(22,GPIO.HIGH)
time.sleep(3)
GPIO.output(22, GPIO.LOW)
def Buzzer (): #Buzzer Function
GPIO.output(17, GPIO. HIGH)
time.sleep(3)
GPIO.output(17, GPIO.LOW)
def email(sender,reciever,msg):
try :
server = smtplib.SMTP('smtp.gmail.com',587)
server.ehlo()
server.starttls()
server.login(sender,'******')
server.sendmail(sender,reciever,msg)
server.close()
print('Email sent!')
except :
print('Error')
try :
GPIO.setmode(GPIO.BCM)
#camera = PiCamera()
pir = MotionSensor(4)
GPIO.setwarnings(False)
GPIO.setup(27, GPIO.OUT) #blueLED
GPIO.setup(22, GPIO.OUT) #redLED
GPIO.setup(17, GPIO.OUT) #buzzer
GPIO.setup(18, GPIO.OUT) #tempsensor
GPIO.setup(21, GPIO.IN, pull_up_down = GPIO.PUD_UP) #entry button
count = 0
while True :
if (pir.motion_detected):
print('Motion Detected')
#Calling the buzzer function
#Buzzer()
#The content that is going to be sent via email
msg = """Subject : Car Park
(Picture) """
email(sender,reciever,msg)
print('\nPlease press the button for the gate to open')
while True :
if(GPIO.input(21) == False):
if (count < 5):
BlueLED()
print('\nThere are ',(5-count), ' parking spaces empty ')
else :
RedLED()
print('\nSorry but the parking is full')
count = count + 1
except Exception as ex :
print('Error occured',ex)
My problem is that the first while loop is not working, i.e if the motion sensor is triggered nothing happens yet you can repress the button and the count is increased. I'm guessing there is an easy solution to this but non seem to come to mind. Would love your help, thanks
Your second while loop has no break point!!!
Your first while loop runs until it detects motion and then enters the second loop, and your second loop runs forever.
If you want both loops to work simultaneously then you should use threads!!!
If not then make a break point in second loop.
Simple example:
import time
count=0
count2=0
while True: #starting first loop
count+=1 # counting to 100 to start second loop
if count==100:
print("its 100 entering second loop")
time.sleep(1)
while True: # entering second loop
count2+=1 #counting to 100 to exit second loop
if count2==100:
print("its 100 exitin second loop")
time.sleep(1)
count=0
count2=0
break # exiting second loop this is the break point
So im writing a basic programme to turn an LED on using a potentiometer, this is my code:
def pot():
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22, GPIO.IN)
GPIO.output(4, GPIO.LOW)
try:
while True:
if (GPIO.input(22) == GPIO.HIGH):
print("switch activated")
GPIO.output(4, GPIO.HIGH)
if (GPIO.input(22) == GPIO.LOW):
GPIO.output(4, GPIO.LOW)
else:
GPIO.output(4, GPIO.LOW)
except KeyboardInterrupt:
GPIO.cleanup()
pot()
When i activate the potentiometer i only want "switch activated" to be printed once but i want the LED to keep running until i deactivate the potentiometer. As the code is "switch activated" will obviously print constantly while the pot is activated. I've tried using a break and other such things but they all either ended the programme or turned off the LED as well. How can i solve this?
Since you want the LED to continue glowing, it's as simple as adding another loop. Here's a (slightly) modified version of your code that should work:
def pot():
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22, GPIO.IN)
GPIO.output(4, GPIO.LOW)
try:
while True:
if (GPIO.input(22) == GPIO.HIGH):
print("switch activated")
# modified part
while (GPIO.input(22) == GPIO.HIGH):
GPIO.output(4, GPIO.HIGH)
# end modification
else:
GPIO.output(4, GPIO.LOW)
except KeyboardInterrupt:
GPIO.cleanup()
pot()
Another way is to switch on the LED and wait for the input at pin 22 to turn LOW. Just change the modified part as below.
# modified part
GPIO.output(4, GPIO.HIGH)
while (GPIO.input(22) == GPIO.HIGH):
pass
# end modification
Apparently you want to have the LED react constantly to the signal, but only print the message when the signal changes.
The way to do this is to track the state with a variable.
Note: I'm somewhat confused by the nested GPIO.input calls inside your loop. It seems like these would be redundant, because if the return value of GPIO.input changed, it'd get handled in the next iteration...
try:
state = None
while True:
signal = GPIO.input(22)
GPIO.output(4, signal)
if signal != state:
if signal == GPIO.HIGH:
print("switch activated")
else:
print("switch deactivated")
state = signal
except KeyboardInterrupt:
GPIO.cleanup()
Outputs can be checked as inputs, too. So you can change your logic to only set the output high if it is currently low.
def pot():
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22, GPIO.IN)
GPIO.output(4, GPIO.LOW)
# Initialize state
state = GPIO.LOW
try:
while True:
# Set the output high only if the input is high and the output is low
if (GPIO.input(22) == GPIO.HIGH) and (GPIO.input(4) == GPIO.LOW):
print("switch activated")
GPIO.output(4, GPIO.HIGH)
# If you want, you could do the same here and add a check on the output to
# only turn it low if it is currently high
elif (GPIO.input(22) == GPIO.LOW):
GPIO.output(4, GPIO.LOW)
except KeyboardInterrupt:
GPIO.cleanup()
pot()
You need to move print("switch activated") outside the loop if you only want it to be executed once.
I`m writing simple script for my home security system. it consist of button, led, buzzer, and sensor. It works like this:
- button pressed, - alarm function on, - it detects me ( everything is fine), - button pressed again, - alarm off(still fine) - button pressed again - and heres the problem: when a wave if front of the alarm when it was off, it still catches the movement, keeps this signal somehow, and the first thing after - alarm on is spotted signal, even if sensor didnt sent signal.
Hope i explain it clear enough. Here's the code:
import RPi.GPIO as GPIO
import time
import os
from itertools import cycle
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(04, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)#switch
GPIO.setup(17, GPIO.OUT)#led
GPIO.setup(18, GPIO.OUT)#buzzer
GPIO.setup(21, GPIO.IN)#sensor
#### definicje funkcji #####
############################
############################
def led_on(czas):
GPIO.output(17,1)
time.sleep(czas)
GPIO.output(17,0)
return;
#led_on(10)
############################
def buzzer_on(czas):
GPIO.output(18,1)
time.sleep(czas)
GPIO.output(18,0)
return;
#buzzer_on(0.1)
############################
def alarm_on():
print "alarm on"
while True:
if (GPIO.input(21)):
print "spotted!"
buzzer_on(0.1)
led_on(0.1)
time.sleep(1)
if (GPIO.input(04) == 1):
next(wlacznik)
alarm_off();
led_on(1)
break
return;
def alarm_off():
print "alarm off"
return;
############################
########################################### PROGRAM ###########################################
###############################################################################################
###############################################################################################
### WLACZNIK_ALARMU ######
wlacznik = cycle(range(2))
print "wartosc wlacznika:"
print next(wlacznik)
prev_input = 0 #toggle dla przycisku
while True:
input = GPIO.input(04)
#if the last reading was low and this one high, print
if ((not prev_input) and input):
print("Button pressed")
if (next(wlacznik) == 1):
led_on(0.1)
time.sleep(0.1)
led_on(0.1)
time.sleep(1)
alarm_on();
#update previous input
prev_input = input
#slight pause to debounce
time.sleep(0.05)
########################################### KONIEC ############################################
GPIO.cleanup()