sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

100 % processing power

Mon Apr 09, 2018 2:54 pm

I am trying to manage a hydroponic garden autonomously.
I have two scripts so far - one to turn the light on and off according to the time of day, and one to take a picture and tweet the environmental readings.
I am using an IKEA Vaxer hydroponic setup with a Pi Zero W, PiCamera, Envirophat and Featherwing relay.

Image
Image
Image

I am using cron to manage the scripts, basically so that the pi is headerless (I think is the correct term when you don't have a keyboard mouse or screen and it starts the scripts at boot up?).
The crontab looks like this:

@ reboot python /home/pi/zwgarden/lxonoff.py &
@ reboot python /home/pi/zwgarden/daycamtwit.py &

These two scripts are consuming all of the processing power (100%)
The goal is for it to only take pictures when the light is on, 1 min past the hour every hour, and one picture at the end of the day to show the light has turned off. I am hoping over time this will help me to create a neat timelapse of the garden and I don't need 12 black pictures over night! I have leaned heavily on the script that was written for the light turning on and off to do this with the camera and it is most likely not the best way. It works (or it seems to, will find out later tonight!) but it burns processing power constantly.

Is this something I should be concerned about? Is there a better way (undoubtably - I am a complete noob floundering around this forum).

I had tried to fit it all into one script but it was proving too difficult for me so I made two seperate ones. I plan to make more scripts - such as a water level monitoring script, and a log of all the environmental sensors on the envirophat to track changes etc so i am concerned to have hit the processing ceiling so soon.

Both scripts shown below, first the lamp on/off script which is working well thanks to previous help:

Code: Select all

# -*- coding:utf-8 -*-
#lxonoff
# Latching mini Featherwing Relay turns on/off light
import time as t
from time import sleep
import RPi.GPIO as GPIO

LXON = 8 * 60 + 0 # turn light on at 08:00
LXOFF = 20 * 60 + 0 # turn light off at 20:00

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT) #RESET
GPIO.setup(27, GPIO.OUT) #OPEN on
GPIO.setup(22, GPIO.OUT) #CLOSE off
GPIO.output(17, 1)
sleep(0.1)
GPIO.output(17, 0)

switched_on = False # hold current state

try:
    while True:
        stm = t.localtime()
        now = stm.tm_hour * 60 + stm.tm_min
        if (now - LXON) % 1440 < (LXOFF - LXON) % 1440:
            should_be_on = True
        else:
            should_be_on = False
        if should_be_on and not switched_on:
            # GPIO pin set to on
            switched_on = True
            GPIO.output(27, 0)
            GPIO.output(22, 1)
            sleep(0.1)
            GPIO.output(22, 0)

        elif switched_on and not should_be_on:
            # GPIO off
            switched_on = False
            GPIO.output(27, 1)
            sleep(0.1)
            GPIO.output(27, 0)

except KeyboardInterrupt:
    GPIO.output(17, 1)
    sleep(0.1)
    GPIO.output(17, 0)
    GPIO.cleanup()


And the script I am having difficulty with, determining what the time of day is, whether the camera should take picture and send to twitter with envirophat data:

Code: Select all

# -*- coding:utf-8 -*-
#daycamtwit
#takes pictures 1 minute past the hour every hour the light should be on,
#and one after light should be off.
import time as t
import datetime
from time import sleep
from envirophat import light, weather, leds
from picamera import PiCamera
from twython import Twython

CAMON = 8 * 60 + 0 # turn light on at 08:00
CAMOFF = 21 * 60 + 0 # turn light off at 21:00

CONSUMER_KEY = 'xxx'
CONSUMER_SECRET = 'xxx'
ACCESS_KEY = 'xxx'
ACCESS_SECRET = 'xxx'
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_KEY, ACCESS_SECRET)

switched_on = False # hold current state

try:
    while True:
        stm = t.localtime()
        now = stm.tm_hour * 60 + stm.tm_min
#        pictwit = datetime.datetime.now().strftime("%H:10") #Tweet time
#        timenow = datetime.datetime.now().strftime("%H:%M")

        if (now - CAMON) % 1440 < (CAMOFF - CAMON) % 1440:
            should_be_on = True
            pictwitt = datetime.datetime.now().strftime("%H:01") #Tweet time
            timenoww = datetime.datetime.now().strftime("%H:%M")
            if timenoww == pictwitt:
                lux = light.light()
                leds.on()
                rgb = str(light.rgb())[1:-1].replace(' ', '')
                leds.off()
                temp = weather.temperature()
                press = weather.pressure()/100
                picfilename = (t.strftime("%y%b%d_%H:%M:%S"))
                pname = "/home/pi/zwgarden/pics/" + picfilename + ".jpg"
                camera = PiCamera()
                camera.sensor_mode=5 #twitter optimum resolution
                sleep(2)
                camera.capture(pname)
                camera.close()
                sleep(15)
                photo = open(pname, 'rb')
                estatus = '%.2f lm, %s RGB, %.2f degrees C, %.2f hPa\n' % (lux, rgb, temp, press)
                response = twitter.upload_media(media=photo)
                twitter.update_status(status='' + picfilename + ', ' + estatus + '', media_ids=[response['media_id']])
                sleep(3480)
                continue

        else:
            should_be_on = False
        if should_be_on and not switched_on:
            #cam enabled
            switched_on = True
            pictwit = datetime.datetime.now().strftime("%H:01") #Tweet time
            timenow = datetime.datetime.now().strftime("%H:%M")
            if timenow == pictwit:
                lux = light.light()
                leds.on()
                rgb = str(light.rgb())[1:-1].replace(' ', '')
                leds.off()
                temp = weather.temperature()
                press = weather.pressure()/100
                picfilename = (t.strftime("%y%b%d_%H:%M:%S"))
                pname = "/home/pi/zwgarden/pics/" + picfilename + ".jpg"
                camera = PiCamera()
                camera.sensor_mode=5 #twitter optimum resolution
                sleep(2)
                camera.capture(pname)
                camera.close()
                sleep(15)
                photo = open(pname, 'rb')
                estatus = '%.2f lm, %s RGB, %.2f degrees C, %.2f hPa\n' % (lux, rgb, temp, press)
                response = twitter.upload_media(media=photo)
                twitter.update_status(status='' + picfilename + ', ' + estatus + '', media_ids=[response['media_id']])
                sleep(3480)
                continue
            else:
                continue

        elif switched_on and not should_be_on:
            continue
            

except KeyboardInterrupt:
    sleep(1)
I appreciate your feedback!

Paul Hutch
Posts: 353
Joined: Fri Aug 25, 2017 2:58 pm
Location: Blackstone River Valley, MA, USA
Contact: Website

Re: 100 % processing power

Mon Apr 09, 2018 3:10 pm

You need a sleep in the "while True:" loops that will always execute on every pass through the loop to avoid 100% processor utilization. Your sleep statement are inside of conditional branches so will not always execute.

I generally put it as the last statement in the loop because it makes a good visual reference for the proper indentation level and end of the loop. Sleeping for even just 1 ms will significantly reduce utilization but a longer sleep will the lower the utilization more.

Idahowalker
Posts: 445
Joined: Wed Jan 03, 2018 5:43 pm

Re: 100 % processing power

Mon Apr 09, 2018 8:42 pm

Ideas, yes.

Interrupts instead of loops. As you have experienced loops waste clock cycles and processing power.

I use an external interrupt timer that, I have found, is very accurate.

Icstation Adjustable Timer Module Time Delay https://smile.amazon.com/gp/product/B01 ... UTF8&psc=1

I have one timer set that goes off once an hour to send me an email on the systems status.

My RPi is connected to an Arduino. The Arduino interrupts the RPi to let the Pi 'know' there is a data packet available. The RPi interrupts to Arduino from gathering data whiles the Pi is busy working on a data packet.

That timer can be set, with a solder iron to trigger once every 12 hours. Once the 12 hour timer is triggered, it can be re-triggered, and your system can be awake for another minute or so to process the picture taking.

Getting the light to turn on and off every 12 hours and not eating clock cycles would be what I work on first. The clock cycles eaten by the light on off will consume resources for the picture taking routine.
Without knowing why you are deleting my postings, I will not know how...

PingoBags
Posts: 47
Joined: Mon Nov 06, 2017 10:53 pm
Location: NS, Canada

Re: 100 % processing power

Tue Apr 10, 2018 1:05 pm

I use a timer for my light script instead of a while loop.
Instead of constantly checking in a while loop, I calculate the intervals for the timer so the code only runs twice daily.

This script could actually work for you. Just fill in the blanks where I've commented.
I've been using something similar for months now on my pi zero.
Not a single issue so far and 0% cpu usage.

Code: Select all

from datetime import timedelta,datetime
from threading import Timer

def RetIntervals(SetTime):
  LightsOn = False
  for x in range(len(SetTime)):#Convert time string to datetime
    Ctime = datetime.now().strftime('%Y-%m-%d ' + SetTime[x])
    SetTime[x] = datetime.strptime(Ctime, '%Y-%m-%d %H:%M')

  dtnow = datetime.now().replace(microsecond=0)

  if dtnow < SetTime[0]:#If current time is before lights on
    return ((SetTime[0] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights on
    
  if dtnow > SetTime[1]:#If current time is after lights off
    return (((SetTime[0] + timedelta(days=1)) - dtnow).seconds + 61,LightsOn)
    #One day is added to lights on, then current time subtracted
    
  if dtnow > SetTime[0] and dtnow < SetTime[1]:#If current time is in range of lights on/off
    LightsOn = True
    return ((SetTime[1] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights off
    
  return (0,LightsOn)

def RunPictures():
  #Take picture code goes here
  print("Picture Taken")
  Timer(3600,RunPictures).start()
  
def PicFirstRun():
  dtnow = datetime.now().replace(microsecond=0)
  dtnext = dtnow.replace(microsecond=0,second=0,minute=0) + timedelta(hours=1,minutes=1)
  Timer((dtnext - dtnow).seconds,RunPictures).start()
  
def RunLights(): 
  Intervals,LightsOn = RetIntervals(["8:00","20:00"]) 
  if LightsOn:
    print("Do something here to turn lights on")
  else:
    print("Do something here to turn lights off")
    #Also this can be where you take a picture to show the lights are off..
  if Intervals != 0:
    Timer(Intervals,RunLights).start()
  
PicFirstRun()#The interval first need calculating so the timer first finishes 1 minute past the hour.
#Then the timer is run every hour

RunLights()#Initially, RunLights is run manually to check if the lights should be on or off.
#Then the timer takes over with the calculated intervals. The function doesn't run in a
#continuous loop, it only runs twice daily.

sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

Re: 100 % processing power

Wed Apr 11, 2018 9:53 am

Cool, I like both of those timer ideas, a hardware and a software solution.

About the software solution, part of the complexity about having the light turn on and off is the initial state when it first turns on.
I don't want it to have to wait for a set time to take an action to start with, I want it to figure out where in time it is now and what is the appropriate action to take given the time.

Is this what your script does? Figures out where in time it is, what should be happening, and then sets a timer to the next event to occur and every event from then on?

I also like having two different scripts, essentially dedicated to two different functions - one which is critical (the light on/off) and the other non critical. If something happens to the non critical I don't want it to get in the way of the critical functions.
The plants must have consistent light on and off times. If something happens with the tweeting I don't want it to disturb the light routine.

PingoBags
Posts: 47
Joined: Mon Nov 06, 2017 10:53 pm
Location: NS, Canada

Re: 100 % processing power

Wed Apr 11, 2018 11:10 am

Is this what your script does? Figures out where in time it is, what should be happening, and then sets a timer to the next event to occur and every event from then on?
That's precisely what it does.
I also like having two different scripts, essentially dedicated to two different functions - one which is critical (the light on/off) and the other non critical. If something happens to the non critical I don't want it to get in the way of the critical functions.
The plants must have consistent light on and off times. If something happens with the tweeting I don't want it to disturb the light routine.
I'm the same way. I have plants growing too.
The two can be separate

Lights

Code: Select all

from datetime import timedelta,datetime
from threading import Timer

def RetIntervals(SetTime):
  LightsOn = False
  for x in range(len(SetTime)):
    Ctime = datetime.now().strftime('%Y-%m-%d ' + SetTime[x])
    SetTime[x] = datetime.strptime(Ctime, '%Y-%m-%d %H:%M')

  dtnow = datetime.now().replace(microsecond=0)

  if dtnow < SetTime[0]:
    return ((SetTime[0] - dtnow).seconds + 61,LightsOn)
    
  if dtnow > SetTime[1]:
    return (((SetTime[0] + timedelta(days=1)) - dtnow).seconds + 61,LightsOn)

  if dtnow > SetTime[0] and dtnow < SetTime[1]:
    LightsOn = True
    return ((SetTime[1] - dtnow).seconds + 61,LightsOn)
    
  return (0,LightsOn)
 
def RunLights(): 
  Intervals,LightsOn = RetIntervals(["8:00","20:00"]) 
  if LightsOn:
    #Lights on code goes here
    print("Do something here to turn lights on")
  else:
    #Lights off code goes here
    print("Do something here to turn lights off")
  if Intervals != 0:
    Timer(Intervals,RunLights).start()
 
RunLights()
and picture

Code: Select all

from datetime import timedelta,datetime
from threading import Timer

def RunPictures():
  #Take picture code goes here
  print("Picture Taken")
  Timer(3600,RunPictures).start()
  
def PicFirstRun():#This gets run initially, so the intervals until the next hour can be calculated.
  dtnow = datetime.now().replace(microsecond=0)
  dtnext = dtnow.replace(microsecond=0,second=0,minute=0) + timedelta(hours=1,minutes=1)
  Timer((dtnext - dtnow).seconds,RunPictures).start()
    
PicFirstRun()

sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

Re: 100 % processing power

Wed Apr 11, 2018 12:20 pm

I have taken your code and adjusted as such:

Code: Select all

from datetime import timedelta,datetime
from threading import Timer
from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT) #RESET
GPIO.setup(27, GPIO.OUT) #OPEN on
GPIO.setup(22, GPIO.OUT) #CLOSE off
GPIO.output(17, 1)
sleep(0.1)
GPIO.output(17, 0)

def LXON():
  GPIO.output(27, 0)
  GPIO.output(22, 1)
  sleep(0.1)
  GPIO.output(22, 0)
  sleep(1)
  GPIO.output(17, 1)
  sleep(0.1)
  GPIO.output(17, 0)
  GPIO.cleanup()

def LXOFF():
  GPIO.output(22, 0)
  GPIO.output(27, 1)
  sleep(0.1)
  GPIO.output(27, 0)
  sleep(1)
  GPIO.output(17, 1)
  sleep(0.1)
  GPIO.output(17, 0)
  GPIO.cleanup()

def RetIntervals(SetTime):
  LightsOn = False
  for x in range(len(SetTime)):#Convert time string to datetime
    Ctime = datetime.now().strftime('%Y-%m-%d ' + SetTime[x])
    SetTime[x] = datetime.strptime(Ctime, '%Y-%m-%d %H:%M')

  dtnow = datetime.now().replace(microsecond=0)

  if dtnow < SetTime[0]:#If current time is before lights on
    return ((SetTime[0] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights on
    
  if dtnow > SetTime[1]:#If current time is after lights off
    return (((SetTime[0] + timedelta(days=1)) - dtnow).seconds + 61,LightsOn)
    #One day is added to lights on, then current time subtracted
    
  if dtnow > SetTime[0] and dtnow < SetTime[1]:#If current time is in range of lights on/off
    LightsOn = True
    return ((SetTime[1] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights off
    
  return (0,LightsOn)
  
def RunLights(): 
  Intervals,LightsOn = RetIntervals(["8:00","20:00"]) 
  if LightsOn:
    LXON()
    
  else:
    LXOFF()
    #Also this can be where you take a picture to show the lights are off..
  if Intervals != 0:
    Timer(Intervals,RunLights).start()

RunLights()#Initially, RunLights is run manually to check if the lights should be on or off.
#Then the timer takes over with the calculated intervals. The function doesn't run in a
#continuous loop, it only runs twice daily.
I now have next to no CPU usage on the Pi! Thank you!

I have used crontab to run my take picture and tweet script:

1 8-20 * * * python filename.py &

Keeps it easy.

Running in this fashion has reduced the load on the CPU over 90%! Thank you so much!

User avatar
Gavinmc42
Posts: 3136
Joined: Wed Aug 28, 2013 3:31 am

Re: 100 % processing power

Wed Apr 11, 2018 12:29 pm

Yep, never run python programs all the time.
Basic beginner mistake :oops: ,
I also found there seems to be memory leaks, memory seems to vanish.
Keep typing "free" and watch it get gobbled by Python ;)

I use cron and watch on my 24/7 stuff, 1-2% usage on a B+ ;)
I also use PiCore, much smaller OS than Raspbian.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

PingoBags
Posts: 47
Joined: Mon Nov 06, 2017 10:53 pm
Location: NS, Canada

Re: 100 % processing power

Wed Apr 11, 2018 2:35 pm

You don't need gpio clean every time you turn the lights on or off, all that is doing it resetting the pins back to input.
I don't even think your new script would run correctly in it current state. If you reset those pins, it'l probably stop working.

I don't completely understand the on off functions. You're changing the state of a pin, only to change it right back in the same function?
I'm betting you can get the cpu down next to nothing with some changes to your script.

I made some changes for you to try. I still don't understand the purpose of the reset pin and why it gets toggled on then off every time the lights are switched. So I left that the same.

Code: Select all

from datetime import timedelta,datetime
from threading import Timer
from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT,initial=1) #RESET
GPIO.setup(27, GPIO.OUT) #OPEN on
GPIO.setup(22, GPIO.OUT) #CLOSE off
sleep(0.1)
GPIO.output(17, 0)
  
def Toggle(lstate):
  GPIO.output(22, lstate)
  GPIO.output(27, not lstate)
  GPIO.output(17, lstate)
  sleep(0.1)
  GPIO.output(17, not lstate)
  
def RetIntervals(SetTime):
  LightsOn = False
  for x in range(len(SetTime)):
    Ctime = datetime.now().strftime('%Y-%m-%d ' + SetTime[x])
    SetTime[x] = datetime.strptime(Ctime, '%Y-%m-%d %H:%M')

  dtnow = datetime.now().replace(microsecond=0)

  if dtnow < SetTime[0]:
    return ((SetTime[0] - dtnow).seconds + 61,LightsOn)
    
  if dtnow > SetTime[1]:
    return (((SetTime[0] + timedelta(days=1)) - dtnow).seconds + 61,LightsOn)
    
  if dtnow > SetTime[0] and dtnow < SetTime[1]:
    LightsOn = True
    return ((SetTime[1] - dtnow).seconds + 61,LightsOn)
    
  return (0,LightsOn)
  
def RunLights(): 
  Intervals,LightsOn = RetIntervals(["8:00","20:00"]) 
  
  Toggle(LightsOn)
  
  if Intervals != 0:
    Timer(Intervals,RunLights).start()

RunLights()

@Gavinmc42
You say running 24/7 is a basic beginner mistake, care to explain why it's a mistake?

I have two pi zero system up and running.
One has been running 24/7 for over 6 months and a small part of it monitors water temp.
The temp is read every 60sec. How would I monitor if the script wasn't running 24/7.
The overall system uses 0-1% load at any given time.

My other system is new but it's a ups. Mains power needs monitoring for it to be effective.
Since power outages are unpredictable, this needs monitoring 24/7.

sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

Re: 100 % processing power

Wed Apr 11, 2018 6:11 pm

Yes good point about the GPIO clean, it was a quick cut and paste to get it happening.

Script did not turn off the light this evening, which is disappointing.

Will go back through now and see if I can find where I have gone wrong.

User avatar
bensimmo
Posts: 4059
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: 100 % processing power

Wed Apr 11, 2018 6:30 pm

That EnviroPhat has a light sensor, among other things. It should be quite easy to work out a check if the lights are on or not, even in a lit room.
It'll give you a light level you can then use to send an emergency tweet that there is a fault or retry light switch on.

Also I see you are switching on the Hat LED (see code snippet), but I'm not sure why, you don't need it to get a reading and it may alter your values ?
First light.lux() gives you the LUX of the .light intensity, .rgb gives your R,G,B values scaled to the .light lux value. Turning the LED's on would alter that scaling if it reflects off anything, the LED is designed to be on directly in front of an item to illuminate it and so you can see the colour.
Not majorly important, but just thought I would mention it.

Code: Select all

                lux = light.light()
                leds.on()
                rgb = str(light.rgb())[1:-1].replace(' ', '')
                leds.off()

sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

Re: 100 % processing power

Thu Apr 12, 2018 7:55 am

Ahh, in the Envirophat tutorial it says:

"To get a more accurate colour reading, we've added two white LEDs either side of the light/colour sensor that should reflect more light back to the sensor."

Which I took to mean its best to use them so you get a better reading.
But i take your point that it's for reflecting an object colour back into it and I don't need that as it is pointing straight at the grow LED's!

I will try to disable the lines for the LED's and see how the readings change, although I expect not so much given the size and intensity of the grow LED's. I actually really like it as I get to see them flash so I know it's working, a visual confirmation.

It is the red LED in the PiCamera which annoys me more, it gives a red tinge to the photo which makes it look a bit sickly.

@Pingobags the GPIO pins are connected to a latching relay with 3 pins, reset, normally open, and normally closed.

It's a two way switch effectively - it could run two different circuits just not at the same time, and because it is latching you only need to pulse the corresponding pin so it knows which side for the relay to go to - open or closed.

It does not need to be a constant signal, like unlatching relays, which as soon as they lose signal, will return to their initial state. In this case I want the relay to stay as it was if the code crashes or the pi gets reboot or looses power.

The first command is a check to send the off command to the opposite pin I want to pulse, it's not healthy to send on to both sides of the relay, and is just a little safety check.
The second sends an on signal to the side I want, waits 0.1 seconds, then sends the off command, as it does not need to send that message constantly for it to stay on.

User avatar
bensimmo
Posts: 4059
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: 100 % processing power

Thu Apr 12, 2018 8:17 am

The LED.can be turned off.
The zerocam uses the V1 camera setup.
You add at camera setup.

# Turn the camera's LED off
camera.led = False

Though on the Pi3 things changed and I don't think it worked and I cannot remember on the Zero's.

You should be able to use
edit
/boot/config.txt
and add
disable_camera_led = 1

Edit / to add and official link https://www.raspberrypi.org/documentati ... /camera.md /edit

Next boot it should be disabled.
Of course, that is if things haven't changed since I last did it.



Unless you mean the Pi Zero itself, you can edit
/boot/config.txt
And add
dtparam=act_led_trigger=none
dtparam=act_led_activelow=on
Reboot

PingoBags
Posts: 47
Joined: Mon Nov 06, 2017 10:53 pm
Location: NS, Canada

Re: 100 % processing power

Thu Apr 12, 2018 10:37 am

sandysound wrote:
Wed Apr 11, 2018 6:11 pm
Yes good point about the GPIO clean, it was a quick cut and paste to get it happening.

Script did not turn off the light this evening, which is disappointing.

Will go back through now and see if I can find where I have gone wrong.
When you first ran the script and turned the lights on, it cleaned the pins.
That's why it didn't turn off, the pins were no longer set.
I'm not sure how your old script ran if you were cleaning the pins.
If your script still isn't working correctly after removing gpio clean, you need to start looking at your
lxon and lxoff functions. To me, they don't look correct.

Pin 17 is reset. What does this do?
In your LX on and off, you are setting the state high then low, is that what you intended to do?

You also seem to be doing the same with pin 27 and 22. Setting the pin then setting it back would just undo everything.
Shouldn't you just set the pin value and leave it?

Answer this.
What value should pin 17, 27 and 22 be when the lights are on?
What value should they be when off.

User avatar
bensimmo
Posts: 4059
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: 100 % processing power

Thu Apr 12, 2018 10:53 am

Just to add links to parts.
I think it is Adafruit Latching Mini Relay FeatherWing
https://www.adafruit.com/product/2923

so it is pulsed, i.e. take it high for 10ms and then you take it low again, it still stays latched.
The idea is you don't then have a constant power drain from the switch.

sandysound
Posts: 58
Joined: Thu Sep 14, 2017 6:05 pm

Re: 100 % processing power

Thu Apr 12, 2018 9:44 pm

Reset shorts to ground, essentially restarting the board. It is not connected to the relay. However after removing the resets from the script it is now functioning as it should.

Each side of the relay is activated by a 0.01s pulse to the corresponding pin. It does not need to be 1 constantly, hence the return to 0 after each command.

Code: Select all

from datetime import timedelta,datetime
from threading import Timer
from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT) #RESET
GPIO.setup(27, GPIO.OUT) #OPEN on
GPIO.setup(22, GPIO.OUT) #CLOSE off
GPIO.output(17, 1)
sleep(0.1)
GPIO.output(17, 0)

def LXON():
    GPIO.output(27, 0)
    GPIO.output(22, 1)
    sleep(0.1)
    GPIO.output(22, 0)

def LXOFF():
  GPIO.output(22, 0)
  GPIO.output(27, 1)
  sleep(0.1)
  GPIO.output(27, 0)

def RetIntervals(SetTime):
  LightsOn = False
  for x in range(len(SetTime)):#Convert time string to datetime
    Ctime = datetime.now().strftime('%Y-%m-%d ' + SetTime[x])
    SetTime[x] = datetime.strptime(Ctime, '%Y-%m-%d %H:%M')

  dtnow = datetime.now().replace(microsecond=0)

  if dtnow < SetTime[0]:#If current time is before lights on
    return ((SetTime[0] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights on
    
  if dtnow > SetTime[1]:#If current time is after lights off
    return (((SetTime[0] + timedelta(days=1)) - dtnow).seconds + 61,LightsOn)
    #One day is added to lights on, then current time subtracted
    
  if dtnow > SetTime[0] and dtnow < SetTime[1]:#If current time is in range of lights on/off
    LightsOn = True
    return ((SetTime[1] - dtnow).seconds + 61,LightsOn)
    #Current time subtracted from lights off
    
  return (0,LightsOn)
  
def RunLights(): 
  Intervals,LightsOn = RetIntervals(["8:00","20:00"]) 
  if LightsOn:
    LXON()
    
  else:
    LXOFF()
    #Also this can be where you take a picture to show the lights are off..
  if Intervals != 0:
    Timer(Intervals,RunLights).start()

RunLights()#Initially, RunLights is run manually to check if the lights should be on or off.
#Then the timer takes over with the calculated intervals. The function doesn't run in a
#continuous loop, it only runs twice daily.

Return to “Python”