H-Bridge 2-wire fairy light controller

So, this project was born out of wanting to replace the controller from two sets of these fairy lights.

Partially because I wanted them both to turn on at the same time, and partly because having the stock controller on a z-wave plug seemed to reset the effects back to the ‘demo’ one, which cycled through some seizure-inducing flashing.

Evidently anyone else that has done so hasn’t written it up, or my Google-fu sucked, because I really struggled to find anything I could use as base, other than the example stuff on the ESPHome docs, and a snippet of Red-Green transition lambda code.

I’ll post a bit more about the hardware used and add a wiring diagram later, but the proof of concept on a test set of string lights works a treat - and I’ve managed to bodge together a couple of effects that work for the way ESPHome sees these lights.

Hardware:

Issues:

  • Need to see if there’s a better way to ‘activate’ each string in the strobe effect, rather than color_temperature. Tried cold_white/warm_white but it threw a “Color temperature value 0.00 is out of range (153.0 - 500.0)”. 3500K seems to be close to the mid-point to activate both strings so have been using that as an “all on” value.
  • In the lambda effect, it seems to flicker a little on each cycle.
  • Add some more effects - in particular a ‘twinkle’ where the two sets of lights twinkle at random brightnesses.

ESPHome YAML:

esphome:
  name: "led-strings"
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: !secret wifi_iot_ssid
  password: !secret wifi_iot_password
  ap:
    ssid: $friendly_name Fallback Hotspot
    password: !secret esphome_fallback_ap_password

captive_portal:

logger:

api:
  encryption:
    key: !secret esphome_api_key

ota:
  password: !secret esphome_api_password

output:
  - platform: esp8266_pwm
    id: pina
    pin: GPIO12
  - platform: esp8266_pwm
    id: pinb
    pin: GPIO14

light:
  - platform: hbridge
    id: ledstrings
    name: "led-strings"
    pin_a: pina
    pin_b: pinb
    
    effects:
      - strobe:
          name: "Flash A-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
      - strobe:
          name: "Flash A-AB-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
      - lambda:
          name: "Fade A-AB-B 10s"
          update_interval: 10s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(10000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.0);
            } else if (state ==1) {
              call.set_warm_white(0.0);
              call.set_cold_white(1.0);
            }
            call.perform();
            state += 1;
            if (state == 2)
              state = 0;
2 Likes

Hi @KablammoNick - this is excellent timing - I’ve just got my hbridge driver working myself, and so the effects are great to add in!
Just one question though - do your lights glitch? It’s really noticeable on my system…

Yeah, doesn’t seem to be as noticeable on the effects I’ve got there, but when manually changing colour temp or brightness they glitch/flash a little.
Messing around trying to DIY a “twinkle” effect it does the same, so about all I’ve got is what’s up there at the moment.
Happy to test any you’ve got though.

I agree, Googling for this info is quite hard so I appreciate you doing a write up of it.
@KablammoNick are you able to add the wiring diagram and/or real photos of the hardware all set up?

Below are some of my finding on this topic:
Hanson Electronics sells a DMX2-24 piece of hardware that seems to allow you to control these 2 wire LED fairy lights. It uses DMX instead of ESPHome. DMX can be controlled through HA though.
More interestingly though is in the manual he explains more about the Multifunction modes.

  1. Combination cycles through the 7 actual modes
  2. In Waves toggles 1 half followed by other at about 5hz
  3. Sequential toggles 1 half followed by other half at about 1hz
  4. “Slo Glo” ramps 1 half up then down followed by the other. about 5s up, 5s down
  5. Chasing /Flash toggles 1 half followed by the other half about 3 times at 5hz followed by 1 half flashing 3 times
    at 5 hz then the other 3 times.
  6. Slow Fade ramps all up followed by all down. about 5s each way
  7. Twinkle / Flash flashes 1 half twice then other half twice
  8. Steady On lights on 100%

You can get a smart controller that replaces the stock controller. It’s tuya based and says that it works on most lights 31-33V 8.4W or less. So for your long lights it likely wouldn’t work.

With wiring it up you could get a fairy light female pigtail meaning you wouldn’t have to chop off the end of your existing lights.

Would it work with other ESP’s such as a ESP32 dev board or ESP32-C3?
Did you just pick a power supply with the same amps and volts as your stock controller?

1 Like

Years ago I looked into trying to flash a similar set of lights from Aussie KMart which were running an ESP (back in the Tuya-Convert days) but since I couldn’t figure out a suitable ESPhome config for them the project went stale. I’ll have to have another crack at it with what you have here. My main concern was with trying to get decent effects similar to the standard ones out of the box. The main difference I se with the ones I have is that they have multiple colours effects.

They are like the ones in this Christmas tree set.

Here is the original thread about them.

The ambient heat outside got to the adhesive that was holding the wago connectors onto the outside of the case, so it’s a bit of a mess but:



Not sure how best to draw a wiring diagram but hopefully the pictures help.
Orange and Yellow wires are on D5 + D6, and the White issnuck in on GND. Terrible colour choice but this was ‘temporary’ for testing - but has been going fine so far so haven’t bothered getting back up to tidy up.

I did find those - funnily enough from my original thread on AusChristmasLighting. They were the backup ‘throw money at it’ solution, but felt like overkill for a single string.
Interesting to see the modes in the manual - if I get some spare time I might see if I can recreate them in ESPHome.

Interesting, didn’t see them at all in my searching - Tuya based so possibly even flashable with ESPHome depending on how long the production run was - might get lucky and they’re older chips.
Agreed it might not be enough - I can’t measure the actual power usage of these but the original bricks are 12w.

I’ve got a feeling those weren’t quite right sizing but ended up just chopping the lights and using a couple of the threeway wago’s.

I assume it would be fine with other ESP’s, but I don’t know enough to say with certainty.

The PSU is variable voltage, adjusted it to 31v. I can’t remember why I ended up with 8A, given from a quick re-calculation that’s ~240w so well and truly overkill. Quite possibly because there was buggerall cost difference and figured if I wanted to use it for more strings then it was good to go.

Yeah wow, I think adding RGB would be a huge step up in complexity if starting from scratch - not only for the ESP but the effects.

Thanks for the great extra info. Seems like enough details for me to have a crack at it. I also found Jaycar has a write-up on a method of using these sort of 2-wire lights with an Arduino UNO. Jaycar-Electronics/Christmas-Light-Controller: Lost your power supply or light controller? (github.com)

I did ended up buying the Tuya smart controller. It’s actually pretty good. I’ve opened a PR to get it supported in Tuya Local: Add support for 8 Functions String Light Control Adaptor by BenJamesAndo · Pull Request #1630 · make-all/tuya-local (github.com). More info about the device can be found there. I might end up flashing it to ESPHome, although replicating all the functionality it exposes with Tuya already would be quite challenging, but likely possible. I reckon though the 8 modes could definitely be improved with ESPHome, such as Slow-Glo. It would be nice if it didn’t fade all the way off and on again, but instead faded down to 5% and then up.

1 Like

Is using an H-bridge to control LED’s a new thing? It makes sense now that i think about it, its just 4 Fets in there. IDK how ive never heard of people doing this before.

What are the pros and cons for using this vs. a 4 channel mosfet module?

TBH no idea. I came across it whilst googling how to replace the controller & power supply with something that used ESPHome and just ran with that.

Looks like it was added to ESPHome in Version 1.16.0 back in Feb 2021 - by someone that was looking to control Christmas lights too.
I suspect the lights he refers to used to use ESP chips that were flashable, whereas now most of the Mirabella ones available here use ?BK or the other not easily flashable ones.

… and no idea about these vs mosfets sorry!

Hrmm. I will try and have a play this afternoon - will probably have to wait until its dark to test properly.
Thinking just use fade A-AB-B but the crossover would be at say 0.1 instead of 0.0.

Couldn’t help myself…

2 seconds to transition, no hold between the cycle, “down” to a value of 0.2 as 0.1 seemed too dull but it’s the middle of the day here so will test again tonight.

      - lambda:
          name: "Slow-Glo | Fade A-AB-B 2s 0.2"
          update_interval: 2s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(2000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.2);
            } else if (state ==1) {
              call.set_warm_white(0.2);
              call.set_cold_white(1.0);
            }
            call.perform();
            state ++;
            if (state == 2)
              state = 0;

I remember seeing this now.

Ive jusr never considered using an H-bridge since ive always used these.
https://www.amazon.com/3-7-27VDC-4-Channel-Driver-Amplifier-Circuit/dp/B07QGXY7F3/ref=asc_df_B07QGXY7F3/?tag=hyprod-20&linkCode=df0&hvadid=459440176747&hvpos=&hvnetw=g&hvrand=3589419955251698302&hvpone=&hvptwo=&hvqmt=&hvdev=m&hvdvcmdl=&hvlocint=&hvlocphy=9016042&hvtargid=pla-949854341482&psc=1&mcid=bb66a86754773c29b93c2f1c45f78d3b&gclid=CjwKCAiA2pyuBhBKEiwApLaIO3FvSJCBN2KJyNu56ETVOqKq5_RmF_7nB_XtWfcTMvPtoOPvaMV8uBoC68AQAvD_BwE

I gueas my curiosity is about chiosing one over the other? I dont think its just me but, h-bridges are usually associated with driving motors. I get that its the same process to drive a motor and drive led’s. Its just interesting to me i guess.

These can now be flashed with ESPhome as well though.

I’ve got a feeling when I last looked, it required opening them up which was difficult to do non-destructively. That or it could be done with tuya-cloudcutter first but needed a setup beyond what I had readily available.

Might have to look into that again too though - these are pretty neat as spare room lights.

You know you can get smart bulbs with esphome pre-flashed right? Or is it just the shape of this that you like?

Yeah it’s the shape for these, in a location without a shade - got a handful of Hue, Wiz and ESPhome flashed bulbs elsewhere in the house

Finally remembered to film at night… although the iPhone camera tries to correct the darkness.

1 Like

I managed to get the Tuya 2-wire controller flashed with ESPHome. It uses a Beken chip. None of the Cloud-Cutter profiles worked but I was able to get it working without soldering using Tuya-Cloudcutter Lightleak. I wish I knew about Lightleak before I used a rotary tool to open it up haha. It’s now officially supported in Cloud-Cutter see Lexi String Light Controller · Issue #629 · tuya-cloudcutter/tuya-cloudcutter (github.com)
Thanks so much to your ESPHome code I was able to quickly get it working. The scenes you made look really nice!
Here’s my modified YAML.

esphome:
  name: lexi-controller
  on_boot:
      priority: 600
      then:
        - light.turn_on:
            id: ledstrings
            brightness: 100%
            color_temperature: 4268K

bk72xx:
  board: generic-bk7231t-qfn32-tuya

logger:

web_server:

captive_portal:

mdns:

api:
  password: ""

ota:
  password: ""

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:

output:
  - platform: libretiny_pwm
    id: pina
    pin: P24
  - platform: libretiny_pwm
    id: pinb
    pin: P26

binary_sensor:
  - platform: gpio
    id: binary_switch_1
    pin:
      number: P8
      inverted: true
      mode: INPUT_PULLUP
    on_press:
      then:
        - light.toggle: ledstrings

light:
  - platform: status_led
    id: stat_led
    name: "Switch state"
    pin:
      number: P7
  - platform: hbridge
    id: ledstrings
    name: "led-strings"
    pin_a: pina
    pin_b: pinb
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
    - light.turn_on: stat_led
    on_turn_off:
    - light.turn_off: stat_led
    effects:
      - strobe:
          name: "Flash A-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
      - strobe:
          name: "Flash A-AB-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
      - lambda:
          name: "Fade A-AB-B 10s"
          update_interval: 10s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(10000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.0);
            } else if (state ==1) {
              call.set_warm_white(0.0);
              call.set_cold_white(1.0);
            }
            call.perform();
            state += 1;
            if (state == 2)
              state = 0;
      - lambda:
          name: "Slow-Glo | Fade A-AB-B 2s 0.2"
          update_interval: 2s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(2000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.2);
            } else if (state ==1) {
              call.set_warm_white(0.2);
              call.set_cold_white(1.0);
            }
            call.perform();
            state ++;
            if (state == 2)
              state = 0;
1 Like

Hello there! I followed the tips in the first post (Thanks @KablammoNick) and managed to make my LED strip light up.

But I noticed that it kept “flickering” a lot. I did some setup assembly tests (I’ll add pictures below) and in some cases it improved, in others it got worse.

First: Along with the LED control functions, I tried to implement a Bluetooth Proxy. I noticed that with it, the LEDs flickered more, so I removed it from my ESPHome programming and it improved a little. (But it could also be a placebo).

Since I was initially powering the LEDs with the 5V from my development board, I thought it could be a lack of power or something like that, so I connected it to an external power supply. Then things got even worse. The LEDs kept blinking and now they’re very weak.

Below I’ll illustrate with pictures, please ignore the colors of the wires, as this is a temporary assembly.


Here, the LEDs and power supply are connected directly by the development board.
The purple and white wires are pinA and pinB that go to the L298N control board. The green wire is 5V and the blue wire is GND.

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
Here is the L298N board, receiving 5V in the 12V input, GND from GND and the wires from the ESP pins (yes, the colors are different because the cables were spliced)

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
In this connection case, I have this result on the LED strip. Notice how bright the lights are.

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
Now, I changed the power supply of the L298N board to an external power supply, connected directly to a powerful USB source (which even delivered more voltage than the ESP board). Notice how the LEDs are off, weak, brigthless.

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
When I went to disconnect the external source again, I noticed that when I touched the heat sink, creating a grounding, the LEDs lit up brighter.

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
But not as bright as if they were connected directly to the development board.

(I had to remove the image because new users can only post one image per post. Why?! :roll_eyes:)
So I reconnected the power supply to the ESP32 development board, and here is a short video of the LEDs flickering.

I just noticed, after completely rereading the topic, that the noble colleague made a connection from the ESP32 GND to the L298N board GND even when using separate sources. This would possibly improve the case of weak LEDs. But would it also solve the flashing LEDs?

PS: The LED strip I bought was originally connected to USB, with a manual on/off control and some effects, but without Wi-Fi, without Bluetooth, very simple. That’s why I’m connecting it directly with USB power.

This is my ESPHome code

esphome:
  name: luzinhas
  friendly_name: Luzinhas
  project:
    name: "jrmania.fairylights"
    version: "1.0.0"

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "****"

ota:
  - platform: esphome
    password: "****"

wifi:
  networks:
  - ssid: !secret wifi_ssid
    password: !secret wifi_password
    
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Safe Fallback"
    password: !secret router_password

captive_portal:

web_server:
  port: 80
  version: 3
  ota: true
  auth:
    username: !secret router_user
    password: !secret router_password

#EXTRA SENSORS
sensor:
  - platform: internal_temperature # Reports the interna temperature of the board
    name: "Temperatura interna"

  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: "Sinal WiFi (dB)"
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"

  - platform: copy # Reports the WiFi signal strength in %
    source_id: wifi_signal_db
    name: "Sinal WiFi (%)"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"

text_sensor:
  - platform: version
    name: "ESPHome Version"
  - platform: wifi_info
    ip_address:
      name: ESP IP Address
    ssid:
      name: ESP Connected SSID
    mac_address:
      name: ESP Mac Wifi Address
    dns_address:
      name: ESP DNS Address

#Lights control
output:
  - platform: ledc
    id: pinA
    pin: GPIO26

  - platform: ledc
    id: pinB
    pin: GPIO14

light:
  - platform: hbridge
    id: ledstrings
    name: "Luzinhas"
    pin_a: pinA
    pin_b: pinB
    restore_mode: ALWAYS_OFF
    
    effects:
      - strobe:
          name: "Flash A-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
      - strobe:
          name: "Flash A-AB-B 500ms"
          colors:
            - state: true
              color_temperature: 2000 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
            - state: true
              color_temperature: 6534 K
              duration: 500ms
            - state: true
              color_temperature: 3500 K
              duration: 500ms
      - lambda:
          name: "Fade A-AB-B 10s"
          update_interval: 10s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(10000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.0);
            } else if (state ==1) {
              call.set_warm_white(0.0);
              call.set_cold_white(1.0);
            }
            call.perform();
            state += 1;
            if (state == 2)
              state = 0;
      - lambda:
          name: "Slow-Glo | Fade A-AB-B 2s 0.2"
          update_interval: 2s
          lambda: |-
            static int state = 0;
            auto call = id(ledstrings).make_call();
            call.set_transition_length(2000);
            if (state == 0) {
              call.set_warm_white(1.0);
              call.set_cold_white(0.2);
            } else if (state ==1) {
              call.set_warm_white(0.2);
              call.set_cold_white(1.0);
            }
            call.perform();
            state ++;
            if (state == 2)
              state = 0;
2 Likes

Complementing my previous post

The USB power supply that I used to power the LEDs has two USB-A outputs, so I connected the ESP32 to one output and the LED strip to another, and with this way the LEDs light up at maximum power.

I also tested with the ESP32’s GND connected to the L298N board (using different power sources) and the LEDs also have maximum power.

I believe this situation has been resolved. But the LEDs “flickering” continues (even without using the effects).

I have the impression that the flicker occurs when the processor “loop” restarts. I don’t know if it makes sense, but it seems to be that way.

Any tips for solving this problem?

EDIT: I tested it with the fan’s h-bridge component, and although the two LEDs with different polarities did not light up at the same time, the lights did not flicker.

Good news!!!

With a few “commands” I was able to drastically reduce the “flickering” of the LEDs. It didn’t solve the problem 100%, but it’s acceptable now.

The first thing I did was to remove all other functions from my application, leaving only the LED control and a button to control the LEDS physically. I removed the webserver, monitored sensors (like wifi, ip, internal temperature, etc), and other items.

But what really helped A LOT in stabilizing the LEDs was disabling the logger. Surprisingly, a simple # (comment) in the function solved 85% of the blinking. So for anyone facing the same problem, this may be the solution.

2 Likes