Ever since the Raspberry Pi was released I've always wanted to get one, but never had a reason to. Then I saw a YouTube video where Andrew Ong had put together a stair lighting project using an Arduino. And I thought, "That's it, I have to be able to do that with a Raspberry Pi!". So I started thinking about it and doing a little bit of research until I was sure that it could be done.
So I knew I wanted a Raspberry Pi, but after searching, I discovered the Raspberry Pi zero at only £4, so that seemed like an ever better choice and also it had lower power requirements which would be ideal. The down side being the GPIO pins are only digital and I wanted the LED lights to fade on and off, so I searched around to see if I could solve that problem. Unfortunately I never did, the solution I came up with was to use a capacitor to hold some charge which would then discharge to the LEDs once the power was cut.
My initial experiments with the light sensor and LED proved promising but once I tried hooking up the Pi in there as well it didn't work quite so well. There wasn't enough power getting through the transistors to power the Pi so it would shutdown a few seconds after starting up.
The question as to how to the get system to only be enabled when it got dark was quickly solved by following this tutorial. I'd originally wanted the light sensor to turn the Pi on when it was dark enough and then off when it got light, who wants to use a boring old switch eh? But I don't know enough about electronics to solve my powering down problem so I figured this will do.
How to get the Pi to detect when someone was at the bottom or the top of the stairs seemed like a much simpler proposal. There were plenty of tutorials on the subject and the sensors looked fairly easy to come by.
As I said, I wanted the LEDs to fade when going off but the Raspberry Pi outputs only support digital, on or off so I needed some other way of doing this. The method I chose was to build a set of small modules with a transistor and a capacitor. Here is the circuit diagram.
The module would be connected directly to the power supply but no current would flow into it until the base on the transistor received an input signal from the Pi. This would then charge the capacitor and illuminate the LED, once the signal from the Pi was disconnected the capacitor would discharge and fade out the LED. My only problem with this is that the fade time is not easily adjustable, but it works. To save wasting loads of strip board I packed the components as tightly as I dared.
Here you can see two modules on the same piece of strip board. You can also see that I'm using two capacitors. I started out that way, as I felt it gave a better fade, but I on completion I changed my mind as the modules were too bulky and removed the smaller ones to free up some space.
This was by far the most tiresome part of the project as I needed to make 11 of these modules, one for each LED. The reason there are 11 was that I wanted an LED for each step on the staircase and there are 11 of those in my house. Each module contains three wires; the 5v input, ground and the output from the Raspberry Pi to the base of the transistor. I cut six of the pre crimped wires giving me 12 crimped ends that could be plugged into the GPIO pins on the Pi.
My expertise in using a soldering iron increased dramatically by the end of the project, that's for sure.
After all the modules were constructed it was just a case of attaching them to a central unit that would house the power socket, light dependant resistor and output power via a usb cable to the Pi. I also decided I'd attach a small red LED that would turn on when the system detected it was dark, just so that I'd know things were working.
Not quite a picture of the finished article, but it's the last picture I took before I assembled it completely. I took an old USB cable that I had lying around and cut it open and connected the red and black wires to the positive and negative rails on the main board. I could have bought a normal USB connector thing and soldered that on instead but I just went with what I had:
I thought I would add a variable resistor between the LDR and the capacitor from the earlier darkness sensor tutorial.
The thinking being that I might be able to control the sensitivity of the sensor. Unfortunately this didn't really work out as well as well as I had hoped for. It does work, it just doesn't give the sensitivity range I'd hoped for. Is it worth it? Probably not.
Up to now we've just been building the modules, they aren't connected to the LEDs yet. I decided the best way for me to achieve this would be to have a strip cable from the main unit out to my home made LED strip, then I could plug and unplug the LED strip as and when I needed to.
I made my own strip cable using the 2x12 way crimp housing and cutting up 12 of the blue and black pre criped wires. One side blue for the 5V and the other side the negative return from the LEDs back to ground.
If I was doing this again, I'd probably just buy some strip cable, I'm not really sure what I was thinking by trying to make my own. Maybe just to prove to myself that I could. I would then plug this into the gold plated header which would also attach to another home made strip cable.
The LED strip was made with quadrant pine moulding from B&Q.
I measured the distance between the centre of each step and marked the position . I then drilled a small 2.5mm hole all the way through the wood and then a larger 4mm hole, but not all the way through, so that the LED would sit inside the wood without falling out the other side. I don't have all the necessary woodworking tools for this sort of thing so I constructed a jig out of LEGO to hold the angled wood in place while I drilled. A little side build which was a lot less hassle.
It held up pretty well and I was able to get most of the LEDs sitting inside the wood without too much of an issue.
Then it was just a case of putting it all together. We have a handy cupboard at the bottom of the stairs which houses the electricity meter, so I just put the main unit in there and lay the strip cable under the floor over to the LED strip on the other wall. This wall is also where the nearest power socket is.
Some of the code from stairled.py maybe needs explaining.
# GPIO pin defines LightDetector = 2 infoLed = 4 irDetBot = 14 irDetTop = 15 stairLeds = [18,23,24,25,8,7,1,12,16,20,21] ledActives = [0,0,0,0,0,0,0,0,0,0,0]
irDetBot and irDetTop are the two IR detectors which I have connected to GPIO pins 14 and 15. The pins controlling the LEDs are listed in stairLeds.
Inside the checkChange check, there is this, slightly confusing bit of code. If both top and bottom have been triggered we don't want the LEDs that have just been turned on being turned off because they came on later. For example if someone is at the top, the lights at the top start coming on. If someone then appears at the bottom, the bottom lights start coming on and meet with the lights from the top coming down. The light at the top will now want to switch off as the time has passed, but it should stay on. So we reset all the counters so the lights go out from top and bottom at the same time.
if activeCount == 11: if botTriggered and topTriggered: for k in range(0,11): ledActives[k] = 1 topTriggered = 12 botTriggered = 12 time.sleep(15) else: time.sleep(15)
Inside the main loop:
lightVal[count] = rc_time(LightDetector) print(count) count = count + 1 if count >= 5: count = 0 for i in range(0,5): average = average + lightVal[i] average = average / 5 if average > 550: GPIO.output(infoLed, GPIO.HIGH) active = 1 else: GPIO.output(infoLed, GPIO.LOW) active = 0
This takes the reading from the light detector and averages it out over a few seconds. This just smooths out the results a little and stops the system flickering between on and off.
The last step is to get the script to run when the Raspberry Pi turns on. Thats just a case of adding this line to rc.local.
python /home/pi/stairled.py &
That's it, stair project is complete. Approach the stairs in the dark and have your way lighted forever more. I apologise for many gaps in this process, but I've put this together, as a few people have asked how I did it, some time after having made the project and I didn't document my steps as I went along as I wasn't fully sure of what I was doing. Hopefully it makes sense and coupled with the other tutorials there is enough to go on to enable you to construct this for yourself.
If I was doing it again, knowing what I know now, I'd probably use neopixels :)
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) # GPIO pin defines LightDetector = 2 infoLed = 4 irDetBot = 14 irDetTop = 15 stairLeds = [18,23,24,25,8,7,1,12,16,20,21] ledActives = [0,0,0,0,0,0,0,0,0,0,0] # global variables topTriggered = 0 botTriggered = 0 # set the led that tells us the system is active GPIO.setup(infoLed, GPIO.OUT) GPIO.output(infoLed, GPIO.LOW) # set the ir detector pins to inputs GPIO.setup(irDetBot, GPIO.IN) GPIO.setup(irDetTop, GPIO.IN) # set stair led pins to output and clear them for i in range(0, 11): GPIO.setup(stairLeds[i], GPIO.OUT) GPIO.output(stairLeds[i], GPIO.LOW) # check the light detector readings def rc_time (LightDetector): count = 0 GPIO.setup(LightDetector, GPIO.OUT) GPIO.output(LightDetector, GPIO.LOW) time.sleep(0.1) GPIO.setup(LightDetector, GPIO.IN) while(GPIO.input(LightDetector) == GPIO.LOW): count += 1 GPIO.setup(LightDetector, GPIO.OUT) return count # do the check for anyone going up or down the stairs def checkStairs(): global topTriggered global botTriggered global ledActives if GPIO.input( irDetTop ) and topTriggered == 0: topTriggered = 1 if GPIO.input( irDetBot ) and botTriggered == 0: botTriggered = 1 checkChange = 0 if botTriggered or topTriggered: checkChange = 1 # if someone is at the top then start incrementing the top var this goes from 10 to 0 if topTriggered: if topTriggered < 12: ledActives[11-topTriggered] += 1 else: # topTriggered starts off here at 12 so 22 - 12 = 10 as this also goes 10 to 0 if ledActives[22-topTriggered]: ledActives[22-topTriggered] -= 1 topTriggered = topTriggered + 1 # once 24 is reached we are done so go bak to zero if topTriggered > 22: topTriggered = 0 # if someone at the bottom start incrementing the bottom var this goes 0 to 10 if botTriggered: if botTriggered < 12: ledActives[botTriggered-1] += 1 else: if ledActives[botTriggered-12]: ledActives[botTriggered-12] -= 1 botTriggered = botTriggered + 1 if botTriggered > 22: botTriggered = 0 if checkChange: activeCount = 0 for i in range(0,11): if ledActives[i] > 0: GPIO.output(stairLeds[i], GPIO.HIGH) activeCount += 1 else: GPIO.output(stairLeds[i], GPIO.LOW) if activeCount == 11: if botTriggered and topTriggered: for k in range(0,11): ledActives[k] = 1 topTriggered = 12 botTriggered = 12 time.sleep(15) else: time.sleep(15) return def testLeds(): count = 0 while count < 11: GPIO.output(stairLeds[count], GPIO.HIGH) time.sleep(0.6) count = count + 1 count = 0 while count < 11: GPIO.output(stairLeds[count], GPIO.LOW) time.sleep(0.6) count = count + 1 return lightVal = [0,0,0,0,0] active = 0 average = 0 count = 0 while True: if botTriggered == 0 and topTriggered == 0: lightVal[count] = rc_time(LightDetector) print(count) count = count + 1 if count >= 5: count = 0 for i in range(0,5): average = average + lightVal[i] average = average / 5 if average > 550: GPIO.output(infoLed, GPIO.HIGH) active = 1 else: GPIO.output(infoLed, GPIO.LOW) active = 0 # print(average) if active: checkStairs() if botTriggered == 0 and topTriggered ==0: time.sleep(1) else: time.sleep(0.25) # testLeds() GPIO.cleanup()
Did you replicate this project? Share it!I made one
Love this project? Think it could be improved? Tell us what you think!