GPIO Digital Read From Python

I am using Python to control an Odrive for a project I’m working on. I wanted to use the Odrive to report the status of a button press on the system.

I have been through as much documentation as I can bear to read including old posts here on the forum, and the only related topics are either years old with “update coming soon” responses or “use get_adc_voltage(gpio)” which only returns nan for a digital pin despite it being set to either digital or analog mdoes.

get_gpio_states()→ [int]

Returns the logic states of all GPIOs. Bit i represents the state of GPIOi.

Above from the documentation returns the modes of GPIOs, but does not return the states of the GPIO pins from what I can tell. It also has the “Bit i represents the state of GPIOi.” comment which makes me think that I could input a bit mask and get something from it, but there is no documentation explaining how to use it.

Is there a way to read the state of a gpio pin, or how to extrapolate that data from get_gpio_sates() using the python library?

Hi! Is this an ODrive v3.6 or S1/Pro?

get_gpio_states() does return a bitmask of GPIO states, so you can just check the corresponding bit of your button.

Here’s a quick bit of python code that could work

def check_gpio_num(odrv, num):
    return (odrv.get_gpio_states() & (1 << num)) != 0

Usage is i.e. x = check_gpio_num(odrv0, 4), where x would then be True/False.

Thank you for the quick response solomondg.

I am using an ODrive Pro with v0.6.7 firmware (I had connection issues with v0.6.8, so I rolled it back).
G02) and 12 (G05) from the data sheet here: ODrive Pro Datasheet — ODrive Documentation 0.6.7 documentation

I have the switches wired up as a normally open active high switch according to the following documentation: Endstops and Homing — ODrive Pro Documentation 0.6.1 documentation

After your input, the following code is what I am using to check the switch position:

roll_drv.config.gpio5_mode = GpioMode.DIGITAL_PULL_DOWN
roll_drv.config.gpio2_mode = GpioMode.DIGITAL_PULL_DOWN

def check_gpio_num(odrv, num):
    while True:
        response = ((odrv.get_gpio_states() & (1 << num)) != 0)
        print(response)
        time.sleep(1/5)

t_test_GPIO1 = threading.Thread(target=check_gpio_num, args=(roll_drv, 5), name="t_test_GPIO1", daemon=True)
t_test_GPIO1.start()

t_test_GPIO2 = threading.Thread(target=check_gpio_num, args=(roll_drv, 2), name="t_test_GPIO2", daemon=True)
t_test_GPIO2.start()

I have checked the wiring, and I am getting the expected outputs from the switch positions, but no matter what position I have the switch I am always getting a “False” as the output of the two threads reading the IO.

Any ideas on what I am missing from this setup?

Hey there,

A few things:

  1. G02 and G05 both have pull-ups, so you may want to switch to using pins G05/G08
  2. If using pins on the ISOLATED IO (J12) connector, ISO_VDD and ISO_GND need to be externally powered with 5V/GND. If the endstops are powered from the ODrive FEEDBACK IO (J8) 5V/GND, that 5V/GND can be used to power the ISO_VDD/ISO_GND, as long as no other devices are connected to ISOLATED IO, and no other devices are connected to the ODrive FEEDBACK IO other than the encoder (this is to avoid ground loops).
  3. Have you ran an roll_drv.save_configuration() after configuring the gpio modes and endstop configuration?

Do you have a link to show which pins are pull-ups and which ones are pull-down? I didn’t see this in the documentation.

Just attempted saving the configuration after changing the gpio pins to DIGITAL_PULL_DOWN. I am now getting True for all responses despite the switch position.

I am currently using the power and ground from pins 11 and 6 on the Feedback IO.

Hey again, I hope everyone had a happy new year and holidays.

I wanted to ping here again and see if anyone has any more help on this topic.

Using: (odrv0.get_gpio_states() & (1 << num)) != 0 where num is the gpio pin I am attempting to monitor, I am always getting True as a response. This is with odrv0.config.gpio1_mode set to GpioMode.DIGITAL_PULL_UP or GpioMode.DIGITAL_PULL_DOWN or if the button is pressed or not pressed that is hooked up to the GPIO pin I am trying to monitor (using gpio1 as the example in this, but I have tested a few pins now).

I am not trying to use this switch as an end stop, so I have not configured it so. I have used the save_config() after changing the GpioMode per the documentation.

Any thoughts, or is standard GPIO monitoring not supported?

Hi! Apologies. We just updated the docs with more info on the pins themselves - here. It’s super messy right now (my fault), but hopefully that should have more info.

Just checking - you ran a save_configuration() after the config change, correct? GPIO modes are only applied on boot.

Thank you for the update.

Yes, I ran a save_configuration() after changing the GPIO mode.

After some extensive testing, I was able to get GPIO pins 1 and 2 working in the DIGITAL_PULL_UP mode.

Strangely, the documentation indicates that G0-G02, G04-G09, G11-G12, G14-G16, G18 are all user-facing GPIO inputs that I should be able to monitor. Since I was trying to use 2 and 5, they should have worked all the same.

Either way, thank you for the help. Pins 1 and 2 are working as expected for me, and they are the only pins I need for the foreseeable future.