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.
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:
- Set pin 18 as out and to LOW voltage.
- Set pin 18 as input to be able to read input voltage. Now we can just read if voltage is LOW or HIGH.
- 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:
In twilight, the LED is not that bright:
Lastly in the darkness, the LED becomes very bright: