12V LED PWM Dimmer With ESP8266

Introduction: 12V LED PWM Dimmer With ESP8266

While trying to make my household more sustainable, I was exchanging halogen bulbs for led lights. There are plenty of alternatives available, to replace any type of light bulb. While doing this, I came across the following problem: I had a light fixture which used 7 12 volt halogen bulbs, each 10 Watts. This light was controlled by a dimmer, which worked fine. When I exchanged the bulbs for 12 volt led lights, each 1 Watt, the dimmer worked badly: the light was flickering, and the dimming somewhat erratic. This is a problem with a lot of classical dimmers: they have a minimal power rating, which they need in order to work.

So, based on my domotics system, I decided to exchange this manual dimmer by a new one, which would have the added advantage of being able to be controlled remotely. I had already built a dimmer using a N-channel MOSFET (IRF540), which is perfect for this kind of thing: it can be controlled by a PWM signal, and it is virtually indestructible, with maximum ratings of 100 volts and 33 Amps, amply enough for this purpose (quick check: 7 x 1 Watt = 7 Watts, divided by 12 volts gives a maximum current of about .58 Amps). I want to use this dimmer for another fixture which has 12 bulbs, each 2 watts, which gives a maximum of 2 Amps, so that is also sufficient. The only thing to watch out for it the frequency of the PWM signal, but the usual values for Arduino or ESP8266 (500 Hz or 1kHz) are not a problem.

Step 1: Step 1: the Components

  1. LED Driver (230 volts AC to 12 volts DC converter)
    For my purpose, I want to use a maximum of 24 Watts, so I started out with a LED driver of 12 volts and 2 Amps. I found one at a Chinese distributor site. This driver was rated 12 volts, 28 Watts, so it was sufficient to drive the fixture by itself. For your own situation, you could use a lighter or heavier version, depending on your fixture.
  2. IRF540 n-channel MOSFET
  3. Adafruit Huzzah ESP8266 Breakout
    Because I wanted to use WiFi, and I absolutely love Adafruit's products, I chose this board: it gives me an ESP8266 with a convenient programming pinout, an on-board power regulator, and an elegant form factor. It is a little bit overkill for this project, but it makes testing and debugging much easier.
  4. LM2596 based DC-DC converter
    In order to derive the power for the ESP board from the 12 volt, I needed a regulator; these small converters are very efficient, and very cheap.
  5. Rotary Encoder with button function, with built-in led light:


    Any rotary encoder would do, but I liked the nice added feature of a built-in LED.
  6. Clear plastic knob


  7. Resistor 4k7
  8. Resistor 1k

Step 2: Step 2: the Circuit

This is the circuit I used: I used pins 4 & 5 as inputs for the rotary encoder, and pin 0 for the button. Pin 0 is also connected to the on-board red led, so I could check the function of the button on the encode by watching this led.

Pin 16 is used for the PWM output, and I connected this directly to the green led on the Sparkfun encoder. The ESP8266 is 3,3 volts, and even with 100%, I measured only 2,9 volts output, so I connected it directly without a series resistor. This same output goes to the Gate of the n-channel MOSFET, by way of a 1kOhm resistor.This Gate is pulled high to 12 volts by a 4.7 kOhm resistor.

I used the DC-DC converter to convert the 12 volts to 5.5 volts, this is connected to the V+ input of the Adafruit breakout. I could have used 3.3 volts and connected it directly, but this is a bit safer.

The 12 V LED Lamp in the circuit is my fixture.

Step 3: Step 3: the Code

I put the code on GitHub:

Sketch for ESP8266 LED PWM dimmer

It is based on an idea another instructable:


But this was purely local control, so I added my own MQTT-based domotics solution. It basically does the same thing, but the main differences are:

  • default number of PWM steps with an Arduino is 255, with the ESP8266 it is 1023 (as I found out later, whole trying to figure out why my LED fixture didn't go up all the way to 100% brightness...)
  • I did not use the 'Totempole' circuit with the 2 transistors, since the PWM was DC anyway, and worked fine with the IRF 540.
  • I did not use the 10k pull-up resistors for the encoder, I trusted the built-in pullups of the ESP8266.
  • The ESP8266 uses 3.3 volt logic instead of 5 volt for the Arduino, which proved no problem for the IRF540

The software has the following features:

  • turning the encoder will dim the light up (CW) or down (CCW), from 0 all the way to 100%, in 1023 steps, with some speeding up in the lower levels.
  • pressing the button will turn on the light when it's off, using the last saved brightness level, or turn it off when it's on.
  • pressing the button for a longer time while the light is on will save the current brightness as the default level.
  • pressing the button for a longer time while the light is off will turn the light on to 100% brightness, without changing the default level.
  • It will connect to the WiFi settings defined by the 'SECRET_SSID' and 'SECRET_PASS' strings, which are saved in a separate file in my sketch, called 'secrets.h'
  • It will connect to an MQTT server in the WiFi network, using the 'MQTTSERVER' and 'MQTTPORT' strings in the same file.
  • You can use the MQTT incoming topic 'domus/esp/in' to issue commands: 'ON' or 'OFF" to turn the light on or off, or a value from 0 to 1023 to change the brightness.
  • It will report the state on the MQTT topics 'domus/esp/uit' (ON or OFF status) and 'domus/esp/uit/brightness' (the brightness value).

Be the First to Share


    • Battery Powered Contest

      Battery Powered Contest
    • Plywood Challenge

      Plywood Challenge
    • Plastic Contest

      Plastic Contest

    9 Discussions


    Reply 11 months ago

    No, it does not exceed the rating, from the same datasheet:
    Gate-Source Voltage is (VGS) is ±20V
    But your comment is valid, I will try to make a circuit without the pullup, see how it responds.


    Reply 11 months ago

    ok.. however, the ESP8266 pin 16 is tied to the 12v line, the resistor may provide some protection, but you really shouldn't "pull-up" in that fashion. if you need to pull the signal up to the data voltage, which is 3.3v for an ESP8266 data pin.


    1 year ago

    I made this,works like a charm.
    Only issue I cannot get unit to respond to MQTT ON & OFF commands,can change brightness over MQTT.
    What is the command to turn off and on please ?


    Reply 1 year ago

    The commands are as stated in the sketch: 'ON' and 'OFF' (without quotes, of course) to turn the led on and off, and an integer to set the brightness.


    Reply 1 year ago

    I tried ON and OFF with no response from the ESP8266,brightness setting works well.
    Will look further,thanks for this,is exactly what was looking for.


    Reply 1 year ago

    Thanks for the compliment! This being my first instructable, I wasn't sure what to include: the workings of a dimmer in general, the ESP8266, the code... Do you have any ideas about that? I assume that there is already a lot of tutorials on instructables on all these topics, so I just wanted to focus on the whole project and the path from problem to solution.

    Penolopy Bulnick
    Penolopy Bulnick

    Reply 1 year ago

    Honestly, I would say enough information for someone to reasonable reproduce your project. If you don't want to repeat what others have done, you can always link to other projects too to give people an idea of what they need to do :)