header image

Raspberry Pi Zero Plant Timer

My wife starts garden plants in the bath tub under a grow light. I was thinking that it would be nice if the grow light was synchronized to the local sunrise and sunset so that the plant could get "used to" the day length for this time of year. I also was thinking it would be nice to have a timer to turn on and off the light so that we don't have to remember to do it. And, it would be kinda cool to watch a time lapse of the seeds growing.

So I figured, why not throw money at a problem that might be reasonably solved by a $5 plug timer and overengineer it?


I bought a raspberry pi zero with a case and the camera module. I had a power switch tail sitting around collecting dust. That's all the hardware needed.


My setup is to wire a GPIO pin + a ground pin down to the power switch tail so that I can control it from software. You don't need to hook anything to the ground pin on the power switch tail, just use your GPIO signal pin and a ground from the pi.

I got a nice little case with a hole in the middle of it that fits the camera lens that came with the pi. Perfect for sitting up on the lamp and looking down on the plants. You can control the camera (i.e. take photos) programmatically with the raspistill command.

I do the toggling of the light and the photo taking from a cronjob but stay tuned because it's a little tricky... because it rewrites itself daily to update for the sunrise and sunset times.


I chose GP21 (physical pin 40) and brought the ground from the GND on pin 3. Solder carefully because those pins are wired directly into the processor of the pi. Here's a picture to help:

Hook them into the power switch tail and test it out. I ended up running about fout feet of wire down to the tail from the pi.

I had some trouble here... I am lazy so I was looking for a commandline way to flip the GPIO pins rather than writing (simple) python. I found something called gpio. Wow, this must work. Well, it turns out it doesn't. I don't know what gives but I ended up having to use the pigs tool instead. Phew, I thought I screwed it up with my soldering!

Then, as mentioned, use the raspistill command with some scp foo to take and copy the photo out to somewhere more permanent.

Sunrise and Sunset

To figure out sunrise and sunset I had to use python. It turns out there is already a library called Astral that knows how to compute sunrise and sunset for different locations at different times. I hacked this up:


import datetime
from astral import Astral

a = Astral()
a.solar_depression = "civil"
city = a["Seattle"]
sun = city.sun(date=datetime.datetime.now(), local=True)

with open("/home/pi/cron/prototype_crontab") as f:
  for line in f.readlines():
    line = line.rstrip("\n")
    for tag in [ "dawn", "sunrise", "noon", "sunset", "dusk" ]:
      line = line.replace("@%s" % (tag), "%d %d * * *" % (sun[tag].minute, sun[tag].hour))
      print line

As you can see it's not just getting the time of sunrise... it's also reading a file called prototype_crontab and replacing all of the @sunrise and @sunset (and @noon, @dawn, @dusk) with the actual hour/minute of those events. Noon is "solar noon", i.e. when the sun is as high as it is going to get. Not actually 12:00 noon (on most days).

This script runs once a day, a little after midnight, via a crontab entry:

  0 15 * * *        sunrise_sunset_cron.py | crontab -

This basically runs the script and takes the output and makes that the new cronjob. Of course the first line in that prototype_cronjob source file has to (always) be the lin that runs that command, or it will stop working.

Here's my prototype_cronjob file, to show you what I mean:

# Note: this crontab is updates itself via the first line below, like this:
#   0 0 * * *     sunrise_sunset_crontab.py | crontab -
# That script processes ~/cron/prototype_crontab and replaces stuff like [at]sunrise,
# [at]sunset, [at]noon, etc... to the actual time of sunrise, sunset and solar noon
# in Seattle, WA.  You can also use [at]dusk and [at]dawn.
# Instead, go edit that prototype_crontab file directly and run this to update:
#   /home/pi/cron/sunrise_sunset_crontab.py | crontab -
# (or, alternately, just wait a day and it will update itself).
# For more information see the manual pages of crontab(5) and cron(8) and the source
# code of that sunrise_sunset_crontab.py script itself.

# m h dom mon dow   command
# ------------------------------------------------------------------------------------
0 15 * * *          /home/pi/cron/sunrise_sunset_crontab.py | crontab -
@sunrise            /usr/bin/pigs w 21 1
@sunset             /usr/bin/pigs w 21 0
@noon               /home/pi/cron/take_picture.sh

Here's what the whole setup looks like:

And there you have it... a very overpried but somewhat cool timer that understands sunrise and sunset and takes time lapse photo sequeunces. Have fun.
index.html was last updated 21 March 2017 and is Copyright (C) 2002-2015 by Scott Gasch (scott.gasch@gmail.com).