i need to combine my python codes which when the door is closed the PIR sensor will start to sense movement. when i combine these two files, it will run only the first while loop. it did not run to the next loop. can someone figure it out?
the first while loop:
#function for door closing
def door_open():
print("Door Open")
# function for the door closing
def door_close():
print("Door Close")
while True:
if GPIO.input(door_sensor): # if door is opened
if (sensorTrigger):
door_open() # fire GA code
sensorTrigger = False # make sure it doesn't fire again
if not io.input(door_sensor): # if door is closed
if not (sensorTrigger):
door_close() # fire GA code
sensorTrigger = True # make sure it doesn't fire again
second while loop:
Current_State = 0
Previous_State = 0
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
print " Motion detected!"
# Record previous state
Previous_State=1
elif Current_State==0 and Previous_State==1:
# PIR has returned to ready state
print " Ready"
Previous_State=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()
i try to combine these two loops, but the result only the first loop is run
#function for door closing
def door_open():
print("Door Open")
# function for the door closing
def door_close():
print("Door Close")
while True:
if GPIO.input(door_sensor): # if door is opened
if (sensorTrigger):
door_open() # fire GA code
sensorTrigger = False # make sure it doesn't fire again
if not io.input(door_sensor): # if door is closed
if not (sensorTrigger):
door_close() # fire GA code
sensorTrigger = True # make sure it doesn't fire again
door_close_thread = threading.Thread(target=door_close)
door_close_thread.daemon = True
door_close_thread.start()
Current_State = 0
Previous_State = 0
try:
print "Waiting for PIR to settle..."
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
print " Motion detected!"
# Record previous state
Previous_State=1
if not Current_State==0 and Previous_State==1:
# PIR has returned to ready state
print " Ready"
Previous_State=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()
Don't use two while loops.
The only way you'll break out of while True: is by calling break.
Use a single while loop and split it with if conditionals.
Related
i'm using the methode when_motion from the gpiozero library to listen on 3 motion sensor.
for what i understand, this methode permit to callback a fonction when motion is detected while the rest of the programme is running
i'm trying to modify the global variabled i've named state and pickedup to trigger different phase of the programme, to get more control on the overall behaviour.
sensors are triggering sound as expected but the main programme is stuck, never seem to pass the WaitUntil function at the beginning of the main loop
i suspect the state variable not really being global and/or not changing value (but it could be something else
how can i really affect global variable from my method in order for my main programme to go on?
every design suggestion is welcome
here's my code so far:
# a fonction that wait until a condition is fulfill to continue the code
def WaitUntil(condition, output): #defines function
wU = True
while True:
if condition: #checks the condition
output
wU = False
def State(val): #return a global variable without interrupting motion methode
global state
state = val
print("state = {}".format(val))
def Pickedup(val): #return a global variable without interrupting motion methode
global pickedup
pickedup = val
print("pickedup = {}".format(val))
class PIR: # motion sensor object
global state #variables to trigger different phase of the programme
state = 0
global pickedup
pickedup = False
def __init__(self, pin, element):
self.pir = MotionSensor(pin=pin)
self.pir.when_motion = self.motion
self.element = element
self.state = state
self.pickedup = pickedup
def motion(self):
global state
global pickedup
if state == 3: #this is for not playing a sound when you juste put back the object in its jar
self.pir.wait_for_no_motion()
sleep(2)
print("object is back")
State(0)
elif state == 0:
sa.stop_all() #stop alredy playing sound
wave_obj = sa.WaveObject.from_wave_file("{}.wav".format(self.element)) #play the sound associated with this sensor when you pick an object from the associated jar
wave_obj.play()
sleep(5)
print ("objet {} is picked".format(self.element))
Pickedup(True) #wait and consider that the object is picked
WaitUntil(state == 2,FadeOut(0.5)) #wait for programme to reach state 2 and fading out the current playing sound
pir1 = PIR(17,"feu")
pir2 = PIR(27,"eau")
pir3 = PIR(22,"vent")
while True: #from here is the start of the continuous programme
WaitUntil(pickedup == True, print("pick an object")) #here is the problem, cant seem to pass to the next line from here
print("put object in the box")
while cardcount == 0 and pickedup == True:
cards = PN5180().inventory()
cardcount = len(cards)
print(f"{len(cards)} card(s) detected: {' - '.join(cards)}")
#code continue
I currently have a piece of code designed to communicate with two motors via a TCP Device Server which sends ASCII commands to them in order to trace sinusoidal paths. I wish to have the movement continue indefinitely and then immediately stop when KeyboardInterrupt is triggered, then have the motors move back to their defined home positions before the program ends.
This code can currently replicate sinusodial motion, but it currently does not stop immediately when KeyboardInterrupt is triggered, nor do the motors move back to their home positions. The sinusodial loop is designed such that when KeyboardInterrupt occurs, a global variable called move changes from True to False and this breaks the loop. The simplified code is given below:
import socket
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.connect(("192.168.177.200", 4001)) # Y motor
s2.connect(("192.168.177.200", 4002)) # X motor
# Disengage the motor to allow manual movement by wheel
s1.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
homeposition = input("Are the motors centred? Press 'y' to confirm: ")
if homeposition == 'y':
s1.send("EN\n".encode("ASCII"))
s2.send("EN\n".encode("ASCII")) # energise the motors so they cannot be moved
print("Motors Engaged")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
else:
print("Set home position and restart program")
exit()
#----ADD DATA FOR SAMPLING SINUSODIAL FUNCTIONS----
radius = input("Desired radius of movement (mm):")
radius = float(radius)
print("radius of circular path (mm): ", radius)
# need slightly different ratios for each motor due to different thread sizes
gearpositionlim_x = 20000 #one rotation equals 2.5mm (+ bearing ration on manipulator of 2:1)
gearpositionlim_y = 10000 #one rotation equals 2mm
# sample sine and cosine
step = 2*pi / 1000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim_x*np.cos(time_range)
y_motorrange = gearpositionlim_y*np.sin(time_range)
x_motorrange = ['la'+str(int(i)) for i in x_motorrange]
y_motorrange = ['la'+str(int(i)) for i in y_motorrange]
#print(x_motorrange)
x_motorrange_wcom = []
y_motorrange_wcom = []
{x_motorrange_wcom.extend([e, 'm', 'np']) for e in x_motorrange} # add movement prompts and wait for movement to complete
{y_motorrange_wcom.extend([e, 'm', 'np']) for e in y_motorrange} # add movement prompts and wait for movement to complete
# Set Acceleration and Deceleration of Motors
s1.send("AC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("AC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Acceleration set to 10 ")
s1.send("DEC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DEC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Deceleration set to 10")
def setup(): #move to initial position before starting movement
s2.send(str(str(x_motorrange_wcom[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
move = False
print(move)
end()
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
I believe my issue is with my function motormove(), but I am unsure of what I should do in order to achieve my desired operation. Does anyone know how this can be achieved?
Thanks in advance
Using library signal should be sufficient for your usecase. See code bellow.
import socket
import signal
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
gearpositionlim = int(10000)
# sample sine and cosine
step = 2*pi / 2000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim*np.sin(time_range)
y_motorrange = gearpositionlim*np.cos(time_range)
def handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == 'y':
exit(1)
else:
#Do STH
def setup():
s2.send(y_motorrange[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
signal.signal(signal.SIGINT, handler)
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
This should be working just fine, note the signal function being called on KeyboardInterrupt, this redirects to signal function where, you can either exit or do something else.
I have two functions. What I want to do here is: when ser.write('1') (i.e. when Python is telling keep the gate open), I want to note the time and keep the door open for 8 seconds. Now, if within
that time, send_data(data) returns true, I want to write ser.write('0') or keep the gate closed.
Can anyone suggest me how to implement this? I tried to do this via a while loop, but I was not successful.
def send_data(data):
if (data ==0):
print "manga"
return True
else:
print "muringa"
return False
def delay_for_goodant(data):
print "thenga"
global ser
try:
if (ser == None):
ser = serial.Serial("COM1",9600,timeout = 0)
if send_data(data) is True:
ser.write('0')
print "python is telling arduino to keep the gate closed"
else:
start_time_opening = time.time()
ser.write('1')
end_time_opening = time.time()
elapsed_time = end_time_opening - start_time_opening
print "time taken for opening is"+ str(end_time_opening - start_time_opening)
if elapsed_time < 8 and send_data(data) is True:
ser.write('0')
elif elapsed_time < 8 and send_data(data) is False:
ser.write('1')
incoming_data2 = ser.readline()
print "python is telling the arduino to keep the gate open"
print "incoming_data for opening is-",(incoming_data2)
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.
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()