ESP32-S3 Firmware Refinement

I’ll adjust the placement as requested, then remove stale/cut/dead-end traces caused by moving parts and rerun routing/review. I’ll keep J2 and the top-edge parts about 7.3 mm from the top edge, and move RST_SW/BOOT_SW down between the ESP32 and J1.
I’m out of execution credits, so I had to stop after the placement step.
Completed:
  • Moved J2 to the top-left edge area with about 7.3 mm clearance from the board edge.
  • Adjusted the other top-edge components so they keep that same top-edge clearance.
  • Moved RST_SW and BOOT_SW down between the ESP32-S3 module and USB-C connector J1.
  • Preserved the ESP32 antenna orientation facing the bottom edge.
  • Placement now has no overlap or out-of-bounds issues.
Still to do:
  • Delete stale/dead-end traces created by moving components.
  • Re-route the affected nets.
  • Clean up trace paths so they don’t run awkwardly over/through component areas.
  • Rerun review and fix the remaining routing errors, including the USB D+/D− airwires.
Clean reroute traces
Run DRC review
Route USB pair
Check trace crossings

Refine this doc
Ask about this doc
Firmware Starter — ESP32-S3 Relay Controller
Update Summary
  • Refined this starter for ESPHome instead of Arduino/PlatformIO.
  • Added the recommended Apple HomeKit integration path via Home Assistant HomeKit Bridge.
  • Kept the GPIO mapping grounded in the schematic: relay control is on GPIO4, native USB is GPIO19/GPIO20, BOOT is GPIO0, RESET is EN.
Platform & Toolchain
  • MCU/module: ESP32-S3-WROOM-1-N16R8
  • Firmware framework: ESPHome
  • Build/install path: ESPHome Dashboard or ESPHome CLI
  • HomeKit path: ESPHome → Home Assistant → HomeKit Bridge → Apple Home app
  • USB: Native ESP32-S3 USB Serial/JTAG via GPIO19/GPIO20
  • Power note: This board is 12V-powered. USB-C is for data/programming/debug only; do not rely on USB-C to power the board.
Apple HomeKit Architecture
ESPHome devices do not normally pair directly with Apple HomeKit. The stable approach is:
  1. Flash ESPHome to the ESP32-S3.
  2. Add the ESPHome device to Home Assistant.
  3. Enable Home Assistant's HomeKit Bridge integration.
  4. Expose the relay/switch entity to Apple Home.
  5. Pair the HomeKit Bridge QR/code in the Apple Home app.
This gives Apple Home control while keeping ESPHome as the device firmware.
Schematic Pin Mapping

Table


FunctionESP32-S3 PinSchematic NetESPHome EntityDirectionNotes
Relay controlGPIO4RELAY_CTRLrelay_output / relayOutputHIGH energizes relay through R3 → Q1 MOSFET gate; LOW releases relay.
USB D-GPIO19USB_DMUSB serial/JTAGUSBNative ESP32-S3 USB D-.
USB D+GPIO20USB_DPUSB serial/JTAGUSBNative ESP32-S3 USB D+.
Boot buttonGPIO0ESP_BOOTBootloader onlyInput strapHold BOOT low during reset for bootloader/flashing mode. Do not use as a normal HomeKit control.
Reset buttonENESP_ENHardware resetReset/enablePulls EN low to reset ESP32-S3.
Dry contact COMRelay contactRELAY_COM / J3 Pin 1External wiringPassive contactCommon relay contact.
Dry contact NORelay contactRELAY_NO / J3 Pin 2External wiringPassive contactNormally-open contact closes to COM when relay is energized.
Dry contact NCRelay contactRELAY_NC / J3 Pin 3External wiringPassive contactNormally-closed contact opens from COM when relay is energized.
Replace the placeholders for Wi-Fi credentials, API key, OTA password, and fallback AP password before flashing.

Yaml


esphome:
  name: esp32-s3-relay-controller
  friendly_name: ESP32-S3 Relay Controller
  comment: 12V powered dry-contact relay controller for Home Assistant and Apple HomeKit via HomeKit Bridge

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: esp-idf

# USB serial logging over native ESP32-S3 USB Serial/JTAG.
logger:
  level: INFO

# Home Assistant native API. This is what Home Assistant uses to discover/control the device.
api:
  encryption:
    key: "REPLACE_WITH_ESPHOME_API_ENCRYPTION_KEY"

# OTA updates after the first USB flash.
ota:
  - platform: esphome
    password: "REPLACE_WITH_OTA_PASSWORD"

wifi:
  ssid: "REPLACE_WITH_WIFI_SSID"
  password: "REPLACE_WITH_WIFI_PASSWORD"
  ap:
    ssid: "ESP32 Relay Fallback"
    password: "REPLACE_WITH_FALLBACK_AP_PASSWORD"

captive_portal:

# Optional web UI on the local network for quick testing outside Home Assistant.
web_server:
  port: 80

# Relay driver: schematic net RELAY_CTRL, ESP32-S3 GPIO4.
# Hardware behavior: HIGH -> MOSFET on -> relay coil energized -> NO closes to COM.
output:
  - platform: gpio
    id: relay_output
    pin:
      number: GPIO4
      mode: OUTPUT
    inverted: false

switch:
  - platform: output
    name: "Relay"
    id: relay
    output: relay_output
    restore_mode: ALWAYS_OFF
    icon: "mdi:electric-switch"
    device_class: switch

# Useful diagnostics visible in Home Assistant.
sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s
  - platform: uptime
    name: "Uptime"
    update_interval: 60s

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "IP Address"
    ssid:
      name: "Connected SSID"
    mac_address:
      name: "MAC Address"
  - platform: version
    name: "ESPHome Version"

button:
  - platform: restart
    name: "Restart"
Optional: Safer Relay Naming for HomeKit
If this relay controls something safety-sensitive, name it based on the load rather than generically. For example:

Yaml


switch:
  - platform: output
    name: "Gate Trigger"
    id: relay
    output: relay_output
    restore_mode: ALWAYS_OFF
    icon: "mdi:gate"
For a momentary dry-contact trigger, use the template switch below instead of the latching switch: platform: output block.
Optional: Momentary Pulse Mode
Use this if the relay should briefly close a contact, such as a garage/gate/intercom button input. This prevents Apple Home from leaving the relay energized.

Yaml


output:
  - platform: gpio
    id: relay_output
    pin:
      number: GPIO4
      mode: OUTPUT
    inverted: false

switch:
  - platform: template
    name: "Relay Pulse"
    id: relay_pulse
    icon: "mdi:electric-switch"
    optimistic: true
    turn_on_action:
      - output.turn_on: relay_output
      - delay: 500ms
      - output.turn_off: relay_output
      - switch.template.publish:
          id: relay_pulse
          state: OFF
    turn_off_action:
      - output.turn_off: relay_output
First Flash Over USB-C
  1. Apply 12V input power to the board.
  2. Connect USB-C to the computer for data/programming.
  3. If upload does not auto-enter bootloader:
    • Hold BOOT.
    • Tap RESET.
    • Release BOOT.
    • Start the ESPHome install/upload again.
  4. After first flash, future updates can usually be done OTA.
ESPHome CLI Example

Bash


pip install esphome
esphome wizard esp32-s3-relay-controller.yaml
esphome run esp32-s3-relay-controller.yaml
If using the ESPHome Dashboard, create a new ESP32-S3 device, paste the YAML above, validate, then install.
Home Assistant Setup
  1. In Home Assistant, go to Settings → Devices & services.
  2. Add the ESPHome integration if it is not already present.
  3. Adopt or add esp32-s3-relay-controller.
  4. Confirm the switch.relay entity toggles the physical relay.
  5. Rename the entity to the final user-facing name before exposing it to HomeKit.
Apple HomeKit Setup Through Home Assistant
  1. In Home Assistant, go to Settings → Devices & services → Add Integration.
  2. Add HomeKit Bridge.
  3. Choose the domain/entity to expose, usually the relay switch entity only.
  4. Home Assistant will show a pairing code/QR code.
  5. Open the Apple Home app and add the bridge accessory.
  6. The relay will appear in Apple Home as a controllable switch.
Validation Checklist
  • Relay is OFF after boot because restore_mode: ALWAYS_OFF is set.
  • Toggling the ESPHome switch energizes the relay: J3 NO closes to COM, NC opens from COM.
  • Relay drops out after reboot, Wi-Fi reconnect, or firmware update unless intentionally commanded on again.
  • Home Assistant can toggle the relay before it is exposed to Apple Home.
  • Apple Home controls the Home Assistant HomeKit Bridge entity, not a separate direct ESPHome pairing.
Notes / Decisions
  • GPIO0 is reserved for BOOT mode and should not be used as a user button in this firmware.
  • GPIO19/GPIO20 are reserved for native USB and should not be repurposed.
  • restore_mode: ALWAYS_OFF is intentional for a relay dry-contact controller; it avoids unexpected activation after power loss.
  • If the load needs a maintained state after power loss, change restore behavior only after confirming that is safe for the connected equipment.
  • Update Summary

  • Platform & Toolchain

  • Apple HomeKit Architecture

  • Schematic Pin Mapping

  • Recommended ESPHome YAML

  • Optional: Safer Relay Naming for HomeKit

  • Optional: Momentary Pulse Mode

  • First Flash Over USB-C

  • ESPHome CLI Example

  • Home Assistant Setup

  • Apple HomeKit Setup Through Home Assistant

  • Validation Checklist

  • Notes / Decisions

Assets

Assets are files uploaded to this project which can be used in various ways.

ESP32 Relay Controller thumbnail
12V-powered ESP32 relay dry-contact controller with USB-C data-only programming/debug and an onboard 3.3V rail for the ESP32.

Properties

Pricing & Availability

Distributor

Qty 1

Arrow

$4.97–$6.48

Digi-Key

$10.80–$25.53

HQonline

$2.06–$2.17

LCSC

$12.92–$13.40

Mouser

$16.78–$17.24

TME

$3.81

Verical

$3.83–$96.32

Controls