Initialising a RELAY pins on ESP32

Just checking I’m using the correct protocol for setup and controlling a 5v Relay.

GPIO.setup_output(27, 0)  <==???
GPIO.write(27, 0);  

I have an ESP32 with 3 Relays attached and after every power on boot I see the pins go high or relays are turned on,but seems to work fine when one is attached .
do I need to “set_mode” and turn off relay at boot time?

I had this working on a NodeMCU ESP8266 however having some issues consolidating all the relays on a ESP32 device

1 Like

I’m also having this issue. It is discussed here. Seems a pretty critical bug…!

First of all: there are no “relay pins” on the ESP32, only GPIO: General Purpose Input Output; what you do with the pins is your responsibility.

Microcontroller pins usually can be set as inputs or outputs. They also usually start configured as inputs on reset, and may have a pull-up or pull-down internal resistor that may or may not be configured on reset.
From this moment until your mJS script is executed, the pin will remain in the reset default state, you have to take precautions when designing your hardware.
What you see depends on how you connect your relay and how pins are configured at reset. Once mOS finished booting and your script is executed, the pin will be set as an output and will stay at 0 logic level until you write a different level. But, during boot time, it will stay at its default reset state, and that may be output high or input with pull-up, and I guess you don’t want that. Unfortunately that can not be changed, so if it does bother you, you’ll have to design your hardware to accordingly.

There is no “protocol”, no need for a specific order, you just have to call the right function to set the hardware as you want it to be.
GPIO.setup_output(27, 0) (explained here) is what you need to do to correctly setup the GPIO27 pin as an output at 0V and avoid possible glitches on the output. It is logically equivalent to first writing 0 and the setting as an output.
GPIO.set_mode(27, GPIO.MODE_OUTPUT) will set the pin as output, its initial state will be whatever is carried on from prior operations or reset state. In your case it will just do again what you already did.
GPIO.write(27, 0) will set the pin at logic level 0

I personally would not connect a relay directly to a microcontroller pin.

is there a way you would go about connecting a relay (module with transistor driver) to an ESP32 with mOS in this instance? This would be outside the scope of mOS and would need something more low level?

Whatever you connect to a GPIO pin must honor the datasheet.
If the pin starts as in input with pull-up, design your driver to activate the relay on low, and viceversa. If you already have something that is active on high, and you can’t change it, just add a logic inverter, which can be from a transistor to a 74LV06 variant, or control power for all relays with another pin you enable later, or …

Yes that’s what I was thinking if in case I couldn’t set the state on boot. Just had a look at datasheet, section 4.1 GPIO says “Each digital enabled GPIO can be configured to internal pull-up or pull-down, or set to high impedance”…

Not sure if my pin definitions are incorrect either:

#define WIFI_LED 16
#define WIFI_BTN 36
#define PB1 35
#define PB2 39
#define R_PB 34
#define GPIO14 14
#define EN_I2C 13
#define R1 4
#define R2 12
#define LED_RED 2
#define RL_LED_EN 15

mgos_gpio_setup_output(EN_I2C, 1);
mgos_gpio_setup_output(R1, 0);
mgos_gpio_setup_output(R2, 0);
mgos_gpio_set_mode(R1, MGOS_GPIO_MODE_OUTPUT);
mgos_gpio_set_mode(R2, MGOS_GPIO_MODE_OUTPUT);
 //mgos_gpio_setup_output(WIFI_LED, 0);
mgos_gpio_setup_output(RL_LED_EN, 0);
mgos_gpio_setup_input(WIFI_BTN, MGOS_GPIO_PULL_DOWN); 
mgos_gpio_setup_input(R_PB, MGOS_GPIO_PULL_DOWN);
mgos_gpio_setup_input(PB1, MGOS_GPIO_PULL_DOWN);
mgos_gpio_setup_input(PB2, MGOS_GPIO_PULL_DOWN);
mgos_gpio_set_mode(PB1, MGOS_GPIO_MODE_INPUT);
mgos_gpio_set_mode(PB2, MGOS_GPIO_MODE_INPUT);

perhaps I am missing this command:

When I said “datasheet” I meant “voltages and currents”.
Your C code will probably run before the mJS script but after the boot process.
Your output pins will stay at whatever function they are configured at reset time (which should also be depicted in the datasheet) while the device is booting; except for those that for some reason are initialized by either the IDF or mOS.

That depends on whether you need a pull-up or not, which is not related to a pin that is intended to work as an output (you said you were driving a relay).

thanks for the direction, I’m not super familiar with implementing the low level coding. Was thinking if I could set an internal pull down on boot could solve it.
The internal resistors are described in the link above, although I will try the mgos_gpio_set_pull command to see if they correlate…??

AFAIK there is no way to define that until user code runs, which happens after boot. Maybe the IDF has a way of doing that, AFAIK…
You can wire a physical resistor to GND but if the processor starts on pull-up instead of hi-Z you can only design your circuit to be active on low

Check A.4. IO_MUX chapter of the ESP32 Datasheet to find the default mode of the GPIO.

LE. Are you using a custom board or a ready-made one? If the latter, check the schematic diagram of the board. Some of them have pull-up resistors on some GPIOs.

Thank you, I have noticed IO12 is low on boot, this does correspond to pull down in the datasheet. It appears there is a solder short on some of my pins, IO 16,4,0. This may be my issue, they are in different power domains and have a pull-up and down.

** board is custom

I’m just experimenting at the moment by delaying the GPIO.set_mode till I need to send first request.
so far so good… here is a code snippet .

  if (relay.init === false) {
	  print("init output relay");
	  GPIO.set_mode(relaypin, GPIO.MODE_OUTPUT);
	  relay.init = true;