Part 3/3: Reading analog input using RPi

Continuing from the previous example, we would like our LED to turn on automatically, based on the light level of the environment.

Photoresistor

First we need to read the value of the photocell that measures the value of light. Photocells (aka. photoresistor) acts as a dynamically-adapting resistor according to the light levels. In dark areas, the resistance is high and in bright areas the resistance is low.

As Raspberry Pi does not have an analog input, we can make a trick to read a value from an analog sensor (resistor-based sensor). We just use a small capacitor and measure time that is needed to fill the capacitor to the full level.

On Raspberry Pi we use 3.3V pin as power supply, GND as ground and pin 18 as an input pin that will be used to measure time to fill the capacitor. In the circuit we measure voltage levels using pin 18 between photoresistor and capacitor.

To get the light level, we need to:

  1. Set pin 18 as out and to LOW voltage.
  2. Set pin 18 as input to be able to read input voltage. Now we can just read if voltage is LOW or HIGH.
  3. Measure, how much time is needed until read voltage on pin 18 is HIGH.

Normally you can use a 1μF but we had just a capacitor of 100μF (if it is designed to higher voltage, it is okay). The difference is only you will need more time to fill the capacitor in darker conditions. In our case, we need about 800000ms to detect dark light and about 30000ms to detect twilight.

Automatic light switching

Above we got the information whether the light conditions are daylight, twilight or darkness. Now we set a LED that will be turned off in daylight, burn lightly in twilight and be very bright in darkness.

For this, we use two pins to turn on a LED and for each pin, we use different resistor to set the brightness of a LED. For darkness we use a 220Ohm resistor and for twilight we use 1120Ohm (2x560Ohm) resistor.

The script to control all of the above looks like:

#!/usr/bin/env python
import RPi.GPIO as GPIO, time, os
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
 
#Variables setup
TWILIGHT_THRESHOLD = 30000
DARK_THRESHOLD = 800000
LIGHT_STATUS_PIN = 18
TWILIGHT_LIGHT_PIN = 22
DARKNESS_LIGHT_PIN = 23
 
class Light(object):
        DAYLIGHT = "Daylight"
        TWILIGHT = "Twilight"
        DARKNESS = "Darkness"
 
def LightInfo():
        GPIO.setup(LIGHT_STATUS_PIN, GPIO.OUT)
        GPIO.output(LIGHT_STATUS_PIN, GPIO.LOW)
        time.sleep(0.1)
        GPIO.setup(LIGHT_STATUS_PIN, GPIO.IN)
 
        # This takes about 1 millisecond per loop cycle
        repeats_to_full_capacitor = 0
        while (GPIO.input(LIGHT_STATUS_PIN) == GPIO.LOW):
                repeats_to_full_capacitor += 1
 
        if (repeats_to_full_capacitor < TWILIGHT_THRESHOLD):
                return Light.DAYLIGHT
        elif (repeats_to_full_capacitor < DARK_THRESHOLD):
                return Light.TWILIGHT
        else:
                return Light.DARKNESS
 
def TurnLEDOnOff(status):
        #Turn all off
        GPIO.setup(TWILIGHT_LIGHT_PIN, GPIO.OUT)
        GPIO.setup(DARKNESS_LIGHT_PIN, GPIO.OUT)
        GPIO.output(TWILIGHT_LIGHT_PIN, GPIO.LOW)
        GPIO.output(DARKNESS_LIGHT_PIN, GPIO.LOW)
        time.sleep(0.1)
        #Turn appropriate pin on
        if (status == Light.TWILIGHT):
                GPIO.setup(DARKNESS_LIGHT_PIN, GPIO.IN)
                GPIO.output(TWILIGHT_LIGHT_PIN, GPIO.HIGH)
        elif (status == Light.DARKNESS):
                GPIO.setup(TWILIGHT_LIGHT_PIN, GPIO.IN)
                GPIO.output(DARKNESS_LIGHT_PIN, GPIO.HIGH)
 
#Main program
status = Light.DAYLIGHT
while True:
        newStatus = LightInfo()
        print newStatus
        if (newStatus != status):
                TurnLEDOnOff(newStatus)
                status = newStatus

When we run the script as “sudo ./LightSwitch.py” in daylight conditions, the LED is off:

IMG_0164

In twilight, the LED is not that bright:

IMG_0165

Lastly in the darkness, the LED becomes very bright:

IMG_0166