Turning something on and off is the first real job most people give an ESP32. A blue relay board costs little, the code is one digitalWrite(), and the lamp clicks on. Then the relay clicks every time the board reboots, the module will not switch off from a 3.3 V pin, or a small LED bulb keeps glowing behind a solid-state relay that is supposedly off.
None of these are bugs in your code. They come from how the parts work, and they are easy to avoid once you know about them.
Why a GPIO pin cannot drive a relay coil directly
A relay is an electromagnet that moves a contact. The coil needs far more current than a microcontroller pin is meant to supply. Take the Songle SRD-05VDC-SL-C, the black cube on most cheap modules. Its datasheet lists a 5 V coil drawing 71.4 mA in the high sensitivity version and 89.3 mA in the standard one. It also expects 5 V, while ESP32 outputs are 3.3 V.
So something has to sit between the pin and the coil. On a bare relay this is usually an NPN transistor or a logic level MOSFET, with a diode across the coil. Relay modules include that circuit, often with an optocoupler in front of it. The ESP32 pin then only drives a few milliamps into a transistor base or an optocoupler LED.
The diode across the coil
When the current through a coil is cut, the collapsing magnetic field induces a voltage spike. TE Connectivity's application note on coil suppression says this transient can reach hundreds or even thousands of volts, and it appears across whatever switched the coil off. Without protection, that is your transistor.
The standard fix is a diode in reverse across the coil, a flyback diode. Omron's relay FAQ recommends diodes for DC coils and varistors or RC elements for AC coils, and adds that any suppression circuit makes the relay release more slowly.
That slower release has a cost. According to TE, a plain diode lets the coil current decay slowly, so the armature opens with less force. With high current loads, the contacts can form tiny welds when they close, and a sluggish opening may fail to break them. TE suggests a Zener diode in series with the ordinary diode: the switching transistor is still protected, and the relay releases faster. For a lamp on a hobby board, a plain diode is fine. For a relay switching a heater or a motor near its rated current, the Zener version is worth the extra part.
Ready-made relay modules almost always include the diode. If you build your own driver, do not skip it.
Relay modules: active low, JD-VCC and 3.3 V logic
Most multi-channel relay boards sold for Arduino and ESP projects have the same input layout. Random Nerd Tutorials describes a typical 2-channel module like this:
VCCandGNDpower the module's input side, andIN1,IN2are the control inputs.- The relay triggers when the input drops below about 2 V. The module is active low:
LOWswitches the relay on. - A jumper connects
VCCtoJD-VCC, which powers the relay coils. With the jumper on, the coils run from the same supply as the ESP32 side, so there is no real isolation. With the jumper off, you feedJD-VCCfrom a separate supply, and the optocouplers isolate the ESP32 from the relay circuit.
Active low trips people up in two ways. First, your code is inverted: digitalWrite(pin, LOW) turns the load on. Second, it changes what happens during boot, more on that below.
The 3.3 V question comes up constantly with modules labelled "5 V". On a module where the input drives an NPN transistor, 3.3 V is normally enough. In an Arduino Stack Exchange answer, the calculation for one such circuit gives about 2.5 mA of base current at 3.3 V, enough to switch the relay. Optocoupler modules are less predictable: another answer warns that 3.3 V may not light the optocoupler LED well enough, and that you have to test it. If a channel will not switch reliably, the clean options are a module rated for 3.3 V logic, a level shifter, or your own transistor stage.
Whatever you choose, the grounds of the ESP32 and the module's input side have to be connected, unless you are deliberately using a separate JD-VCC supply for the coils only.
Pick pins that stay quiet at boot
An ESP32 does not start with your firmware in control. Between reset and the moment your code configures the pin, some GPIOs are read by the boot ROM or toggled by it. Random Nerd Tutorials' ESP32 pinout reference lists the ones to watch:
- GPIO0 must be low to enter flashing mode, and outputs a PWM signal at boot.
- GPIO2 must be floating or low to enter flashing mode.
- GPIO5 and GPIO15 output a PWM signal at boot and are high at boot.
- GPIO12 makes the boot fail if it is pulled high.
- GPIO14 outputs a PWM signal at boot.
- GPIO1 and GPIO3 are the serial port, GPIO6 to GPIO11 are connected to the flash memory, and GPIO34 to GPIO39 are inputs only.
Espressif's boot mode guide explains the GPIO12 problem: if it is high at reset, the flash voltage is set to 1.8 V instead of 3.3 V. With 3.3 V flash, that can stop the chip from booting or flashing.
A relay on GPIO5 or GPIO15 can therefore click when the board starts, and on an active low module a pin that is low during boot means the load switches on. For outputs that drive a load, RNT's list of safe pins is GPIO13, 16 to 19, 21 to 23, 25 to 27, 32 and 33. On some modules, such as boards with PSRAM, GPIO16 and 17 are taken by the memory, so check yours.
Then decide on a safe default. Set the output state at the very start of setup(), before Wi-Fi and anything else slow. If the load must stay off while the ESP32 is unpowered or resetting, check what your module does when its input is left floating, and add a pull resistor to the "off" level if it does not stay off on its own.
Mechanical relay or solid-state relay
A solid-state relay (SSR) has no moving parts. An LED on the input side triggers a semiconductor on the output side, for example a triac or thyristor for AC loads, a power transistor for DC loads, or a pair of MOSFETs for either. Omron's technical guide lists the advantages: no switching contacts that wear out, high-speed switching and minimal noise. It also lists the costs.
Leakage current. An SSR does not fully disconnect the load. Omron says a small leakage current flows through the snubber circuit even with no input signal. Panasonic adds that if the load current is smaller than that leakage current, the load can stay on. This is why a small LED bulb glows faintly or flickers behind an "off" SSR. The fix from both manufacturers is a bleeder resistor in parallel with the load, or a relay with a MOSFET output for very small loads. It is also why Omron warns you to switch off the supply before touching the wiring of an SSR: "off" is not "disconnected".
Minimum load current. Panasonic explains that a triac output may not turn off if the load current is below the SSR's specified minimum load current.
Heat. Omron's guide marks heat dissipation as required. A semiconductor carrying several amps gets hot, and SSR ratings depend on the heat sink and ambient temperature. A relay rated at 25 A on a label will not carry 25 A in a closed plastic box without a heat sink.
AC versus DC. The output type has to match the load. Omron lists triacs and thyristors for AC loads, so for a DC load pick an SSR designed for DC.
Zero-cross. Many AC SSRs switch on only when the mains voltage crosses zero. Omron notes this reduces noise and inrush. It does nothing about leakage.
A mechanical relay has a real air gap when off, a low voltage drop when on and no leakage. Its weaknesses are wear and speed. The Songle datasheet gives an electrical life of 100,000 operations, mechanical life of 10 million, and a maximum of 30 operations per minute under load. That is fine for a pump that runs three times a day. It is not fine for a heater switched on and off every few seconds. Omron's guide says that if a heater is switched at intervals of a few seconds over several years, an SSR must be used.
Read the contact rating, not the number on the box
Relay modules often have "10A 250VAC" printed on the relay. The Songle datasheet gives 10 A at 125 VAC and 7 A at 240 VAC for the changeover version, with resistive loads. For inductive loads, the changeover contact is rated at 3 A at 120 VAC. A motor, a transformer or a power supply with a large input capacitor stresses contacts far more than a heater.
The relay is also only one part of the module. PCB traces, screw terminals and spacing on a cheap board decide how much current and voltage it really handles. For mains loads above a few amps, a DIN rail relay or contactor in a proper enclosure is the safer choice, with the ESP32 driving its coil.
Mains voltage needs respect
Random Nerd Tutorials puts a warning in its ESP32 relay tutorial: mains voltage can cause serious injury, so disconnect everything from mains while you program or wire the board, and get help from someone experienced if you are not. Use an enclosure that keeps fingers away from the terminals, a fuse sized for the wiring, and strain relief on the cables. If the whole job is switching a socket, a certified smart plug or a ready-made relay with local control is often a better choice than a bare module.
A short checklist
- Never drive a relay coil straight from a GPIO pin. Use a module or a transistor stage with a flyback diode.
- Check whether the module is active low, and write the code to match.
- Test 3.3 V logic on "5 V" modules, especially those with optocouplers.
- Avoid GPIO0, 2, 5, 12, 14 and 15 for loads, and set a defined state as early as possible.
- Remove the
JD-VCCjumper and use a separate coil supply if you want real isolation. - Use an SSR for frequent switching, but plan for leakage, heat and the minimum load current.
- Size the relay for the real load type, not the headline rating.