Python rpi GPIO output control based on GPIO input and time of day

拈花ヽ惹草 提交于 2021-02-10 06:45:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!