Dusk-til-dawn switches and timer switches are both handy ways to automate your lights. Wouldn't it be great if you could combine the two, or even hook them up to the internet for a truly smart lighting system?

A Raspberry Pi, a relay, a light sensor, and a dash of code are all you need to achieve this automatic lighting nirvana on a shoestring.

What You'll Need

Components for your light-sensing smart switch are easy to source. You'll need:

How a Light-Sensing Smart Switch Works

By using a relay in the same way as our automatic garage door opener project, you can program a Raspberry Pi to switch a lighting circuit on and off at fixed times. Adding a luminosity sensor to the mix means the Pi can detect the ambient light level, and choose to turn the lights on only when they're really needed.

Because a Pi is a tiny computer that can be connected to a network, you can set it up to be controlled over the internet, too. Your smart lights will have three inputs to determine when they come on:

  1. A programmed schedule.
  2. The ambient light level.
  3. An override signal sent over the network.

Step 1: Connect the Raspberry Pi to the Relay

If you're new to using the GPIO, start by reading Everything You Need to Know About Raspberry Pi GPIO Pins.

First, check to see if your relay board has a jumper connecting the VCC and JD-VCC pins together. If it has, remove it.

JD-VCC to VCC relay board jumper

With everything powered down, connect the relay board to your Pi as follows:

  • Pi Pin 2 (5v) to the JD-VCC on the relay board.
  • Pi Pin 6 (GND) to GND on the relay board.
  • Pi Pin 15 (GPIO 22) to IN1 on the relay board
  • Pi Pin 17 (3.3v) to VCC on the relay board.
Raspberry Pi Zero W connected to a relay board

Step 2: Connect the Luminosity Sensor

The TSL2561 is a light sensor that can detect infrared, full spectrum, and human-visible light. It can send a very precise digital reading to the Raspberry Pi. The sensor reports the light level on a scale of 0.1 (no light) to 40,000 (bright sun).

The TSL2561 board talks to the Raspberry Pi using the i2c protocol. I2C only needs two connections, one for a clock to keep the two devices in sync, and one for the data being transferred. Of course, the lux sensor also needs some power, so there are four connections to make altogether:

  • Connect Pi Pin 1 (3.3v) to Vin (or VCC) on the lux sensor
  • Connect Pi Pin 3 (SDA) to SDA on the lux sensor
  • Connect Pi Pin 5 (SCL) to SCL on the lux sensor
  • Connect Pi Pin 9 (GND) to GND on the lux sensor
Raspberry Pi Zero W connected to TSL2561 lux sensor

Step 3: Configure and Install Dependencies

Before going any further, you'll need to check that I2C is enabled on your Raspberry Pi (it's disabled by default). Type the following into the terminal:

        sudo raspi-config
    

Select Interfacing Options > P5 I2C, then choose Yes.

Interfacing options in raspi-config utility

Hit Enter then select Finish to exit the config screen. Reboot your Pi for the change to take effect:

        sudo reboot
    

Some dependencies are necessary for the Pi to be able to communicate with the sensor board. Type the following commands:

        sudo apt-get update
sudo apt-get install -y python-smbus
sudo apt-get install -y i2c-tools

You can check everything is working by typing:

        sudo i2cdetect -y 1
    

If your dependencies are installed and your lux sensor is connected correctly, you'll see a response like this:

IC-Detect utility reporting lux sensor address

Here the utility is reporting that it has found an I2C device (the lux sensor) at I2C address 39.

You're not quite done with the dependencies yet. You're going to need a few libraries, too. First, make a folder to keep everything related to this project in:

        mkdir ~/lighting
cd ~/lighting

Next, download bottle, a lightweight framework that will create a simple web server on your Pi. You'll use it for controlling your lights from the web.

        wget https://bottlepy.org/bottle.py
    

The other libraries you'll need are on Github, so if your Raspberry Pi doesn't already have Git installed, add it now:

        sudo apt-get install git
    

Now clone two libraries, like this:

        git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
git clone https://github.com/adafruit/Adafruit_Python_PureIO.git

And lastly, create a test script by creating a new file:

        nano test.py
    

Paste in this code (courtesy of Adafruit):

        #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
from tsl2561 import TSL2561
if __name__ == "__main__":
   tsl = TSL2561(debug=True)
   print(tsl.lux())

Press Ctrl + X to save, following the onscreen instructions to exit.

When you're done, run the test script:

        python test.py
    

If everything is installed and working, you'll get back a number. That number is a lux reading from the sensor. Try blocking the sensor, or moving it so it gets more or less light. Then run the test script again and see how the number changes.

Step 4: Create the Automation Scripts

The Raspberry Pi will switch the lights on when it gets dark, but also switch them off at certain times. For example, you might want your lights to come on when it gets dark in the evening, then go off around midnight to save electricity. They could come on again early in the morning, then turn themselves off when it gets light.

To manage a schedule with multiple timing zones like this, there are two different scripts. One (onzone.py) will run every minute during the times you want your lights to be on if it is dark. The other (offzone.py) will run every minute during times you want the lights to be off regardless of the light level.

Smart lighting script schedule

The scripts will be scheduled to run using cron jobs. By choosing which hours of the day and night each script gets run, it will be easy to set the hours that your lights can come on automatically. You can set up as many on and off periods as you want.

As well as scripts for automatically controlling the lights, there is a third script to manage override situations. This will let you switch the lights on remotely regardless of the ambient light level.

Script 1: The ON Zone

This Python script will be run every minute of the day that you want the lights to come on if it is dark. Download the script by copying and pasting this command into the terminal:

        wget https://gist.githubusercontent.com/hamishdownell/ea151d2ff7c888ac09f8a850afaab4ee/raw/10b0e9d8ec42f8577750941da46a93d16b597c05/onzone.py
    

Every time onzone.py is run, it will get a lux value from the sensor to see if it is dark. If it is, it will then check to see if the lights are on or off. If they are off, it will switch them on. If it isn't dark, the script will see if the lights are on. If they are, it will switch them off unless they have been overridden.

The script uses a variable called lowlux to decide at which point it is dark enough to switch the lights on. You can change it to something suitable for your own installation by altering the value in this line near the top of onzone.py:

        lowlux = 50
    

Script 2: The OFF Zone

This script will be run every minute of the day that you want the lights to stay off, unless they have been overridden. Download the script:

        wget https://gist.githubusercontent.com/hamishdownell/fb8970909145bbfefbbef8dba5f5a00f/raw/eae5a6057a51ca4727907c7d061f0a48b07da944/offzone.py
    

This script doesn't care about how light or dark it is. Its job is simply to switch the lights off if they are on (unless they have been overridden).

Script 3: The Override Server

This script creates a simple web service that can accept commands to do the following actions:

  1. Switch the lights on for a number of minutes regardless of the ambient light level.
  2. Switch the lights off.
  3. Find out whether the lights are currently on or off.
  4. Find out for how much longer the lights are due to stay on when they have been overridden.

Download the script:

        wget https://gist.githubusercontent.com/hamishdownell/2303bfd9fb30d42e79923bdb7e69ed4e/raw/7dcb456b81b8ae58ae48efa225adb41ba7d7f69c/lightserver.py
    

Before moving on to the next step, run the offzone.py script like this:

        python offzone.py
    

This will create the control files that the scripts use to keep track of everything.

Step 5: Schedule the Scripts

Your Raspberry Pi can run the automation scripts with cron. Set up the schedule like this:

        sudo crontab -e
    

Paste these two lines into the text editor:

        * 7,8,9,17,18,19,20,21,22,23 * * * python /home/pi/lighting/onzone.py > NULL
* 0,1,2,3,4,5,6,10,11,12,13,14,15,16 * * * python /home/pi/lighting/offzone.py > NULL

Note: If the username you logged into your Raspberry Pi with was not the default pi, change the path accordingly.

List all the hours where you want the lights to come on when it's dark in the first line. All the hours where you want the lights off go in the second line.

Now set the override script to run automatically when the Pi starts up:

        sudo nano /etc/rc.local
    

Paste this line at the bottom of the file, then save and exit:

        nohup python /home/pi/lighting/lightserver.py &
    

Finally, reboot the Raspberry Pi so you can check that the server script is loading as it should

        sudo reboot
    

Step 6: Test the Relay

Before connecting up your lights, test that everything is working by using the override function. Type the following into a web browser on the same network as your Pi, replacing the IP address with the address of your own Raspberry Pi:

        11.22.33.44:1234/overrideon/3
    

If all is well, you will hear the relay click and the browser will respond that the lights have been switched on for three minutes.

While the relay is closed, you can test the other override functions. This will tell you for how many more minutes the lights will stay on due to the override:

        11.22.33.44:1234/getoverrideremaining
    

This should tell you that the lights are on:

        11.22.33.44:1234/lightstatus
    

Finally, you can turn them off again with:

        11.22.33.44:1234/overrideoff
    

The relay will click as it opens.

Step 7: Connect Your Lights

Switch off and unplug your Raspberry Pi before connecting up your lights to the relay. Use the normally open (NO) connectors on the relay board in place of a regular switch, like this:

Inserting the relay into the lighting circuit

Finally, you can install your lux sensor in a place where it will capture the ambient light level. Note that the TSL2561 will report as being saturated if it encounters direct bright sunlight, so it's best to keep it in the shade if possible.

More Raspberry Pi Projects for You to Try

Remotely overriding your new smart lighting setup by typing commands into a web browser is pretty cumbersome. A better way is to hook up something like an Amazon Echo to make things easier. Combining the Alexa service and Webhooks service on IFTTT is a simple way to add voice control.

See our guide to using IFTTT to help you get started.

IFTTT Applet to connect smart lights to Alexa

Another option is to use Siri Shortcuts. A single shortcut with menus can query the status of the lights and use the override functions to turn them on and off.

If you enjoyed this project, be sure to check out these weird Raspberry Pi projects for more ideas.