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
Related
Let's imagine that someone has plugged some sensor on his raspberry, but I don't know which one. Would it be possible for me to create a program that guess which sensor is connected ?
So that I could then give him a program that would use those sensor.
If it is possible, is there a python library to do that ?
The value of state can be either 1 or GPIO.HIGH or True for the ON state and 0 or GPIO.LOW or False for OFF.
sudo pip install RPi.GPIO
RPi.GPIO
import RPi.GPIO as GPIO
GPIO.setup( self.PIN , GPIO.IN )
if( GPIO.input( self.PIN ) == 0 )
self.value = 'Device not connected'
else:
#self.value = 'Device is connected'
return GPIO.output(pin, 1)
gpiozero
def _state_to_value(self, state):
return int(state == self._active_state)
def _read(self):
try:
return self._state_to_value(self.pin.state)
except (AttributeError, TypeError):
self._check_open()
raise
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.
I am trying to make a door swipe card system in Python for my Raspberry Pi. I broke the program into two: A Door Alarm and a Card Swipe Recording system. The two programs work individually but how do I combine the two programs into one python file? I've tried threading but it doesn't seem to work.
Below are the programs:
1.) Door Alarm: If door is left open for a certain duration, an led will blink, then an alarm will ring
import time
import RPi.GPIO as gpio
led = 37
buzzer = 11
door = 16
gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(buzzer, gpio.OUT)
gpio.setup(led, gpio.OUT)
gpio.setup(door, gpio.IN, pull_up_down=gpio.PUD_UP)
def blink(buzzer):
gpio.output(buzzer, True)
time.sleep(0.1)
gpio.output(buzzer, False)
time.sleep(0.1)
return
def blink(led):
gpio.output(led, True)
time.sleep(1)
gpio.output(led, False)
time.sleep(1)
return
while True:
if gpio.input(door):
time.sleep(3)
for i in range(0,5):
blink(led)
for i in range (0,5):
blink(buzzer)
else:
gpio.output(buzzer, False)
gpio.cleanup()
2.) Card Swipe Recording System: When someone swipes their card, the led blinks and a picture is taken
import datetime
import time
import os
import RPi.GPIO as gpio
led = 37
t = datetime.datetime.now()
gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(led, gpio.OUT)
def blink(led):
gpio.output(led, True)
time.sleep(0.1)
gpio.output(led, False)
time.sleep(0.1)
while True:
card = raw_input()
f = open("Laptop Sign Out" + '.txt', 'a')
f.write("OneCard Number: " + card[1:10] + " Time: " + t.strftime("%m-%d-%Y %H:%M:%S"))
f.write('\n')
f.write(';')
f.write('\n')
f.close()
time.sleep(1)
for i in range(0,3):
blink(led)
os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
time.sleep(3)
gpio.cleanup()
(UPDATE) Also, below is my attempt at threading:
import time
import RPi.GPIO as gpio
import os
import datetime
from threading import Thread
led = 37
buzzer = 11
door = 16
t = datetime.datetime.now()
gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(buzzer, gpio.OUT)
gpio.setup(led, gpio.OUT)
gpio.setup(door, gpio.IN, pull_up_down=gpio.PUD_UP)
def blink(buzzer):
gpio.output(buzzer, True)
time.sleep(0.1)
gpio.output(buzzer, False)
time.sleep(0.1)
return
def blink(led):
gpio.output(led, True)
time.sleep(1)
gpio.output(led, False)
time.sleep(1)
return
def doorsensor():
while True:
if gpio.input(door):
time.sleep(3)
for i in range(0,5):
blink(led)
for i in range (0,5):
blink(buzzer)
else:
gpio.output(buzzer, False)
def cardreader():
while True:
card = raw_input()
f = open("Laptop Sign Out" + '.txt', 'a')
f.write("OneCard Number: " + card[1:10] + " Time: " + t.strftime("%m-%d-%Y %H:%M:%S"))
f.write('\n')
f.write(';')
f.write('\n')
f.close()
time.sleep(1)
for i in range(0,3):
blink(led)
os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
time.sleep(3)
f1 = Thread(target = doorsensor())
f2 = Thread(target = cardreader())
f2.start()
f1.start()
gpio.cleanup()
You need to pass your thread functions as the target arguments, not their return values:
import sleep
f1 = Thread(target=doorsensor) # Remove parentheses after doorsensor
f1.daemon = True
f1.start()
f2 = Thread(target=cardreader) # Remove parentheses after cardreader
f2.daemon = True
f2.start()
# Use a try block to catch Ctrl+C
try:
# Use a while loop to keep the program from exiting and killing the threads
while True:
time.sleep(1.0)
except KeyboardInterrupt:
pass
gpio.cleanup()
The daemon property is set on each thread so that the program will exit when only the daemon threads are left:
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.
I'm presenting a thread-less approach.
The idea is to turn your while bodies into update functions, and call them alternatively.
First off, your door loop becomes
def update_door():
if gpio.input(door):
time.sleep(3)
for i in range(0,5):
blink(led)
for i in range (0,5):
blink(buzzer)
else:
gpio.output(buzzer, False)
Then your card swipe recording system becomes
def update_card():
card = raw_input()
f = open("Laptop Sign Out" + '.txt', 'a')
f.write("OneCard Number: " + card[1:10] + " Time: " + t.strftime("%m-%d-%Y %H:%M:%S"))
f.write('\n')
f.write(';')
f.write('\n')
f.close()
time.sleep(1)
for i in range(0,3):
blink(led)
os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
time.sleep(3)
Finally, your main loop becomes:
while True:
update_door()
update_card()
But a problem arises: time.sleep in update_card will delay update_door as well.
Here, you have three solutions:
1 - It's ok if update_door is delayed
Well, ok.
2 - It's not ok if update_door is delayed, but it's ok if update_card is not delayed
Then just remove time.sleep(3).
3 - You need update_door not to be delayed, and update_card to be delayed
Then you can set a manual timer, using the time module.
lastCardUpdate = time.time()
while True:
update_door()
now = time.time()
if now - lastCardUpdate >= 3:
update_card()
lastCardUpdate = now
But raw_input in update_card is a blocking method, waiting for a user input.
If you do need this user input to happen every three seconds, then this approach cannot be used.
If you can move it before the while, ie outside of the update_card function, then it's fine.
Else, you will indeed need to use threads.
If you are attempting to run these two programs simultaneously, then you will have to use either threading or multiprocessing, which you say you have attempted. If you have, may we see your attempt as we may be then able to help you with your issue there.
One other issue is that all of your methods are named Blink, which is not allowed in Python, in python all of your methods should have different names.
Edit: For threading make sure to type threading.Thread(target = target) as your code
Regardless of any other mistake, you need to join one of your threads once they have been started.
f1 = Thread(target = doorsensor())
f2 = Thread(target = cardreader())
f2.start()
f1.start()
f1.join()
What does f1.join() do?
Basically, it tells Python to wait until f1 has finished running.
If you don't do so, the program will start f1 and f2, then will exit.
Upon exiting, Python will release all the resources, including those two threads, whose execution will stop.
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.
First off, I'm very new to python. I have a raspberry pi connected via lan to a few nodes. I want the pi to be the power interface for the nodes. When a button is pressed, magic packets get sent to the nodes to wake them up. Once the nodes have been powered up, the same momentary switch will be able to power off the nodes, by ssh-ing into each and executing the "poweroff" command. While the machines are coming up, and while the machines are powering off, an LED should be blinking.
My attempt so far has most of the functionality I described, but the LED blinking is spotty, and I'm noticing that some of my threads are being redundantly executed.
My Question is, how do I get the led blinking to more accurately represent the state change of the machines.
Here is the script:
#!/usr/bin/python
import RPi.GPIO as GPIO
import threading
import time
import os
from subprocess import call
nodes = [
{
"name": "node-1",
"mac": "80:EE:73:AE:AA:7C",
"ip": "10.15.1.254",
},
#more nodes...
]
#function to blink the leds
def blink(pin,number):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
count =0
while count < number:
GPIO.output(pin,GPIO.HIGH)
time.sleep(.5)
GPIO.output(pin,GPIO.LOW)
time.sleep(.5)
count +=1
return
except Exception as inst:
print "error: could not blink"
#function to turn LED on or off based on power state
def led(pin, state):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
if state ==1:
GPIO.output(pin, GPIO.HIGH)
else:
GPIO.output(pin, GPIO.LOW)
except:
print "error: could not turn on LED"
#function to wake up a node
def wake(node, mac):
try:
print "waking" +node
call(["wakeonlan", mac])
except Exception as inst:
print "error: could not wake " + node
#function to power off nodes
def shutdown(node, ip):
try:
print "shutting down " +node
call(["ssh", "-o", "StrictHostKeyChecking=no", "root#"+ip, "poweroff"])
except Exception as inst:
print "error: could not shutdown " + node
#function to check the state of the nodes (if node can be pinged, it is up)
def checkstate(node,ip):
try:
response = os.system("ping -i 0.1 -c 1 -w2 " + ip + " > /dev/null 2>&1")
if response == 0:
state =1
else:
state =0
return state
except:
print "error could not ping"
#function checks if all node states are the same
def checksame(list):
try:
list = iter(list)
first = next(list)
return all(first == rest for rest in list)
except StopIteration:
return list[0]
def main():
while True:
state = []
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
state.append(checkstate(node_name,node_ip)) #write each node state to an array
power_state = state[1]
if power_state ==1:
led(40,1) #turn LED on because all the nodes are on
if not checksame(state): #checks that all values in state array are the same. If not, led should blink because there is a state change or an error in a node
t = threading.Thread(target=blink, args=(40,8) )
t.start()
else:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(05, GPIO.IN, pull_up_down=GPIO.PUD_UP)
button_state = GPIO.input(05)
if button_state == False: #this is the button press detection
if power_state ==1:
#button has been pressed, and machines are on, need to be off
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
shutdown(node_name, node_ip)
print "Nodes have been shut down"
else:
#button has been pressed, machines are off, need to be on
for node in nodes:
node_name = node.get('name', '')
node_mac = node.get('mac', '')
wake(node_name,node_mac)
print "Nodes have been powered on"
t = threading.Thread(target=blink, args=(40, 180) )#this is a hack to show the LED blinking until the nodes can be pinged, otherwise, the LED would be off until the nodes were ping-able
t.start()
time.sleep(0.2)
if __name__ == "__main__":
main()