Page 1 of 1

Reading output GPIO pin logic state

Posted: Mon May 21, 2018 4:06 pm
by x-8973
I needed to know the logical level on the pin, which is set to output. The gpio_get_level() function always returns 0, even after a gpio_set_level(GPIO_PIN, 1). Is there any way to find out the logical level on such a pin?

Code example:

Code: Select all

gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1 << GPIO_OUTPUT_IO_LED);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);

while (1)
{
	if (gpio_get_level(GPIO_OUTPUT_IO_LED)) // If pin is switched on
	{
		ESP_LOGI(__func__, "LED on");
		gpio_set_level(GPIO_OUTPUT_IO_LED, 0); // Switch pin off
	}
	else
	{
		ESP_LOGI(__func__, "LED off");
		gpio_set_level(GPIO_OUTPUT_IO_LED, 1); // Switch pin on
	}
}

Re: Reading output GPIO pin logic state

Posted: Mon May 21, 2018 6:31 pm
by loboris
The question was asked several times already, you must set the gpio mode to GPIO_MODE_INPUT_OUTPUT (or GPIO_MODE_INPUT_OUTPUT_OD) if you want to use the gpio as output and read its state back. Or you can simply save the state in a variable after gpio_set_level().

Re: Reading output GPIO pin logic state

Posted: Mon May 21, 2018 7:24 pm
by x-8973
I did a search on the forum, but did not find anything suitable. Thank you, now I will know)

Re: Reading output GPIO pin logic state

Posted: Thu Feb 14, 2019 4:07 pm
by flodis
If you are interested in the last output state of a pin you can read from either GPIO_OUT_REG (31..0) or GPIO_OUT1_REG (32..39).
To detect if port is input or output you can read the GPIO_ENABLE_REG (31..0) or GPIO_ENABLE1_REG(32..39)

If you are sure the direction is not changed outside your control a non atomic direct port access for pin 0..31 like this may work:

Code: Select all

gpio_num_t pin = (gpio_num_t)(your_pin_number_0to31 & 0x1F);
int state=0;
if (GPIO_REG_READ(GPIO_ENABLE_REG) & BIT(pin)){
	//pin is output - read the GPIO_OUT_REG register
	state = (GPIO_REG_READ(GPIO_OUT_REG)  >> pin) & 1U;
}
else
{
	//pin is input - read the GPIO_IN_REG register
	state = (GPIO_REG_READ(GPIO_IN_REG)  >> pin) & 1U;
}
Details here:
https://github.com/espressif/esp-idf/bl ... gpio_reg.h
https://docs.espressif.com/projects/esp ... /gpio.html
https://www.espressif.com/sites/default ... #section.4

Re: Reading output GPIO pin logic state

Posted: Tue Aug 10, 2021 5:17 am
by JL1946
Many thanks to @flodis for your code snippet. It worked for me...

I implement a timer to toggle the Blue Led on a Esp32 Dev Board...
My Code is as follows:

Code: Select all

#define BLINK_GPIO 	2

void blink_blue_led() {

	gpio_num_t pin = (gpio_num_t)(BLINK_GPIO & 0x1F);
	int state = 0;

	if (GPIO_REG_READ(GPIO_ENABLE_REG) & BIT(pin))
	{
		state = (GPIO_REG_READ(GPIO_OUT_REG)  >> pin) & 1U;
		if (state == 0) {
	        	gpio_set_level(BLINK_GPIO, 1);
		} else {
			gpio_set_level(BLINK_GPIO, 0);
		}
	}
}

Re: Reading output GPIO pin logic state

Posted: Tue Sep 07, 2021 11:26 pm
by ayham24
Hey Could you please somehow send me your whole package of the program if it's ok? cuz i'm trying since days to do it but i don't know what's wrong here :( i would be really thankful

Re: Reading output GPIO pin logic state

Posted: Sat Oct 22, 2022 3:19 am
by davidhbrown
... read from either GPIO_OUT_REG (31..0) or GPIO_OUT1_REG (32..39)....
Emphasis added as I'd missed that on first reading and it turned out I was using GPIOs 32 and 33 (hidden behind #defined constants so I'd forgotten) :oops: Thank you for the example; it's working great.

Re: Reading output GPIO pin logic state

Posted: Thu Jun 13, 2024 11:44 am
by bojanj
I'm trying to compile pieces of the code posted here with the latest Arduino (IDF 5.x). WHich libraries do I have to #include?

Re: Reading output GPIO pin logic state

Posted: Sat Nov 23, 2024 11:01 am
by stdenits
Hello.
Any possibility to read output pin state for ESP32-S3 and ESP-IDF (master branch)?

Re: Reading output GPIO pin logic state

Posted: Fri Jun 27, 2025 11:36 am
by notron124
Hello.
Any possibility to read output pin state for ESP32-S3 and ESP-IDF (master branch)?
If it is still relevant and for those, who are still searching. There is a way to read gpio state, when it in output mode.

It would look like this:

Code: Select all

#include "driver/gpio.h"
#include "hal/gpio_hal.h"

bool get_out_gp_level_hal(gpio_num_t gpio_num) {
   gpio_dev_t *hw = GPIO_HAL_GET_HW(GPIO_PORT_0);
   if (gpio_num < 32) {
      return (hw->out >> gpio_num) & 0x1;
   } else {
      return (hw->out1.data >> (gpio_num - 32)) & 0x1;
   }
}
Be aware: how yout obtain gpio hw pointer is hardware dependent.

I tested that only on ESP32-S3, esp-idf v5.4.

Personally, I wouldn't use this approach unless there's a pressing need. To track pin states, you can create your own bit-field.
Something like this:

Code: Select all

typedef struct valve_pins_states {
   uint8_t valve1_pin_state : 1;
   uint8_t valve2_pin_state : 1;
   uint8_t reserved : 6;
} valve_pins_states;

static valve_pins_states valve_ps;

#define P_VALVE1        GPIO_NUM_38
inline static void close_valve1(void) {
   gpio_set_level(P_VALVE1, 0); 
   valve_ps.valve1_pin_state = 0;
}

inline static void open_valve1(void) {
   gpio_set_level(P_VALVE1, 1); 
   valve_ps.valve1_pin_state = 1;
}

inline static bool is_valve1_open(void) {
   return valve_ps.valve1_pin_state;
}

#define P_VALVE2        GPIO_NUM_37 
inline static void close_valve2(void) {
   gpio_set_level(P_VALVE2, 0);
   valve_ps.valve2_pin_state = 0;
}

inline static void open_valve2(void) {
   gpio_set_level(P_VALVE2, 1);
   valve_ps.valve2_pin_state = 1;
}

inline static bool is_valve2_open(void) {
   return valve_ps.valve2_pin_state;
}