问题
I'm trying to write a little script to control two raspberry pi's gpio output pins based on two factors: the state of GPIO.input.17 and the time of day.
I would like gpio.output.23 and gpio.output.25 to be low when gpio.input.17 is low.
I would like gpio.output.23 to go high when gpio.input.17 is high and the time is between 0700-2159.
I would like gpio.output.25 to go high when gpio.input.17 is high and the time is between 2200-0659.
so far, the code i've put together looks like this:
#!/usr/bin/python
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# Setup GPIO pins
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # set GPIO 17 as input
GPIO.setup(23, GPIO.OUT) # set GPIO 23 as output
GPIO.setup(25, GPIO.OUT) # set GPIO 25 as output
GPIO.output(23, 0) # set GPIO 23 as low
GPIO.output(25, 0) # set GPIO 25 as low
while True:
dt = list(time.localtime())
hour = dt[3]
minute = dt[4]
second = dt[5]
time.sleep(1)
print hour,minute,second;
PIR_Active = GPIO.input(17)
if not PIR_Active:
GPIO.output(23, 0)
GPIO.output(25, 0)
elif (PIR_Active and (hour>=00 and hour<=6) and (minute >=00 and minute<=59) and (second >=0 and second<=59)):
GPIO.output(25, 1)
elif (PIR_Active and (hour>=7 and hour<=11) and (minute>=0 and minute<=36) and (second>=0 and second<=59)):
GPIO.output(23, 1)
else: (PIR_Active and (hour>=11 and hour<=23) and (minute >=37 and minute<=59) and (second >=0 and second<=59));
GPIO.output(25, 1)
time.sleep(1)
GPIO.cleanup()
I have LED's connected to pins 23 and 25, the times shown in the script are from my testing and the results i see with this code are:
Out.Pin 23 toggles between high and low following In.Pin.17's status whilst the time variable is true
Out.Pin 23 stops toggling between high and low whilst the time variable is not true
I feel like I have Out.Pin.23 working...
Out.Pin 25 immediately lights up when the code is executed and stays lit regardless of In.Pin.17's status or the time.
Please ignore the times in the script, they're from my testing and won't match up with the requirements above.
I'm a beginner with coding and writing scripts and would appreciate any assistance from the community.
Thanks
回答1:
First off, I acknowledge this is not a full answer to your question, but too much for a comment.
The purpose of this partial answer is to suggest a simplification to the datetime tests.
- Set a
now
time - Set a
day
time - Set a
night
time - User a single, simple logical operator to test if it's day or night.
Example:
import datetime as dt
now = dt.datetime.now().time()
day = dt.time(7, 00)
night = dt.time(22, 00)
# Test if it's day time.
now
>>> datetime.time(14, 8, 6, 000000)
day < now < night
>>> True
# Test again at midnight.
now
>>> datetime.time(0, 0)
day < now < night
>>> False
Integrating this logic into your code will help to simplify the if/elif
, and
statements.
For example, this:
(PIR_Active and (hour>=00 and hour<=6) and (minute >=00 and minute<=59) and (second >=0 and second<=59))
... can become this - obviously using your own time definitions.
all([PIR_Active, day < now < night])
回答2:
thanks for your suggestion. Although I could run this in IDLE and followed the logic in your code, I wasn't able to integrate it into my script (it broke what i had working in the first place: GPIO.output.23 following GPIO.input.17's state 'during active hours'.
Given my noobishness, can you guide me on where I'm going wrong with your suggestion please? I like the idea of tidying the if/elif statements up.
#!/usr/bin/python
import time
import datetime as dt
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# Define Time Variables
now = dt.datetime.now().time()
day = dt.time(16, 32, 59, 000000)
night = dt.time(16, 33, 00, 000000)
# Setup GPIO pins
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # set GPIO 17 as input
GPIO.setup(23, GPIO.OUT) # set GPIO 23 as output
GPIO.setup(25, GPIO.OUT) # set GPIO 25 as output
GPIO.output(23, 0) # set GPIO 23 as low
GPIO.output(25, 1) # set GPIO 25 as low
while True:
dt = list(time.localtime())
hour = dt[3]
minute = dt[4]
second = dt[5]
time.sleep(1)
print hour,minute,second;
PIR_Active = GPIO.input(17)
if not PIR_Active:
GPIO.output(23, 0)
GPIO.output(25, 0)
elif all([PIR_Active, day < now < night]):
GPIO.output(23, 1)
else: all([PIR_Active, day < now < night]);
GPIO.output(25, 1)
time.sleep(1)
GPIO.cleanup()
回答3:
I've managed to work this issue out... my original else statement was invalid, so i've added a third elif with my 'night time' conditions and finished the statement with an else that sets both GPIO.out pins to 1.
I've also inverted the 'resting' state of the outputs because i think the relay unit I've got is neg applied
Here is the working code with notes:
#!/usr/bin/python
import time
from time import sleep
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# Setup GPIO pins
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # set GPIO 17 as input
GPIO.setup(23, GPIO.OUT) # set GPIO 23 as output
GPIO.setup(24, GPIO.OUT) # set GPIO 25 as output
GPIO.output(23, 1) # set GPIO 23 as high - relay boards are neg applied to activate, this keeps the relay powered off without a signal
GPIO.output(24, 1) # set GPIO 25 as high - relay boards are neg applied to activate, this keeps the relay powered off without a signal
while True:
dt = list(time.localtime())
hour = dt[3]
minute = dt[4]
second = dt[5]
time.sleep(.01) #The first time.sleep command value impacts any similar statements made below it
print hour,minute,second;
PIR_Active = GPIO.input(17) #Define a condition which is met in the statements below
if not PIR_Active: #If the input is not active, reset both outputs to 'off'
GPIO.output(23, 1)
GPIO.output(24, 1)
elif (PIR_Active and (hour>=00 and hour<=6) and (minute >=00 and minute<=59) and (second >=0 and second<=59)):
GPIO.output(24, 0) #If all of the above is true, set this output to on
time.sleep(30) #Hold this output 'on' for 30 seconds
elif (PIR_Active and (hour>=7 and hour<=21) and (minute>=0 and minute<=59) and (second>=0 and second<=59)):
GPIO.output(23, 0) #If all of the above is true, set this output to on
time.sleep(30) #Hold this output 'on' for 30 seconds
elif (PIR_Active and (hour>=22 and hour<=23) and (minute >=00 and minute<=59) and (second >=0 and second<=59)):
GPIO.output(24, 0) #If all of the above is true, set this output to on
time.sleep(30) #Hold this output 'on' for 30 seconds
else: #Cleanly exit out of the if/elif statements with an else that:
GPIO.output(23, 1) #Resets this output to 'off'
GPIO.output(24, 1) #Resets this output to 'off'
GPIO.cleanup()
来源:https://stackoverflow.com/questions/64480895/python-rpi-gpio-output-control-based-on-gpio-input-and-time-of-day