Summary
I am documenting my (successful) attempt to make a Benfei USB switch smart by adding an embedded ESP32 S3 zero board. This is because I found zero information about this device on the web, and it might help someone in the future.
Background
I wanted to be able to use Home Assistant to switch my keyboard and mouse between 2 pc's.
But I wanted to be able to control this via Home Assistant so I could make it switch at the same time as I used it to switch my monitor input between the same 2 PCs, so I could have a smart KVM without spending the money on a proper one, and without losing my lovely 4k 144Hz capability.
I did some googling and I saw that folk had successfully added a ESP32 to generic, cheap USB switches.
So I took a punt on a Benfi one, ensuring that it had a remote control and optional external power, should they be needed for the project (they werent).
The one I bought was
https://amazon.co.uk/dp/B0DGFC4MWK
It was less than £20 so even if I broke it, and failed, it wouldnt be a huge loss, and I would have learnt something.
Investigation
I could find no teardowns or documentation on the web for this device (or any similar device),so I popped it open (after testing it worked), and got my multimeter out:
I was searching for a way to
a) toggle inputs
b) detect current input
c) power the ESP32 S3
so I could reliably tell home assistant to "select input 1" or "select input 2"
So I needed a way to detect which LED was lit up, and to press the button.
What I found
a) toggle inputs
The button was surface mount, but had nice big pads, so soldering to them was easy. A bit of probing proved that the pads on the bottom of the image above were ground, and the ones at the top were the input to the controller on board (u4). (there are 2 pairs of joined together pins on these switches)
It operated by normally having +5v on the signal side, which was pulled to ground when the button was pressed.
Easy.
b) detect current input
I initially planned to tap the LEDs themselves (or one of them, since if 1 is on, 2 is off), but when I saw the surface mount pads, I no'ped right out, they are tiny, and beyond my soldering ability.
So I probed the main microcontroller, and played, and discovered that the pins already provided what I needed. I found the 8 pins on the chip are
1. Unsure, +5v all the time, probably the chip power input
2. Unsure, +5v all the time, probably the power for the actual switching chip
3. The currently selected output (output 1, high +5v, output 2, low, 0v or the other way round). I think this is what goes to the actual switching chip to select output. This was the one to tap :)
4. Connected to the push button via a resistor. Easier to solder to the actual button
5. Ground
6. LED output 1
7. LED output 2
8. Ground
c) power for the ESP32
This turned out to be the hardest part. I was hoping to tap off one of the large capacitors, but one only had 5v if port 1 was connected to a PC and the other never had 5v at all (maybe for the external power input?).
I considered tapping from the +5v on the U4 chip, but there were 2 of them, and I was unsure if it had enough capability to power a wifi esp32
So I ended up tapping the 2 PC usb connections, via a pair of diodes to get my +5v
The design
I used Claude to help design the actual circuit to do this, and it came up with. I didnt include the cap.
The build
I dont have the capability to fab my own PCBs so it was a bit of a bodge job. I didnt want to build it as a rats nest, with diodes etc inline with the wires, but that might have been a better choice.
I instead build the 3 component parts onto tiny 3x3 pieces of stripboard, then used wires to join it all up.
I used velcro sticky pads to position and hold the ESP32 board itself to the space on the devices PCB, and off-cuts of these to insulate the PCB to stick my 3 bodge boards to it using hot glue.
I then soldered it all together.
The reassembly
It was a very tight fit. If it was doing this again I would take more care about vertical space within the enclosure :)
But I did get it back together and it worked.
The software
I used ESPHome to drive it, and it was a simple YAML that published the following:
Here is the ESPHome YAML code:
# Board: Waveshare ESP32-S3-Zero (Waveshare)
# Definition: definitions/boards/waveshare_esp32_s3_zero/manifest.yaml
esphome:
name: benfei
friendly_name: Benfei
esp32:
variant: esp32s3
flash_size: 4MB
framework:
type: esp-idf
advanced:
enable_ota_rollback: true
logger:
api:
encryption:
key: "(REDACTED)"
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: Benfei Fallback Hotspot
password: "(REDACTED)"
captive_portal:
# GPIO2 -> 1N5819 (band towards ESP) -> K1 top pad. Open-drain: driving low presses the button,
# released (high-Z) leaves it alone. Inverted so "on" = pressed.
output:
- platform: gpio
id: press_output
pin:
number: GPIO2
inverted: true
mode:
output: true
open_drain: true
button:
- platform: output
id: toggle_input
name: "Toggle Input"
output: press_output
duration: 200ms
- platform: template
name: "Select Input 1"
on_press:
- script.execute:
id: select_input
want_input1: true
- platform: template
name: "Select Input 2"
on_press:
- script.execute:
id: select_input
want_input1: false
# Only toggles if the switch isn't already on the wanted input. Mode single plus the settle
# delay stops back-to-back calls from double-toggling before GPIO1 has caught up.
script:
- id: select_input
mode: single
parameters:
want_input1: bool
then:
- if:
condition:
lambda: return id(input1_selected).state != want_input1;
then:
- button.press: toggle_input
- delay: 500ms
# GPIO1 <- 3k <- 1N5819 (band towards U4) <- U4 select line. High = input 1, low = input 2.
binary_sensor:
- platform: gpio
id: input1_selected
name: "Input 1 Selected"
internal: true
pin:
number: GPIO1
mode:
input: true
pullup: true
text_sensor:
- platform: template
name: "Active Input"
update_interval: 1s
lambda: |-
return std::string(id(input1_selected).state ? "Input 1" : "Input 2");
Comments
Post a Comment