Community project

Schematik Project Blueprint Smart Power Pedestal

ESP32
Photo of Schematik Project Blueprint Smart Power Pedestal
Generated with AI

George Zardavas

Last updated August 24, 2026

This project builds a smart power pedestal controller using an ESP32 microcontroller and a 30 A latching relay to remotely switch power on and off. The dual-coil relay design requires minimal holding current, making it ideal for battery-powered or always-on monitoring applications. The system includes a watchdog timer that automatically cuts power if the ESP32 stops sending heartbeat signals, providing a safety mechanism for unattended equipment.

The guide provides a complete wiring diagram, parts list, and step-by-step assembly instructions starting with low-voltage testing before any AC power connections. Builders will receive the full firmware code for relay control via serial commands, including the UNLOCK, LOCK, and HEARTBEAT logic that manages the power state and safety timeout. The modular design allows the relay driver to be adapted for various desk-based power distribution or remote shutdown applications.

Wiring diagram

Wiring diagram for Schematik Project Blueprint Smart Power Pedestal

Gather all the parts

QtyComponent
1

30 A 5 V dual-coil latching power relay

5 V coil, 30 A contacts

A dual-coil relay that switches the pedestal power contact and consumes power only during a short set or reset pulse.

1

AO3400A

AO3400A

30V 5.7A N-channel enhancement-mode logic-level MOSFET in SOT-23-3L. Vgs(th) typically ~0.7V (max 1.45V at Id=250 uA), fully enhanced at Vgs=2.5V-4.5V. RDS(on) ~26 mOhm at Vgs=4.5V, ~38 mOhm at Vgs=2.5V. Driven directly by 3.3V or 5V microcontroller GPIO/PWM as a low-side switch for loads up to its Id and VDS limits. No firmware library required.

1

AO3400A

AO3400A

30V 5.7A N-channel enhancement-mode logic-level MOSFET in SOT-23-3L. Vgs(th) typically ~0.7V (max 1.45V at Id=250 uA), fully enhanced at Vgs=2.5V-4.5V. RDS(on) ~26 mOhm at Vgs=4.5V, ~38 mOhm at Vgs=2.5V. Driven directly by 3.3V or 5V microcontroller GPIO/PWM as a low-side switch for loads up to its Id and VDS limits. No firmware library required.

1

1N4007 Diode

1N4007

General-purpose silicon rectifier diode in DO-204AL (DO-41) axial through-hole package. Rated 1A average forward current and 1000V peak reverse voltage (VRRM). Forward voltage drop ~0.7V at typical load (up to 1.1V at full 1A). Used here in series with LM7805 Vout for reverse polarity protection: anode to LM7805 output, cathode to 5V rail, resulting in ~4.3V on the output rail. Not suitable for high-frequency switching (reverse recovery ~2µs–30µs); intended for DC or 50/60Hz rectification only.

1

1N4007 Diode

1N4007

General-purpose silicon rectifier diode in DO-204AL (DO-41) axial through-hole package. Rated 1A average forward current and 1000V peak reverse voltage (VRRM). Forward voltage drop ~0.7V at typical load (up to 1.1V at full 1A). Used here in series with LM7805 Vout for reverse polarity protection: anode to LM7805 output, cathode to 5V rail, resulting in ~4.3V on the output rail. Not suitable for high-frequency switching (reverse recovery ~2µs–30µs); intended for DC or 50/60Hz rectification only.

1

Resistor

100 Ω

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

100 Ω

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

10 kΩ

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

10 kΩ

Through-hole resistor (current-limiting in series with an LED)

1

LED

Green, 3 mm

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

LED

Red, 3 mm

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

1 kΩ LED series resistor

1 kΩ, ¼ W

A resistor that limits current through the green SET-pulse indicator LED.

1

1 kΩ LED series resistor

1 kΩ, ¼ W

A resistor that limits current through the red RESET-pulse indicator LED.

1

USB-C 5V Adapter

5 V, 1 A minimum

USB-C wall adapter delivering regulated 5 V to the board's USB or VBUS rail. Default wired power source for desktop / stationary projects.

Assemble it in 7 steps

1. Keep the first test away from AC power

For this desk test, leave the relay contact terminals marked COM and NO completely unused. Do not connect the PZEM, an outlet, a boat, or any 120/240 V wiring. You are only testing the 5 V relay coils and the safety timer.

  • Put a small label over the relay contact terminals so they cannot be mistaken for the coil terminals.
  • Connecting mains power during this first test can cause electric shock, fire, or damage; the contacts are not part of the desk-demo wiring.

2. Make a common low-voltage ground

Connect the negative or GND output of the 5 V USB bench supply to a GND pin on the T3-S3. This shared ground gives the two MOSFET drivers the same electrical reference as GPIO10 and GPIO21.

  • Use black wire for every ground connection to make the circuit easier to inspect.
  • Without the shared ground, the relay drivers may not turn on even if their indicator LEDs light.

3. Wire the SET coil driver

Connect relay SET+ to the bench supply +5 V. Connect relay SET- to the Drain (D) of mosfet_set_1. Connect its Source (S) to GND. Connect GPIO10 through gate_resistor_set_1 (100 Ω) to its Gate (G), then connect gate_pulldown_set_1 (10 kΩ) from that same gate point to GND.

  • On the AO3400A SOT-23 package, verify the pin positions from the seller’s datasheet before soldering; the package is very small.
  • Do not swap the MOSFET Drain and Source; the coil may fail to switch or behave unpredictably.

4. Add the green SET pulse light and diode

Connect the long leg of the green set_pulse_led_1 to set_indicator_resistor_1 (1 kΩ), then connect the other resistor end to the SET MOSFET Gate (G). Connect the LED short leg to GND. Put flyback_set_1 directly across the SET coil: its striped cathode end goes to SET+ and its unstriped anode end goes to SET-.

  • The green LED should flash only during a SET pulse. The stripe on the diode is the cathode mark.
  • A reversed flyback diode makes a direct short across the 5 V supply when the coil is pulsed.

5. Wire the RESET coil driver

Connect relay RESET+ to the bench supply +5 V. Connect relay RESET- to the Drain (D) of mosfet_reset_1. Connect its Source (S) to GND. Connect GPIO21 through gate_resistor_reset_1 (100 Ω) to its Gate (G), then connect gate_pulldown_reset_1 (10 kΩ) from that gate point to GND.

  • Use a different wire color for the RESET coil route so it cannot be mixed up with the SET coil.
  • Do not join SET- and RESET- together; each coil needs its own MOSFET driver.

6. Add the red RESET pulse light and diode

Connect the long leg of reset_pulse_led_1 to reset_indicator_resistor_1 (1 kΩ), then connect the other resistor end to the RESET MOSFET Gate (G). Connect its short leg to GND. Put flyback_reset_1 across the RESET coil: striped cathode to RESET+ and unstriped anode to RESET-.

  • The red LED flashes at startup and when you send LOCK or let the watchdog expire.
  • Make sure the LED long and short legs are not swapped — a reversed LED will not show the pulse.

7. Power and test the desk prototype

Power the T3-S3 from its USB-C port and power the relay coils from the separate regulated 5 V bench supply. Open Schematik’s serial console after Deploy and send UNLOCK followed by Enter. The green LED should flash once. Send HEARTBEAT every 10–20 seconds to keep it enabled, send LOCK to flash the red LED, or stop heartbeats and wait 60 seconds for the red watchdog pulse.

  • Send STATUS at any time to see whether the firmware believes the relay is enabled.
  • Do not use an unregulated supply or a supply above 5 V for the relay coils; excessive coil voltage can damage the relay.

Review all connections

1. Connections between "relay_1" and "ESP32"

Functionrelay_1ESP32
powerSET+5V
powerRESET+5V
powerCOMProtected incoming live conductor inside insulated enclosure — qualified-person-only wiringEXT
powerNOSwitched live conductor to outlet inside insulated enclosure — qualified-person-only wiringEXT

2. Connections between "gate_pulldown_set_1" and "ESP32"

Functiongate_pulldown_set_1ESP32
groundP2GND
digitalP1AO3400A Gate (G)EXT

3. Connections between "gate_pulldown_reset_1" and "ESP32"

Functiongate_pulldown_reset_1ESP32
groundP2GND
digitalP1AO3400A Gate (G)EXT

4. Connections between "flyback_set_1" and "ESP32"

Functionflyback_set_1ESP32
powerAnode30 A 5 V dual-coil latching power relay SET-EXT
powerCathode30 A 5 V dual-coil latching power relay SET+EXT

5. Connections between "flyback_reset_1" and "ESP32"

Functionflyback_reset_1ESP32
powerAnode30 A 5 V dual-coil latching power relay RESET-EXT
powerCathode30 A 5 V dual-coil latching power relay RESET+EXT

6. Connections between "mosfet_set_1" and "ESP32"

Functionmosfet_set_1ESP32
digitalGate (G)Resistor P2EXT
powerDrain (D)30 A 5 V dual-coil latching power relay SET-EXT
groundSource (S)GND

7. Connections between "mosfet_reset_1" and "ESP32"

Functionmosfet_reset_1ESP32
digitalGate (G)Resistor P2EXT
powerDrain (D)30 A 5 V dual-coil latching power relay RESET-EXT
groundSource (S)GND

8. Connections between "gate_resistor_set_1" and "ESP32"

Functiongate_resistor_set_1ESP32
digitalP1GPIO 10

9. Connections between "gate_resistor_reset_1" and "ESP32"

Functiongate_resistor_reset_1ESP32
digitalP1GPIO 21

10. Connections between "set_indicator_resistor_1" and "ESP32"

Functionset_indicator_resistor_1ESP32
digitalP1AO3400A Gate (G)EXT
digitalP2LED ANODEEXT

11. Connections between "set_pulse_led_1" and "ESP32"

Functionset_pulse_led_1ESP32
groundGNDGND

12. Connections between "reset_indicator_resistor_1" and "ESP32"

Functionreset_indicator_resistor_1ESP32
digitalP1AO3400A Gate (G)EXT
digitalP2LED ANODEEXT

13. Connections between "reset_pulse_led_1" and "ESP32"

Functionreset_pulse_led_1ESP32
groundGNDGND

14. Connections between "bench_5v_usb_supply_1" and "ESP32"

Functionbench_5v_usb_supply_1ESP32
power+5V5V
groundGNDGND

Deploy the firmware

#include <Arduino.h>

// LILYGO T3-S3 desk prototype: low-voltage relay-driver and watchdog test.
// GPIO10 closes (SET) a 5 V latching-relay coil through its MOSFET driver.
// GPIO21 opens (RESET) the other coil through its MOSFET driver.

// Forward declarations
void pulsePin(uint8_t pin, const char *label);
void openRelay();
void closeRelay();
void handleCommand(String command);

constexpr uint8_t RELAY_SET_PIN = 10;
constexpr uint8_t RELAY_RESET_PIN = 21;
constexpr unsigned long PULSE_DURATION_MS = 100;
constexpr unsigned long HEARTBEAT_TIMEOUT_MS = 60000;

bool powerEnabled = false;
unsigned long lastHeartbeatMs = 0;

void pulsePin(uint8_t pin, const char *label) {
  Serial.printf("[RELAY] %s pulse for %lu ms\n", label, PULSE_DURATION_MS);
  digitalWrite(pin, HIGH);
  delay(PULSE_DURATION_MS);
  digitalWrite(pin, LOW);
}

void openRelay() {
  if (powerEnabled) {
    pulsePin(RELAY_RESET_PIN, "OPEN / RESET");
    powerEnabled = false;
  }
}

void closeRelay() {
  if (!powerEnabled) {
    pulsePin(RELAY_SET_PIN, "CLOSE / SET");
    powerEnabled = true;
  }
}

void handleCommand(String command) {
  command.trim();
  command.toUpperCase();

  if (command == "HEARTBEAT") {
    lastHeartbeatMs = millis();
    Serial.println("[WATCHDOG] Heartbeat accepted.");
  } else if (command == "UNLOCK") {
    lastHeartbeatMs = millis();
    closeRelay();
    Serial.println("[STATE] Power enabled; send HEARTBEAT within 60 seconds.");
  } else if (command == "LOCK") {
    openRelay();
    Serial.println("[STATE] Power disabled.");
  } else if (command == "STATUS") {
    const unsigned long age = millis() - lastHeartbeatMs;
    Serial.printf("[STATUS] power=%s, heartbeat_age_ms=%lu\n", powerEnabled ? "ON" : "OFF", age);
  } else if (command.length() > 0) {
    Serial.println("[HELP] Commands: UNLOCK, LOCK, HEARTBEAT, STATUS");
  }
}

void setup() {
  pinMode(RELAY_SET_PIN, OUTPUT);
  pinMode(RELAY_RESET_PIN, OUTPUT);
  digitalWrite(RELAY_SET_PIN, LOW);
  digitalWrite(RELAY_RESET_PIN, LOW);

  Serial.begin(115200);
  const unsigned long serialWaitStarted = millis();
  while (!Serial && (millis() - serialWaitStarted < 1500)) {
    delay(10);
  }

  // Deliberately pulse RESET once at startup: the desk prototype begins open.
  pulsePin(RELAY_RESET_PIN, "STARTUP OPEN / RESET");
  powerEnabled = false;
  lastHeartbeatMs = millis();
  Serial.println("[SYSTEM] T3-S3 relay watchdog desk test ready.");
  Serial.println("[HELP] Commands: UNLOCK, LOCK, HEARTBEAT, STATUS");
}

void loop() {
  if (Serial.available() > 0) {
    handleCommand(Serial.readStringUntil('\n'));
  }

  if (powerEnabled && (millis() - lastHeartbeatMs >= HEARTBEAT_TIMEOUT_MS)) {
    Serial.println("[SAFETY] Heartbeat timed out; opening relay.");
    openRelay();
    lastHeartbeatMs = millis();
  }
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik