ESP8266 WLED Hardware Experimentation Platform

by Maxosyack in Circuits > Electronics

834 Views, 2 Favorites, 0 Comments

ESP8266 WLED Hardware Experimentation Platform

00_all.jpg

Yes, yet another WLED controller ! This one focuses on setting up basic hardware features for those who don't like to only rely on WiFi remote (I am one of those).

It is mainly based on LOLIN D1 eco-system for KISS but still DIY. The CPU is the cheap ESP8266 and implemented features are:

  • 1 button (On/Off cycle, random color, WiFi reset, factory reset)
  • 1 potentiometer (global brightness)
  • 1 relay control (Switch LEDs power supply)
  • 1 infrared remote control (recall presets)
  • On device graphic user interface

Each feature is independent, you can use (or not) any of them.

The on-device user interface is composed of an OLED display and a rotary encoder. This feature is quite advanced as it requires compiling WLED with existing usermods and custom build optimizations.

Combined, theses features uses all available pins on the EPS8266. With certain that must use hardware resources of the CPU, versatile ones, like button, are set with a non-intuitive configuration.

Choices are explained in each sections and links to external resources are provided in order to give a sort of yellow brick road trough the Land of Oz main documentation.

Supplies

20231115_202018.jpg
20231115_202247.jpg
20231119_164310.jpg
20231119_164413.jpg
20231115_202144.jpg
20231119_165508.jpg
20231119_165619.jpg
20231119_165949.jpg

Base features supplies :

For button option :

  • 1x momentary button (ex: PBS-33B)

For potentiometer option :

  • 1x potentiometer 50kΩ (or 10kΩ)
  • 2x resistances : 2.7kΩ (or 560Ω)

For relay control option :

For infrared Remote Control option :

  • 1x IR receiver KY-022 module
  • 1x Infrared remote (I use the remote control of my DVD player)

For local graphic user interface option :

  • 1x Rotary encoder KY-040 module
  • 1x OLED display (I use I2C SSD1306 controller 128X64) or any of the compatible OLED display

Installing WLED

The first thing to do is to program the ESP8266 with the WLED firmware. No need to say more than the programming documentation. For the D1-mini use WLED_0.x.x_ESP8266.bin as explained in the What binary should I use? section.

Next connect to the WLED-AP using the default password wled1234 to make your board connect to your Wifi as explaind in the getting started guide.

My advice is to read a bit of hardware description of the ESP8266 like this concise WeMos D1 Mini Pinout Reference before going deeper in hardware features.

Base : LED Driver

LED_driver.png
20231118_095407.jpg
LED_data_conf.png

The first prototyping area is populated with de LED driver. The Getting Started Guide was followed. Small space is available so I used a MOS driver for the level shifter because it came in DIL8 package. Compatible Levels Shifters are listed in the official guide, many are DIL14 but SN74LVC2T45 is DIL8. I advise to read this explanation on logic levels compatibility, the Design #4 talks about MOS drivers used as level shifters for driving LED.

This step can be omitted if the first LED is very close to the controller and if the environment is not too noisy (far from switched mode power supplies and from fluorescent tube) but many times it is required.

For driving the LEDs, no surprises I use the D4 pin on the D1-mini : GPIO 2 on the ESP8266, see picture attached. Navigate to the LED setting page for your WLED device or by adding /settings/leds to its' address - for example, https://my-led-device.local/settings/leds.

Powering the LEDs

If your setup is <30 LEDs, you can power them directly from the D1mini's 5V (J5 connector on my diagram). In this case, D1mini can be powered using a phone charger, DC Power Shield or Battery Shield. For Larger setup, a dedicated power supply is mandatory. The tips for powering LED gives almost all the details.

One final tip, if you have a large number of LEDs far away from the controler, it may be interesting to :

  • Use a 12Vdc power adapter with suitable power
  • Power the controler with the 12Vdc power adapter trought the DC Power Shield
  • Sending 3 wires to the remote LEDs
  • 12V (from power adapter)
  • Data out (from J5)
  • Gnd (power adapter)
  • Close to the LEDs : a step-down DC/DC converter with suitable power that generate from the 12V a local and clean 5V

This extra setup will minimize voltage drop in remote locations thus minimizing the wire section.

There is a WLED power calculator to easily chose a good power supply and fuse, depending on your needs.

Button Feature

Button.png
02_button.jpg
Button_conf.png

The middle prototyping area is used to connect one button and and one potentiometer. Buttons are described in the macros section of the documentation.

The button switches the 3.3V to the D8 pin on the bord (GPIO 15 on the ESP8266). It has to be configure as an inverted push button because the D1-mini as an internal pull-down on this pin. See D1-mini's schematics. I don't use the default button location (GPIO0 - D3) because it will be used by IR remote in few steps.

Navigate to the LED setting page for your WLED device or by adding /settings/leds to its' address - for example, https://my-led-device.local/settings/leds to configure the button.

Behavior of the button is configured in the "settings -> Time and Macros" menu. Select preset 0 on short - long - double push to keep default (built-in) actions :

  • short-press: toggle on/off
  • long-press: select random color
  • double-press ?? I don't know (when local graphic user interface is set-up, it displays network information on double click)

Note: Button 0 has also two built-in functions:

  1. Hold it down for >6 seconds and the Wi-Fi settings will be reset to default
  2. Hold it down for >12 seconds and flash memory is erased

It think it is important to have this feature especially if you are considering giving your lamp a gift : you will be able to do a factory reset just before "delivery".

Potentiometer Feature

Potar.png
02_potar.jpg
Potar_conf.png
Macro.png

An intuitive way of driving brightness is to use a potentiometer. It is called analog button in the documentation.

The circuit simply consist of a voltage divider : 3.3V on one end, GND on the other end an finally A0 pin for the middle point of the potentiometer. Follow the documentation to use that analog button for global brightness. But "be aware that wled is configured to turn off when the potentiometer is adjusted to either extreme - both maximum and minimum adjustments". So that's why you can see resistances at each end of the potentiometer on my diagram. I've mounted theses resistances on female socket to easily adjust their values. The documentation takes as example a 10kΩ potentiometer with 750Ω and 500Ω resistances. Because of what I got in stock, I used 50kΩ potentiometer with 2.7kΩ resistances. My diagram shows documentation value and mine in parenthesis.

Navigate to the LED setting page for your WLED device or by adding /settings/leds to its' address - for example, https://my-led-device.local/settings/leds to configure the analog button as Button 1. As you can see I've configured the GPIO to 1 wich is the TX pin but the documentation says "On ESP8266, you can only have a single analog button on pin A0, the pin set in the settings UI is ignored.".

Then configure the button 1 for global brightness in the "settings -> Time and Macros" menu (https://my-led-device.local/settings/time) : the Short and Long columns set to 0, the Double column in Button Actions to 250.

Relay Feature

Relay_conf.png
20231217_133528.jpg
20231217_133446.jpg
20231217_133510.jpg

Controlling a relay is explained on the Relay Control page of the documentation. The main reason to do it is to prevent unwanted power cosumption from LEDs when they are off by removing power. I have another reason to do so : during power-up sequence, the firsts LEDs may shortly blink white. Switching power (or data line !) suppress that bad behavior.

The default relay pin on the Relay Shield is the GPIO5 - D1 but it will be used by I2C_SCL on my design so I've used GPIO16 - D0 for this feature. I encourage you to buy a genuine relay control shield, you will be able to select the correct pin to drive the relay by a simple cut and solder operation. Because I like to increase delivery efficiency when I buy things on the Internet, I have bought a clone one with other non D1-mini stuffs. This v1.0 shield do not have the "quick configuration" option.

To modify your clone shield (see pictures attached) :

  • Cut the track on the bottom layer : at the top right of "S" of the silkscreen "Shield"
  • Cut the track on the top layer : between "RX" et "D1" silkscreen
  • Solder one wire : from D0 pin to the resistor pad near the "TX" silkscreen
  • Solder one wire : from D0 pin to the LED located near the relay connector, + side

I encounter some EMC issues with this modification (unexpected switching of the LEDs). So again, I encourage you to buy a genuine board for this feature OR, to keep the default pin but then, you will not be able to use the local graphic interface.

When your board is ready to use, plug it on top of the middle prototyping area.

Navigate to the LED setting page for your WLED device or by adding /settings/leds to its' address - for example, https://my-led-device.local/settings/leds to configure the relay feature. As said in the documentation : "Many relays are powered when the signal is LOW" so do my relay board and therefore configured as "inverted". GPIO16 (D0) on my case or GPIO5 (D1) for the non modified board.

Infrared Remote Control Feature

IR_module.png
04_IR.jpg
Ir_conf.png
20240131_143007.jpg

Using an infrared remote is described in the Remote Control section of the documentation. You can dedicate a remote to this or use the unused buttons on other remote (I use my DVD player remote).

Warning : IR receiving will not work on ESP8266 if you use any LED pin other than GPIO 1, 2, or 3 for digital LED strips.

Binding a button with a function is done editing the "ir.json" file. It is explained on the JSON Infrared page. After planning what action on which button, the steps are :

Getting each button's code :

To do this, connect your ESP8266 to a computer and open Arduino or VSCode serial monitor. Then press each button and record the code printed on the serial monitor (default baud rate is 115200). You should see something like this:

IR recv
0xFFDE10

You should get a 24-bit hex encoded integer. If you get 0xFFFFFFFF, that means the button has been pressed repeatedly or held down. Try tapping quickly.

If for the same button you get different values (my old TV remote does), perhaps your remote is using a security layer like rolling code. Those remote will not be usable by WLED.

Writing the appropriated command :

For basic commands, use the HTTP API

For advanced commands, use the JSON API

I have attached a simple ir.json example. You can find more on the online documentation.

Downloads

On-device User Interface Feature

OLED.png
05_GUI.jpg
platformio_override.png
UserMod_conf_1.png
UserMod_conf_2.png
UserMod_conf_3.png

First of all, you'll need a dev environment, follow the instructions in the compiling guide. Use PlatformIO to use the attached configuration file. As I will not do code modifications, I'll use the last release instead of the master branch. In November 2023 it is the WLED-0.14.0. Download the source and go on with the instructions Compilation guide (PlatformIO) to compile with the d1_mini environment and verify that your ESP8266 can be program this way, with no modifications.

Okay, now you have compile WLED ? Program the CPU with your fresh bin file ? You are ready to customise the build environment using the "platformio_override.ini" file.

In the "usermods" folder of the source code, you will find several non-standard features to extend your LEDs controller capabilities. To add a usermod, carefully read its documentation but be aware that their manual are not always up to date. Two mods caught my attention :

  • usermod_v2_four_line_display_ALT
  • usermod_v2_rotary_encoder_ui_ALT

the description said "Provides a four line display using either 128x32 or 128x64 OLED displays. It can operate independently, but starts to provide a relatively complete on-device UI when paired with the Rotary Encoder UI usermod.". Sounds good, even better with the demo vidéo.

It is important to use the ALT version of the 2 usermods as non-ALT display seems not maintained.


First try : If you just add the 2 usermods and your "platformio_override.ini" file looks like this :

[platformio]
default_envs = d1_mini

[env:d1_mini]
board = d1_mini
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
upload_speed = 921600
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags =
${common.build_flags_esp8266}
-D WLED_RELEASE_NAME=esp8266_display_rotary
-D USE_ALT_DISPlAY
-D USERMOD_FOUR_LINE_DISPLAY
-D USERMOD_ROTARY_ENCODER_UI
monitor_filters = esp8266_exception_decoder

lib_deps = ${esp8266.lib_deps}
olikraus/U8g2 @ ^2.35.5

Compile and you will get the following error : .platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld: .pio/build/d1_mini/firmware.elf section `.text1' will not fit in region `iram1_0_seg'.

The program does not fit into IRAM, but what is that ? IRAM stands for Instruction RAM, it is a place (in RAM) where the instructions are stored for execution. Remenber that ESP8266 is a CPU, not a µC (microcontroller). µC have the amazing ability to execute their program directly from the flash storage whereas CPU have to cache them into a specific RAM region. Remember the L1, L2, L3 cache size of your computer's CPU datasheet ? The larger, the better but also the more expensive.

I see two ways to fit ESP8266's IRAM specification :

  1. Remove features to decrease code size
  2. Increase IRAM size


Second try : Disable several unused features and your "platformio_override.ini" file looks now like this :

Second try : I remove features that I dont use, mio]
default_envs = d1_mini

[env:d1_mini]
board = d1_mini
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
upload_speed = 921600
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags =
${common.build_flags_esp8266}
-D WLED_RELEASE_NAME=esp8266_display_rotary
-D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE
-D WLED_DISABLE_HUESYNC
-D WLED_DISABLE_LOXONE
-D WLED_DISABLE_MQTT
-D WLED_DISABLE_ALEXA
-D USE_ALT_DISPlAY
-D USERMOD_FOUR_LINE_DISPLAY
-D USERMOD_ROTARY_ENCODER_UI
monitor_filters = esp8266_exception_decoder

lib_deps = ${esp8266.lib_deps}
olikraus/U8g2 @ ^2.35.5optimisations to fit ESP826Detailed information on IRAM optimisation can be found here

But still the same error so after a dig on the Internet I found a post explaining exactly what I need. Also this page is useful to understand what are the various RAM areas in ESP8266.


Last try : Expand IRAM size and your "platformio_override.ini" file looks now like this :

[platformio]
default_envs = d1_mini

[env:d1_mini]
board = d1_mini
platform = ${common.platform_wled_default}
platform_packages = ${common.platform_packages}
upload_speed = 921600
board_build.ldscript = ${common.ldscript_4m1m}
build_unflags = ${common.build_unflags}
build_flags =
${common.build_flags_esp8266}
-D WLED_RELEASE_NAME=esp8266_display_rotary
-D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE
-D WLED_DISABLE_HUESYNC
-D WLED_DISABLE_LOXONE
-D WLED_DISABLE_MQTT
-D WLED_DISABLE_ALEXA
-D USERMOD_AUTO_SAVE -D AUTOSAVE_PRESET_NUM=100
-D USE_ALT_DISPlAY
-D USERMOD_FOUR_LINE_DISPLAY
-D USERMOD_ROTARY_ENCODER_UI
-D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48
monitor_filters = esp8266_exception_decoder

lib_deps = ${esp8266.lib_deps}
olikraus/U8g2 @ ^2.35.5

And the compilation is done without errors so go on programming your device. You will notice that I have add the AUTOSAVE usermod. This is for convenience as it can take time to adjust an effect via the GUI. So the current sate will be automatically be saved as preset 100.


The configuration part :

Time to configure usermods. Navigate to the Usermod Setup page of your WLED device or by adding /settings/um to its' address - for example, https://my-led-device.local/settings/um to configure the usermods features :

Don't forget to configure the "Global I2C GPIOs (HW)" section with the correct lines for SDA and SCL. I don't use GPIO extention but wihtout this configuration, I2C will not be set at startup and OLED display will remain empty.

The result is as expected but... My encoder seems quite buggy : sometimes the encoder run on the other side or, steps are missed. It works as expected when I pull the shaft while rotating it.

Attached my "platformio_override.ini" file, renamed "platformio_override.txt" has ini files are not allowed in Instructables :).

Global Schematic

EasyWLED.png

Attached, the global schematic, remember, the suggested pins are :

  • LED Data : GPIO2 - D4
  • OLED Display
  • I2C_SCL : GPIO5 - D1
  • I2C_SDA : GPIO4 - D2
  • Relay : GPIO5 - D1 but it is used by I2C_SCL on my design, so I used GPIO16 - D0
  • IR remote : GPIO4 - D2 but it is used by I2C_SDA on my design, so I used GPIO0 - D3
  • Button : GPIO0 - D3 but it is used by IR remote on my design so I used GPIO15 - D8 which is pulled down in DI-mini

So, without the local GUI, you can use all the suggested pin.

Going Further

I have some other ideas for digging a little deeper into WLED features:

  • Sound reactive setup with LedFX, take a look at the exelent tutorial by DrZzs
  • Buy another rotary encoder, to see if it works better
  • Same setup but with ESP32 (I hope pins are compatible)
  • Adding a mic for sound reactive with ESP32
  • housing

Feel free to share other interesting feature to explore.