2-Gang Switch
A battery-efficient dual switch using nRF52 that broadcasts both switch states via BTHome. Uses a shared wakeup pin so either switch can wake the device from deep sleep.
Hardware
Section titled “Hardware”- Seeed XIAO BLE (nRF52840)
- 2x Toggle switches or rocker switches
- 2x 1N4148 diodes (for wakeup OR circuit)
- 3.7V LiPo battery
Wiring
Section titled “Wiring”| Component | XIAO Pin |
|---|---|
| Switch 1 | D2 → GND |
| Switch 2 | D3 → GND |
| Wakeup (combined) | D4 |
| Battery+ | BAT+ |
| Battery- | BAT- |
Wiring Diagram
Section titled “Wiring Diagram”graph TD
subgraph XIAO["Seeed XIAO BLE"]
D2["D2 (Pin 2)"]
D3["D3 (Pin 3)"]
D4["D4 (Pin 4)"]
V3["3V3"]
GND["GND"]
end
subgraph Switches
SW1["Switch 1"]
SW2["Switch 2"]
end
subgraph Battery["LiPo Battery"]
BATP["BAT+"]
BATN["BAT-"]
end
SW1 --- D2
SW1 --- GND
SW2 --- D3
SW2 --- GND
Wakeup Circuit
Section titled “Wakeup Circuit”Wire both switch outputs to the wakeup pin using diodes to create an OR gate:
graph LR
subgraph Wakeup["Diode OR Gate"]
D2["D2<br/>(Switch 1)"] --> DIODE1["1N4148<br/>▶|"]
D3["D3<br/>(Switch 2)"] --> DIODE2["1N4148<br/>▶|"]
DIODE1 --> D4["D4<br/>(Wakeup)"]
DIODE2 --> D4
D4 --> R["10kΩ"]
R --> V3["3V3"]
end
style D4 fill:#f96,stroke:#333
style DIODE1 fill:#fff,stroke:#333
style DIODE2 fill:#fff,stroke:#333
When either switch is pressed (pulls to GND), D4 goes LOW and wakes the device.
Configuration
Section titled “Configuration”esphome: name: switch-2gang friendly_name: 2-Gang Switch
nrf52: board: xiao_ble bootloader: adafruit
logger:
external_components: - source: type: git url: https://github.com/dz0ny/esphome-bthome ref: main components: [bthome]
# Battery monitoringsensor: - platform: adc pin: 29 id: battery_voltage name: "Battery Voltage" update_interval: 60s filters: - multiply: 2.0
- platform: template id: battery_percent name: "Battery" unit_of_measurement: "%" lambda: |- float voltage = id(battery_voltage).state; float percent = (voltage - 3.0) / (4.2 - 3.0) * 100.0; if (percent > 100) percent = 100; if (percent < 0) percent = 0; return percent; update_interval: 60s
# Switches on separate pins for individual state readingbinary_sensor: - platform: gpio pin: number: 2 mode: INPUT_PULLUP id: switch_1 name: "Switch 1" filters: - invert: - delayed_on: 10ms - delayed_off: 10ms
- platform: gpio pin: number: 3 mode: INPUT_PULLUP id: switch_2 name: "Switch 2" filters: - invert: - delayed_on: 10ms - delayed_off: 10ms
# BTHome broadcastbthome: min_interval: 5s max_interval: 30s tx_power: 4 sensors: - type: battery id: battery_percent binary_sensors: - type: generic_boolean id: switch_1 advertise_immediately: true - type: generic_boolean id: switch_2 advertise_immediately: true
# Deep sleep - wake on either switch via combined wakeup pindeep_sleep: run_duration: 15s sleep_duration: 5min wakeup_pin: number: 4 mode: INPUT_PULLUP inverted: trueHow It Works
Section titled “How It Works”- Normal operation: Device sleeps, both switches readable on D2/D3
- Either switch pressed: D4 goes LOW via diode OR circuit
- Device wakes: Reads individual switch states from D2 and D3
- Broadcasts: Sends both switch states via BTHome
- Returns to sleep: After
run_durationexpires
Power Consumption
Section titled “Power Consumption”| State | Current |
|---|---|
| Deep sleep | ~3µA |
| Active | ~5mA |
Expected battery life: 6-12 months with 400mAh battery