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).