Over-engineered LED strip controller

Way too much stuff to light my garage MY way.

Similar projects worth following
I've put up the usual 12V LED strips to give more light in my garage. Like everybody else, I'm going to make a custom controller for those lights. This is part practical, part aesthetics, and part learning exercise.

My garage is 20 ft x 30 ft. (That's about 0.01 US [Imperial] football fields and an indeterminate number of metric [FIFA] football pitches.) The original lighting in there is 3 connected ceiling-mounted sockets. That's enough light to walk through there without risking your life, but it's very poor lighting for actually doing anything in that garage.

It's easy to find many descriptions of people putting up inexpensive 12V LED strips in garages or other places. So, hey, me too! I'm not bothering with describing much of that part of the project because there is nothing special about my take on it. This project is about the controller I am making for it.

Creative Commons License
Over-engineered LED strip controller by WJCarpenter is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

  • 2 × STP16NF06L mosfet
  • 4 × shallow single-gang plastic electrical box
  • 2 × PIR motion sensors
  • 4 × generic LEDs
  • 30 × meters (approx) of 3-pair solid wire telephone cable

View all 14 components

  • Tickled green

    WJCarpenter09/28/2017 at 02:01 0 comments

    I received my PCBs today, and they are beautiful. I used the Seeed Fusion service. (The boards are very inexpensive, but the shipping from China to the US is pretty steep.) "Back in the day" , I've made some of my own PCBs with some of the usual home-based methods. Although they worked (sometimes), they always looked like a mud pie. This is the first time I've used a fab to make custom boards. They are gorgeous and exceed my expectations.

    That's right. I did label the "top" and "bottom" of my board. Hey, they're both green, white, and silver.

  • Updates on various things

    WJCarpenter09/25/2017 at 23:52 0 comments

    It's a good thing I don't do this for a living, because I don't go very fast. Mostly it's because I act like a dog that goes in a different direction every time it smells something new. I've worked through several things without updating the project log. Here are quickies for those:

    • I'm now using the SparkFun ESP32 Thing. I chose that mainly because it's got enough available pins, and I had one right here in the parts department.
    • Now that I have moved to an ESP32 board, I found a very nice Lua implementation from this European education (not sure) project: The thing I like about it, compared to the NodeMCU flavor of Lua, is that it has true threads via Lua-RTOS-ESP32 instead of just co-routines. I think the threads are going to simplify my software quite a bit.
    • For a while, I was planning to use this D-duino-32 V2. It has a small SSD1306 OLED screen right on the board. I don't really need a display for this project, but I thought it might come in handy for the software development phase when it wasn't convenient to have the serial console running. Although the display is rather common, and there is good support for it in the Arduino/C/C++ community, there isn't currently support for it in Lua-RTOS-ESP32. I considered porting a graphics library into the Lua-RTOS-ESP32 ecosystem, but it seemed like more work than I felt like doing.
    • While looking into the display possibilities from the previous bullet, I decided to have a look at the displays that Lua-RTOS-ESP32 does support. I was completely shocked to find out that these days you can get a 2.8 inch 240x320 TFT display (with touch interface! with an SD card slot!) for under $10 from multiple vendors if you can wait for shipping from Asia. What? And, you can get it faster in the US for only a couple dollars more. Like I said, I don't need a display for this project, but that doesn't mean I can't jam one in there with some contrived rationalization.
    • Putting the display into the project definitely rules out using a single-gang electrical box for the main control unit. The display module itself will not fit. I've decided to move up to a double-gang box and will mount the display horizontally. I thought it would be pretty easy to find a clear plastic blank faceplate, but it turns out to be difficult. In fact, I never found one. I settled for one with cutouts for two ordinary toggle light switches. It's the kind of faceplate where you can put in your own wallpaper so the plate matches your walls. I may later decide to use a normal opaque blank faceplate and cut a rectangular hole just right for the display (though I'm sure I'm doing a better job in my mind than I will in practice).
    • I finished the schematic and the PCB layout. Even with a double-gang enclosure, it was still tricky to fit everything on the board. I made a sort of layer cake out of it. The voltage regulator module is going on the bottom side of the board (which will be handy anyhow if there is any modest heat buildup). The ESP32 module is on the top of the board. Because I plan to mount the TFT display using tall-ish female stacking pins, the display sits on top of the ESP32 board with plenty of clearance. The other small parts are scattered around both sides of the board where they fit well or where I thought they would be most convenient. There are tons of screw terminals for connecting wires from the remote boxes.
    • I sent the board Gerbers off to Seeed Fusion and am now waiting.
    • I have not started the software yet, though I've been doing some mental planning. 

  • yo,, no!

    WJCarpenter08/20/2017 at 03:20 0 comments

    That didn't take long. I spent a couple of hours on, which looks like it is not Autodesk Circuits. It was sort of OK, sort of meh. But when I got to creating a schematic symbol from scratch ... that was a dealbreaker: 

    They give you a handful of drawing tools, but the tools have no idea they are drawing schematic symbols (except for the "pin" menu item). Once you put something onto the editor page, you're not going to change it much. You can select it, and then you see a small context-sensitive form along the bottom. Would you like to move a part? No problem, just select it and then fill in the appropriate X/Y coordinates. If you want to move several parts, do each of them individually. The part I need to make has 26 pins, but it's not a DIP.

    There certainly might be an friendlier way to do that, but I didn't discover it. (Large swaths of the site look like they haven't been touched since 2015, so I'm not optimistic about improvements.)

    Anyhow, I'm back on I still don't remember why I left.

  • online design sites

    WJCarpenter08/19/2017 at 21:29 0 comments

    Despite the fact that I was once a software guy working on a tiny piece of a gigantic in-house EDA suite, I've never really spent any time designing something in a real EDA environment. So, prompted by 's series, I set out on a quest to do that. My plan was to limit myself to the online EDA tools for now.

    I started at and got about half-way through the schematic. I became unhappy with it for reasons that I now honestly cannot remember. I think I was having trouble finding things in the parts library or something.

    Anyhow, I started over at Maybe if I were a practicing EE things would be a lot more clear, but I found it fairly difficult to grasp all the "easy" things they were trying to tell me. It doesn't help that there are many busted help links. It was painful, but I stuck with it and actually got all the way done with the schematic. That included making a schematic symbotl for a D-duino-32 V2 (, more about that in a separate log post). 

    Now comes the time to push a button and get a PCB layout. A couple of my schematic parts don't have footprints. That's when it became pretty frustrating. There is an editor for making PCB footprints, and I know the exact size of the D-Duino-32.  It's mostly a rectangle with rounded corners. I wasted a lot of time trying to just get the rectangle part with the correct dimensions. I don't mean the correct dimensions plus-or-minus a few tenths of a millimeter. It would have been awesome to have a property sheet so I could just type the numbers, but I had to (try to) do it tediously with a drawing tool. Maybe there is a way to do this that is a whole lot easier, but I refer you to my previous comment about busted help links.

    I plan to check out one more site ( If that doesn't fill me with bliss, I'll probably go back to

  • pin money

    WJCarpenter08/06/2017 at 21:42 0 comments

    Well, I've done it again. With all the bells and whistles, I don't have enough GPIO pins on the NodeMCU. Here's what I need right now:

    4 outputs with PWM

    8 inputs with interrupts

    2 outputs with simple on/off

    That's 14 pins, but the NodeMCU only has 13 available. If I deduct the two pins used for the serial console (in case I need that for debugging), there are only 11 available.

    Here are some strategies I am contemplating for handling this:

    • The NodeMCU 12E has 4 pins dedicated to an SPI interface. So far, I'm not using SPI. Is there a way I can repurpose those pins for the types of GPIOs that I need? From my quick look at the ESP8266EX datasheet, this might be possible. Have to figure out if the board makes any difference and then figure out if the software environment makes it inconvenient. 
    • Is there another ESP8266 or even another micro available in a similar small form factor that has more GPIOs available? SparkFun ESP8266 Thing seems about the same (or maybe a GPIO or 2 fewer).  Adafruit Huzzah looks like it has 9 GPIOs; I didn't drill down to see if more could be squeezed out because it's still not close. Wemos D1 mini and mini Pro have 11 GPIOs, but that includes the two serial pins..
    • Maybe it's just time to switch over to an ESP32 board. Those seem to have a couple dozen GPIOs even though they are not much different in physical form factor (just a little longer). They can be had for under $10. I'm not sure, but there might be some incompatibilities in the Lua API.

    Before I started pondering the above, more fruitful, options, I was thinking about more traditional pin count solutions. I could mux the plain on/off outputs with a SIPO shift register, but that's pretty boring since there are only 2 of those outputs. I thought about some way of multiplexing the PWM outputs but didn't get very far down that path. 

    The 8 inputs that need interrupts seem ripe for consolidation. There is such a thing as an 8-input OR gate in a 16-pin package (for example That could tell me if some interrupt occurred. I could run the same 8 inputs to a PISO shift register and read them out as the first part of the response to an interrupt. That's pretty simple, but also simple-minded because it ignores a few edge cases. Luckily, in this application, I can tolerate a lost interrupt here and there. (I also briefly looked for an interrupt controller, but it seems the world didn't any simpler than the Intel 8259. Besides being a pretty big chip, it also seems pretty complicated. I grant you, it does some pretty sophisticated things. I just don't need those things.)

  • Don't fret, MOSFET

    WJCarpenter08/05/2017 at 19:47 0 comments

    Today is about experimenting with driving the MOSFET that will be the dimmer control for the strips.

    First, I tried driving it directly with PWM from a GPIO pin. I verified that the PWM does step the gate voltage up and down from ~0v to ~3.3v. I also verified that simple GPIO high/low gives the same result. Nothing unexpected there.

    The switching voltage for the MOSFET I'm planning to use is 2.5v (STP16NF06L:, because I have a handful right here). I did some tests driving the MOSFET gate directly from a GPIO pin, both for simple on/off and for PWM. My switched voltage to the MOSFET (ie, the thing I want the MOSFET to control) is ~12v from a wall wart. With GPIO on/off, I got just about ~12v/0v on the nose. With PWM at 100%/0% duty cycle, I also got ~12v/0v. I did a simple software loop that varied the PWM duty cycle up and down in steps, over and over. I'm too lazy to drag my scope over here, so I just measured that with my multimeter., which updates the display about every half second or so. (I have no idea how frequently it samples.) I saw it go as low as 0.06v (correction, I just saw exactly 0.00v), but only as high as a little under 10v. I suspect that high part is due to some kind of rise time thing in my meter. OK, OK, you talked me into it. I grabbed my much-newer-but-much-cheaper meter. It updates a lot more frequently. I now regularly see it hitting ~0v and ~12v. Yay.

    My load for this breadboard test is just a simple LED+resister, so the current is probably around 20mA. I wonder how the load of the LED strips will affect this MOSFET. I plan to use 2 MOSFETs with each controlling a single LED strip. Earlier, I measured the A/C draw for a single strip as 40-45w.  Since I don't really know what I'm talking about, I'm going to assume the strips draw a maximum of 45w at 12vdc, or a little over 3 amps.

    Now we're off to the races with the datasheet for this MOSFET. I've watched or read several discussions of how to use a MOSFET datasheet, but ... you know. This datasheet has a nice graph for the "safe operating area". That sounds good. 

    It looks like it can handle a little over 3A of 12v supply, but it's also pretty close to the margin. Let's try something else. ST provides a smart phone app called "ST MOSFET Finder" that will let you do a parametric search to find appropriate ST MOSFETs. When I put in the parameters I've just discussed, the MOSFET I planned to use is not among the search results. Drat. I guess I have no choice but to actually measure the DC load of one of those strips. Wait right here.

    Things are looking better. With the power supplies that came with the strips, they are drawing 1.5A @ 12.6V, or <20W DC. That puts us well within the safe zone.

    What about heat? This guy's video provides a pretty clear explanation of how to calculate that from the datasheet. Following his calculations, I get about 1/4 watts of heat and about a 15 C rise in temperature with no heat sink. I doubt that it's ever been as warm as 50 C in my garage. 15 C + 50 C == 65 C is well under the max operating junction temperature of 175 C, so I think I just have to worry about melting something in the case I use to mount these. I'm most likely to use a fairly standard wall-mounted electrical box. The common blue PVC boxes available in the US are typically rated for 90 C conductors. That seems like plenty of margin.

  • more about PIR

    WJCarpenter07/31/2017 at 00:04 0 comments

    After some more experimentation, it seems like these components are very sensitive to input voltage. It's alleged that they want anything from 4.5v to 20v, but the tirggering behavior is pretty erratic for every power supply I've tried from 5.5v up to 12v.

    They seem to work best (most stable) when powered by the 3.3v pin from the NodeMCU board. Hmm. In my note yesterday, I forgot to mention that. Actually, I didn't even notice until I was looking at my breadboard this morning. It's one of the zillion things I tried.

    I guess if I end up using the HC-SR501 units in the project, I'll have to select the specific ones by testing them with the voltages I have available (which will be 3.3v, 5v, and 12v). Maybe the AM312 units will be more consistent.

    Another thing.... Sometimes, after getting my 2-3 seconds of HIGH for motion detection, the signal will go low for 5-7 seconds and then mysteriously go high again for another 2-3 seconds. That won't make too much difference for this garage light project since the lights will still be on from the initial trigger.

  • Once more in the Lua

    WJCarpenter07/30/2017 at 03:29 0 comments

    I've spent some time looking into Lua. I think it will meet my needs for this project.

    As with most languages, the authors have made some choices that I wouldn't have made. However, there seems to be at least a reasonable rationale for the things they decided. And they seem to have made it so that you can get close enough to things you want the language to have. For example, Lua doesn't need semi-colons to terminate statements ... but you can put them in there if you want to. Yay! They don't have real classes and objects, but you can make your code look a lot like it does.

    I was planning to do most of this code in an event driven way, and the Lua libraries for NodeMCU make it pretty easy to register callback functions to handle interrupts. On the other hand, the standard libraries are not especially rich in devices (like Arduino-land), but I think that will be OK.

    Oh, yeah, it's got GC memory management. I've spent enough time debugging mismatched malloc and free, thank you, so GC is a major plus for me. I doubt that I will have that many collectible "objects", but it's nice to not have to worry about it.

  • Seeing red over infra-red

    WJCarpenter07/30/2017 at 03:21 0 comments

    Today was a pretty frustrating day. It took me way too long to get my passive IR motion detector working correctly, though I was victorious in the end.

    I think the most common module is HC-SR501 or something that looks like it. I got a handful of them to use in this project. My main reason for selecting that component specifically is because of the abundance of sample wire-ups and code fragments. I set about doing the same thing ... read the PIR and show what I got on an LED.

    Here's the thing about these: I guess a lot of different places produce them, and the specs vary a little bit. Most commonly, there is a variation on what operating voltage they will accept (though, luckily, they all seem to put out ~3.3v for the signal). The ones I have didn't come with a spec sheet. I have what it said in the description on eBay, but that's not always accurate.

    Let me cut to the chase: I spent hours trying to get rid of spurious triggerings. I tried decoupling the input voltage, I tried pull-up and pull-down resistors on the signal, I even wrapped the entire sensor component in aluminum foil. No matter what I did, every 15 seconds or so I'd get a few seconds of high signal indicating motion detected. These things have two pots and one jumper setting. I tried all kinds of combinations. I tried swapping around the Vcc, ground, and signal wires just in case the silk screen was wrong.

    Finally, the thing that worked was turning the sensitivity pot all the way down. That seemed to do it. No decoupling caps, no resistors, just the board and some wires. I don't know if I just got a bad batch of if they are all like this.(I did have one that was from another source [another source for me; could have been assembled in the same factory line], and it was the same.) What's the point of having a sensitivity pot if it only works when it's turned all the way counter-clockwise?

    Along the way, I found some badly translated operating instructions and some other instructions that were just plain wrong. Here is what I deduced from a lot of pondering.The jumper controls repeatable or non-repeatable triggering. I found those terms a little confusing. "Repeatable" means the signal stays high as long as motion is detected; when motion is no longer detected, the signal goes low after a short time. "Non-repeatable" means the signal is made high for a short, fixed duration. After that the signal goes low and won't go high again until there is a period of no motion and then motion is seen again. Even with non-repeatable, it's not just a single pulse; or rather, it's a single pulse of a couple of seconds.

    I'm a little leery about the lack of precision (or something like precision) with the HC-SR501. I've ordered a different type of PIR that goes by the designation "AM312". The specs and form factor are somewhat different. We'll see.

  • what's with Lua?

    WJCarpenter07/16/2017 at 22:08 0 comments

    Earlier I said, "I don't plan to use Lua". That's mainly because of a personal bias against languages that don't really add anything except their own flavor of syntax and their own crowd of cheerleaders. I've saved myself a lot of tiresome dead ends that way. For example, if a language has built-in "dictionaries" or "maps" or whatever, it's a big yawn to me because I can get the same thing is most other languages by just calling a library of some sort.

    But there is no ignoring languages that have a rich ecosystem. For example, the Arduino environment has tons of C/C++ libraries for doing all kinds of things. So, even though it's a somewhat "non-technical" environment, it is really, really handy for saving a ton of grunt work.

    I've been looking through the eLua APIs and reading some of the claims made by the Lua gang. If what they say is true, then it sounds pretty compelling. Especially that it plays well with C/C++, so there is always an out if I find something it doesn't have.

    I'll be considering the ecosystem differences and synergies of the Arduino and Lua camps as I get a bit closer to the software layer.

View all 16 project logs

Enjoy this project?



Graham Toal wrote 07/16/2017 at 02:12 point

This (use a pi zero w for lower cost, or stick with the ESP8266 if you prefer working at a low level) should do most of the analog side for you:

  Are you sure? yes | no

WJCarpenter wrote 07/16/2017 at 02:30 point

Interesting idea. Thanks.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates