Over-Engineered Closet Lights

Dillon Nichols
My Life as a Tinkerer
10 min readAug 18, 2017

This isn’t the first time I’ve made a complicated project just to turn on the lights in a closet. Sure, I could’ve used a strip of LEDs, a magnetic door sensor, and a relay and it would have the same functionality, but where’s the fun in that?

Just like before, I have a closet without a source of light and without a power outlet. This time, the closet is in my rented house, so everything must be non-permanently mounted. This project uses an Arduino to control LED puck lights using IR light.

The required parts for this build:

I started off by reverse engineering the puck lights so I could be sure that they met my needs. All results are in the Google Sheet, titled “Capstone Puck Lights”, shared above. Each light normally runs off of 3x AAA batteries, so they should be powered by 4.5V. I measured the current consumption at each brightness interval to find a power supply that can handle the full load of six lights at maximum brightness. I also powered them with 5V and measured the current because 5V power supplies are easier to find. The LEDs worked at 5V, but they might be operating past their max specifications which would result in a shorter lifespan. In the end, I made a 4.5V power supply to use on this project.

Test setup for receiving, decoding, and retransmitting the IR protocol

I used the IR receiver with the Arduino Leonardo to capture the code sent on each button press of the remote using the record.ino sketch from the IRLib2 repository. These LED pucks use the NEC protocol and the commands are listed in the “Commands” tab of the Google Sheet. I also reversed the protocol in the “ Command Decoding” tab. The protocol is amazingly simple. The format is 0xFF_0_F, where the first underscore is the command byte and the second underscore is that byte’s bitwise negation. For example, the “off” command is 0xFF807F. The command byte is 8, or 0b1000. The bitwise negation is 0b0111, or 7. I found that the buttons on the remote are commands 0 to 11, but that leaves 12 to 15. Upon further experimentation, I determined that the other commands don’t do anything. I even looked at Capstone’s other products and their remotes always use 12 buttons, so it appears that the other commands just aren’t used.

Disassembly showing inner ring | Pigtail soldered onto battery terminals | Pigtail routing through opening

The next step was converting the battery-powered lights to be powered from the wall so I’ll never need to change the batteries. This worked out much better than I expected. When I disassembled the lights, I realized there was a plastic ring around the center that could be removed. This made it clear where the IR receiver was located as well as leaving an opening to route the power wires outside the case without making any modifications to the plastic. Inside the lights, the + and - terminals are clearly marked and easy to solder to. I used the male end of the pigtails on the lights so the power cord could use the safer female ends. I mounted the lights to the closet frame using the included 3M tape. I made sure the IR receiver was pointed to the ceiling because that is where I planned on mounting the Arduino controller.

I guess I shouldn’t be surprised that it broke, but I wish I would’ve tested it before I painted it

Due to the design of the door, I chose to use a pin switch as an input to the Arduino to detect the door’s state. These switches are often used in cars to detect when the door or hood is opened, so I expect they can handle the force of a closet door shutting. I made a piece of 2x4 with holes for the switch and screws to mount to the door frame. I also painted it to match the frame. When I attempted to install it, the wood cracked where the screws would attach it to the door frame. I tried another piece with the wood grain in a perpendicular direction, but the same thing happened.

This new design is very sturdy

After this, I knew wood wasn’t going to work so I searched the house for a stronger material. I found a leftover piece of exercise equipment made out of square metal tubing. It even came painted the correct color and with an end cap to hide the insides. I used the preexisting hole and drilled two more holes for the screws. I used some washers to mount the pin switch because the hole was too large. Then I mounted it to the door frame. I connected the wires so that the ground connection is to the body and the output is on the tail. I tested by closing the door and the switch opens when the door is latched shut. Success!

I used the IRLib2 to capture the remote’s packets, and also used it as a basis for my code. I took the send.ino sketch and modified it so that it sends the on or off command based on the state of the pin switch. I also decoded the other buttons and added a fade effect when it turns on and when it turns off (although it’ll be behind a closed door and you’ll never see it). When I was measuring the current, I determined that pressing “on” sets it to 80% brightness, so after turning on, I delay and then set it to 100% brightness. Lastly, I send the “10 minute shutoff” command so I ensure that the lights shut off after 10 minutes in case I accidentally leave the closet door open. When turning off the lights, I smoothly step down through a few different brightnesses and then turn it off. As simple as it is, my code is located in the project’s repository on GitHub. Follow the instructions in the README to install the IRLib2 and Button libraries.

Two pins — One input, one output | Simple shield mounted on the Arduino Leonardo clone

The shield for the Arduino Leonardo is just as simple as the code. It has a 2 pin screw terminal for the pin switch that is mounted between pin 12 and ground. This relies on using an internal pullup on the Arduino’s pin. I also have the IR transmitter connected with the DAT line to pin 9. Although there is a VCC pin on the transmitter, it is not connected and not required for operation. Of course, connecting ground is also required.

One weird trick to producing the correct output voltage!

I mentioned earlier that I measured the currents at 5V because I thought that I would need to use that voltage due to the abundance of USB power supplies. Surprisingly, I found a 4.5V AC/DC adapter in my collection. Fortunately, I measured the output before using it and discovered that it was measuring around 6V even under high load. I thought I’d have to go back to 5V, but first I looked through my box of power bricks. The only one that I found that was close to the desired voltage was 5.2V, 2.2A. That wouldn’t work… or would it? While I was putting everything away, it dawned on me that 5.2V is 0.7V above the required 4.5V — a diode drop! I made the above circuit on a small piece of protoboard and it worked. The 1N4001 is rated for 1A and I’m running way below that, so it should be stable.

The next step was creating the wiring harness. It required a lot of measuring, cutting, soldering, and heat shrink but everything worked, much to my surprise. It begins with the power adapter that I made above and then there’s a female jack at the location of each light. Additionally, there’s a jack at the top of the door to power the Arduino. For the Arduino, I made a cable that is another pigtail attached to a USB Micro power cable. All of the lights are wired in parallel so they each receive 4.5V. This configuration draws less current than if they were mounted in series so the Arduino and all six lights set to full brightness only draws about 125mA. Further measurements are presented in the “Mounted Specifications” tab of the previously mentioned spreadsheet.

Hacked together mount | Screwed to ceiling | Arduino wired in place

I needed a way to mount the Arduino somewhere. There’s a piece of plywood covering the entrance to the attic in the closet, so I thought this would be the best location. I knew I couldn’t screw the Arduino directly to the plywood so I needed to make something to mount it. I was looking around my desk for inspiration and found this foam. I sandwiched a piece of cardboard between two layers of foam to add stiffness. I also left cutouts in the bottom of the foam so I could mount nylon standoffs. I wanted to screw the standoffs in place, but the threads weren’t long enough, so I hot glued them instead. All I needed to do was run some screws through the foam to mount it to the ceiling. Then I screwed the Arduino onto the standoffs and attached the power and pin switch wiring. It’s mounted in place, but I’m worried about the temperature. There’s no insulation on the plywood that is covering the entrance to the attic so it gets very hot during the summer and very cold during the winter. The TI MSP430 from my other closet project has been in my parent’s attic for over four years without an issue, but only time will tell if the Arduino can also survive these extremes.

Bending the LED downwards fixed my issues

December 2017 update: I’ve had this project running for four months now and sometimes I’d notice that the lights would still be on when the door was closed. I started by adding the light-dependent resistor (seen in the above photo) to detect when the door was closed and the lights were on and then issuing the “off” command again. Unfortunately, the lights that didn’t turn off were at the bottom of the closet and this LDR wasn’t sensitive enough to detect between all lights off and just one light on at the bottom of the closet, so I had to scratch that idea. Next, I added a library into the Arduino code which would debounce the pin switch on the door to ensure the code always matched the physical state. Again, this didn’t work. As I was checking out the circuit, I noticed that the IR LED was in line with the PCB (check any other photo of the circuit in this post to see what I mean). This meant that the IR LED was pointing straight into the wall and probably 70° away from the bottom lights. I thought this wouldn’t be an issue at first because the light should bounce off the walls in the closet and hit all of the lights, but I was wrong. I bent the IR LED to face the bottom lights and they started to switch every time. They even would switch when I had the blinds open and daylight was streaming in. Before the daylight would overpower the IR signal and I couldn’t switch the lights. Just remember that sometimes the answer is so simple, you may overlook it.

As I mentioned earlier, the power outlet is outside the closet, but I was able to run the wire inside through a hole that was drilled for the TV connection. Inside, the AC/DC adapter is wired into the power adapter and then connects to the wiring harness that powers the LEDs and Arduino. The six LED pucks are mounted with two on the top and two on each side. Everything is mounting and working, but the small size of the closet makes it impossible to take a photo of all six lights and the Arduino with an iPhone camera.

That’s it! Another part of my house is automated. I think these simple projects that just work without any outside interaction are the best examples of home automation. There’s fewer failure points and they do exactly what you expect. I enjoyed making this project and I hope that this post will give you some inspiration to make a similar build using the parts you have on hand.



Dillon Nichols
My Life as a Tinkerer

Electrical engineer: hardware/firmware; tinkerer; hobbyist; amateur fabricator;