DIY Smart LED Ceiling Light with 8 Individually Dimmable Channels

July 18, 2018

Dimmable LED Smart Ceiling Light

Today on the hookup we’re going to build the ultimate customizable ceiling light including 8 individually dimmable and controllable LED spotlights and LED ambient lighting.

In addition to smart home technology, one of my other interests is design, where I often lean towards a more modern aesthetic.  Around 10 years ago I built this entertainment unit for our family room, but when we moved into our new house the lighting, which we lovingly call the boob light, never really seemed to match.   After looking around for the perfect light for our needs, I decided that building it myself seemed like the best option.

After a quick mockup in sketchup to look at different light configurations my wife and I decided on a design, and it was time to start building.

For this project I used  8 of these 12 volt LED led spotlights, a 12v led strip light, a 12 volt power supply, some N-channel mosfet transistors, a prototype board, some header pins and  everything is controlled by a ESP32 based nodemcu.  Normally I use ESP8266 based nodemcus in my projects, but the ESP32 was a much better option for this particular project, and to explain why, we need to know a little more about how a dimmable LED circuit works.

When dimming an old incandescent bulb a dimmer switch worked by adding a variable resistor into the circuit which would effectively limit the current flowing to the bulb.  Because there was less current the filament heated up less and therefore produced less light.


Dimming an LED isn’t quite as simple since they generally operate at narrow voltage and current ratings.  Instead of sending less current, LED dimming is done by rapidly turning the current on and off in a process called pulse width modulation or PWM.

If you were to turn a bulb on for 1 second and off for 1 second you would produce half the light that you would if you had just left the bulb on for 2 seconds, but you would obviously notice that the bulb had turned off.

If you instead turn the bulb on for a millisecond and off for a millisecond and repeated the process for 2 seconds, you would notice that the bulb was 50% less bright than leaving it fully on, but you wouldn’t notice that the bulb was flashing.

Since the lights are on for .001 seconds and off for .001 seconds, that means that the whole cycle takes .002 seconds, and we could complete 500 cycles in a second which is called it’s frequency it’s measured in hertz.  The unit hertz just means times per second and since we can do 500 cylces per second, this is a frequency of 500 hz.


The second part of a PWM signal is called the duty cycle which the time that the circuit is on, divided by the total duration of the cycle.  In this example we turned the light on for 1 millisecond, and our cycle duration was 2 milliseconds, so our duty cycle is 50%.  The duty cycle determines how bright the LED appears and the frequency determines how noticeable the flicker is.


I love the ESP8266 nodemcu and use it in the vast majority of my projects, but it generates its PWM signals using software and processing power, this means that if wifi traffic gets high, or if you’re using the processor to run some other calculations it will lower the PWM frequency to compensate resulting in noticeable flashing.  The ESP32 has 8 built-in independent hardware PWM channels which are timers that aren’t responsible for anything other than producing a consistent PWM signal at insanely high frequencies up to three hundred thousand hertz.

For this project I am going to use a more modest frequency of 600hz, because it’s generally accepted that humans can’t perceive any flickering in frequencies over 200hz, so we’ll triple that just to be safe.  Some cheap LED bulbs end up with frequencies around 60hz due to the way they switch between AC and DC current, which can cause headaches for some people, but these bulbs should be buttery smooth.


You’ll also notice that the bulbs I use for this project specifically say they are non-dimmable, but this actually only refers to their power supply circuit, and since we’re providing our own power supply and driver all we need are the LEDs, and there’s actually no difference between dimmable and non-dimmable LED chips,  so buying the non dimmable type will save us a few bucks.


Enough talking, lets build stuff.  I started out by cutting the 14 inch by 14 inch square that will become the main light.  I used a table saw to cut down some leftover birch plywood that I had laying around from another project but you absolutely don’t need a table saw for this project.  A circular saw, jig saw, or even a hand saw would work just fine.  Next I cut the pieces that would become the base of the light, originally I cut them 6 inches tall, but after a quick dry fit I decided that was too tall, so I cut an inch and a quarter off to put the base at a total height of 4 and three quarters inches.


Then I drilled pocket holes to attach everything together.  I’ve gotten a bunch of use out of this kreg jig junior, and it’s significantly cheaper than the full jig.  If you like to build things and don’t have a pocket hole jig yet, I highly recommend this one.

I drilled four holes in two of the side pieces and screwed them together, it was too tight to fit a screwdriver inside when I was putting the sides together, so I used a socket wrench to drive the final four pocket screws in.


Next I marked the center of each LED hole and used a the largest hole saw I had, which was 2 and one eighth inches to cut the holes for the lights.  When using a hole saw drilling all the way through from a single side will cause significant tearout.  To prevent this you should flip your work piece once the pilot hole goes all the way through to the other side.  It also makes it much easier to remove the cut out hole from the bit.  After a quick test fit I realized that the largest hole saw I owned wasn’t going to cut it [wink].  At this point I searched how much a 2 and three quarter inch hole saw cost, and decided to just use my router to make the holes a bit bigger, if you have a 2 and three quarter inch hole saw you can save yourself a bunch of time by drilling the correctly sized holes the first time.

Of course my routered holes aren’t perfect circles, but there is a big enough bezel around each LED that the holes don’t need to look nice.  I also took the opportunity to hog out a little bit of material above each of the lights to give them a little more clearance, a jig saw would have been a better tool for this, but I already had my router out.  This wasn’t exactly a precision process, but I wasn’t too worried about it since none of this would be visible once the light was installed.  Once I was done with the router I did a quick test fit of the lights before moving on to the detail work.

To give it a more finished look I used a heat gun to attach some edge banding over the unfinished plywood edges.  A clothes iron is a better tool for applying edge banding, but the iron was upstairs and the heat gun was in the garage, so concessions were made.  The key to good edge banding is to make sure there is a small overhang on both sides allowing you to sand it flush later on.

To start Iused 80 grit sandpaper to knock down the overhangs of the edge banding and take care of the small amount of tear out that happened on the LED holes and then switched to 220 grit to finish it off.  I definitely don’t have the patience for the detail work of woodworking, my general mantra is that if the sanding can’t be done with a power tool, it’s probably not going to get done.

Thankfully my wife has better attention to detail and is therefore in charge of painting or staining all of our projects, she does a significantly better job than I ever could.

While my wife worked on the finish I started to put together the circuit board to control the lights.  As  we discussed earlier the ESP32 can generate a great PWM signal with high accuracy, but it does so at 3.3volt and very low current, so trying to drive 12V LEDS with that signal wouldn’t work at all.  We need to step up the voltage using a transistor.  When you’re working with different voltages the best way to switch between them is a transistor called an N-channel Mosfet.


A MOSFET has three pins, the gate, the source and the drain.  The cliffs notes for transistors is that applying a small voltage to the gate will allow a larger voltage to flow from the drain to the source.  A transistor essentially works like a variable resistor, the more voltage that is applied to the gate, the less the resistance between the drain and the source, and once you reach a voltage called the threshold voltage the resistance essentially goes to zero, which is what we want.  To be absolutely certain I was reaching the threshold voltage I decided to use a logic level converter to change the 3.3v logic of the ESP32 to 5v logic.  According to the datasheet the mosfets that I used had a threshold voltage of 2 volts, but in practice I found that even at 100% duty cycle the LEDS weren’t quite at full brightness.  If you want to make this project I’d recommend you use a slightly different transistor than I did.  I’ve posted a link to the better transistor with a lower threshold voltage down in the description. If you use those transistors you will be able to skip the logic level converter.

For each LED spotlight the GPIO pin outputting PWM on the ESP32 goes through the 3v to 5v logic level converter, then into the gate on the MOSFET.  The positive terminals on the LEDs connect to the positive 12V terminal on the power supply and the negative of each LED connects to the drain pin on the MOSFET.  The source pins on the MOSFETS are connected to the ground terminal on the 12V power supply, which is also connected to the ground of the ESP32.  This same circuit is essentially just repeated  8 times with 8 different GPIO pins on the ESP32, one for each LED spotlight.  I’m running the ambient LED strips on a different switch because I have two different switches for this light, but if you wanted the ambient lights to be controlled by the ESP32 you’d just need another MOSFET circuit.  I used two of the 12 volt adapters that came with the LED spotlights to power my LED strips, this ensured that I wasn’t drawing too much current from these cheap 12 volt adapters.

I wired everything up on a prototype board using quick connect harnesses to make it easier to change out the LEDS if they were to burn out.  I also made four quick connect extensions to make it easier to wire the corner LEDS.

The last thing I needed to do to finish the wiring was power the nodemcu.  To do this I used a buck converter to convert the 12v power source into 5 volts.  When setting up a buck converter, first disconnect the power from your ESP32 or remove it from the header pins.  Then connect the 12v source and turn the set screw on the buck converter. Measure the output voltage until you get a voltage you are happy with.  I’d recommend slightly under 5v, for the ESP32.

Next I wrote a bit of code in the Arduino IDE to control the PWM signal.  If you’ve ever coded in Arduino you’re probably familiar with the analogWrite function.  Unfortunately, analogWrite hasn’t been implemented yet for the ESP32 so PWM signals are generated through something that is called LEDC.  LEDC requires that you specify a frequency and duty cycle for each hardware timer you want to use.  As we discussed before we’re going to use a frequency of 600 hz and we’ll adjust the duty cycle based on an 8 bit integer.  This means 0 will be a 0% duty cycle or full off and 256 will be a 100% duty cycle or full on.  Each light has a separate MQTT topic to accept brightness messages and each will publish it’s current state (on or off) to a specific state topic.

I’m controlling my light with an open source home automation program called home assistant, specifically the version of it called  If you’ve never heard of it and you want to get into home automation, I highly recommend you check it out.  In my opinion it’s absolutely the best consumer grade option and there is an amazing community of users out there willing to help you get started.


In my configuration file for home assistant I’ll add these 8 entities under the light domain, one for each LED spotlight.  I’ll also add a group that contains all 8 lights, which will allow me to turn them on and off and set their brightness as a group.

I tested out all of the functionality on the floor before installing it, and after a bit of troubleshooting due to a bad solder joint I was ready to install it.

After turning off the power at the breaker I removed the old light and marked the locations of the mounting screws.  I drilled slots in the mounting plate to allow me to adjust the angle of the light once it was hanging and then installed it using some washers.  I pulled the wires through the mounting holes connected the mains leads using wire nuts, and put two screws on either side of the base to fix it to the mounting plate.

After turning the power back on all that was left to do was test it out.  Each channel can be controlled individually or as a group and can be set to specific brightness by my amazon echo dot.  Each light is aimable to highlight different areas of the room that need more task lighting like my 6 year old’s drawing table.  Overall, I’m really happy with the way this project turned out and the lights are really bright, even though I bought the 3 LED version.

Total cost of this project for me was around $60 since most of the parts were leftover from other projects, but if you needed to buy everything including wood it would probably run you around $120.  Amazon links to the parts to build this project are down in the description as well as links to the Arduino code you’ll need to get this thing working.  If you run into problems while making this project you can leave a comment and I generally respond within a few hours.  If you enjoyed this video and you’d like to see more like it, please consider subscribing, and as always, thanks for watching the hook up.

Parts List:
LED Lights:
LED Strips:
12V Power Supply:
ESP32 NodeMCU:
3.3v MOSFET:
Wiring Harnesses:
Buck Converter:
Prototype Boards:
Header Pins:
Hook Up Wire:

Arduino Code:
Home Assistant Config:
Wiring Schematic:

Follow me on Twitter: @TheHookUp1
Support my channel:

Music by

Related Posts