Room Light Dimmer (WIP)


I read about Amazon Dash button alternatives somewhere. Connect to wifi, send a request, power off.
I wanted a cordless device to talk to a NodeJS server which controls some Lifx lightbulbs so that got things rolling.


This is a rotary encoder (the "volume knob") wired up to an Expressif ESP8266 WiFi SoC. A power button is not pictured, but to power it on means momentarily connecting VCC to EN (CH_PD).

Once powered, I can adjust the volume and tell a server what just happened (e.g. I turned the knob by 5 detented clicks). After a period of inactivity, the device shuts off to save battery.

The Struggle

I have limited experience with this sort of thing. It's slowly getting more accessible for casual hobbyists like me. I am familiar with Lua so I chose not to learn Arduino.

Training Wheels

I started out with a LoLin NodeMCU V3 dev board.

I wanted to use the rotary module but it's not considered a default. I used a cloud service for building the firmware because compiling on Windows leads to headscratching a vast majority of the time (I can't remember what all I tried but the last approach was to use someone's ESP toolchain binaries. It had a dependency on wget.exe, but after that the Makefile failed elsewhere and so I gave up).

Actually flashing was most quirky, requiring two separate flash writes.

I used ESPlorer for serial port operations. I wired a rotary encoder to GPIO via breadboard. The rotary module was very straightforward. I configured the WiFi station login credentials. I got the prototype working to make HTTP requests to echo rotary events, and let the server decide what should happen. No security in place.

Back to the Basics

Using a bare ESP8266 chip would yield less power consumption, which matters because I want to power this with a battery, so good bye NodeMCU V3.

I ordered a FT232RL and a ESP-12E and was convinced that a LiFePo4 battery would make power easy. The cell I bought read 3.33V. It can be safely charged up to 3.6V (and so I did). What I thought was now fully charged read 3.55V. Leaving the cell to rest a day, the voltage then read 3.36V, to my surprise.

I wired up the FT232RL and ESP-12E. Seems IO2 and IO15 need to be tied for stability.

          TXD0 -------------------------------------2
          | RXD0 -----------------------------------3
          | | GPIO4
          | | | GPI05
          | | | | GPIO0 --------------------+
          | | | | | GPIO2                   | ______6
          | | | | | | GPIO15 ----+           /
          | | | | | | | GND -----+----------+
          | | | | | | | |
||     [] o o o o o o o o                               FT232RL USB FTDI (VCC = 3.3V)
||                        o - SCLK                   1
`====, ||                 o - MOSI                   2  TX
,====' ||     ESP8266     o - GPIO10                 3  RX
`====, ||     ESP-12E     o - GPIO9                  4  VCC to CH_PD (EN)
,====' ||                 o - MISO                   5
`======='                 o - CS0                    6  GND  (to GPIO0 when reflashing)
          o o o o o o o o              also to GPIO2
          | | | | | | | |                   |
          | | | | | | | VCC ----------------+
          | | | | | | GPIO13                 \
          | | | | | GPIO12                    \_____4
          | | | | GPIO14                      /
          | | | GPIO16                       /
          | | EN/CH_PD ---------------------+
          | ADC

Flashing the custom NodeMcu .bin plus the default .bin in a single command is required. I tried to do the commands separate as for the NodeMCU dev board, but it failed on the first write command at 99%.

I took a note that in the guide, connecting GPIO0 to VCC after done flashing prevented it from booting, so just leave GPIO0 alone.

I Just Want To Sleep Forever

I thought maybe put the device to sleep rather than shut it off and on, to save power.

I tried several things with regards to waking up after a node.dsleep(0), nothing worked. This got my hopes up. This brought me back to reality, and so I gave up on trying to get RESET working.

I reached out to a respectable internet friend to vent my impotent nerd rage.

I ended up trying to power off via a GPIO pin. It hints at a pullup resistor. I put a(n overkill) 1M resistor between the pin I use to enable/disable, and EN. Initially powering the circuit involves a direct, momentary connection from VCC to EN long enough for the application code to put the GPIO pin high to keep EN high. The app eventually brings the GPIO pin low, so that pulls EN down to power off the device.


An ideal power-on actuation would be more transparent than a separate pushbutton. Is there any way around it to involve only the rotary encoder? Enabling this chip using another is beyond the project's scope.