End switches an interrupts

Hello and thanks for your sharing your own experiences. Would you mind sharing the technical information below?

Switch limit type
Is your limit switch wired to an arduino board and then the arduino is connected to the odrive?If so, can you share the wiring From -To pinouts?
Would you be able to show a video how switch works?
If you are using arduino, would you mind sharing the sketch?



I had a look to your code, but couldn’t find why the GPIO 7 and 8 isn’t working as expected.

But one idea to void Axis::set_min_endstop_enabled(bool enable) in axis.cpp
you set interrupt_mode = GPIO_MODE_IT_RISING_FALLING. For debouncing isn’t it better to set it like:

uint32_t interrupt_mode = config_.min_endstop.is_active_high ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING;

You can use every micro switch that fits to your application. I used: https://www.ebay.de/itm/10-Stueck-AC-125V-5A-SPDT-1NO-1NC-Glatt-Hinge-Lever-Mini-Micro-Schalter-DE/282522069641?hash=item41c7a0aa89:g:kxcAAOSwCkZZPuy7

The connetion is very easy. It’s directly connected to a GPIO on the ODrive. The other contact is connected to Ground GND.

Greetings / Zennix



  1. debouncing
  2. GPIO7 and 8 not recognised correct
  3. new-> axis1 didn’t find the encoder anymore.

Greetings / Zennix

I’ve updated the endstop branch again. To make the code cleaner, I’ve made each endstop an object. This means they now exist as objects within the axis context:


I’ve also added software debouncing, with a default value of 100ms.

<odrv>.<axis>.min_endstop.config.debounce_ms = <Float>
<odrv>.<axis>.max_endstop.config.debounce_ms = <Float>

Please try this out. I don’t think it will have fixed the GPIO issues though.


Couldn’t test it, because I could not save the configuration.
After a save_configuration() and reboot(), the values are gone.

Greetings / Zennix

2 posts were split to a new topic: How to use github?

Yes, I am having the same result. All parameter configuration settings gone.


other values like “odrv0.axis0.config.startup_closed_loop_control = False”
where also not saved.

I think we have to wait till Wetmelon has finished the Trajectory Planner.

Greetings / Zennix

Yes. The wait is worth it. I handled to make it work without it ;but, the switch and ramp features will be excellent improvements.My project



@hbtousa I think you can use the “echo” effect in after-effects (or premiere pro maybe) to properly show off the POV trails:

@Zennix @hbtousa Please pull the most recent Endstops branch to test with. I was able to fix the saving issue on my end, but I don’t have a good way to test the other settings. I also updated this branch to the most recent devel version, so it has other fixes.

Thank you for the new version. Here is what I found:

  1. Saving is working now
  2. Homing is not working

In [88]: odrv0.axis0.requested_state = 9
In [89]: odrv0.axis0.current_state
Out[89]: 8

The motor is not going to search the home position. It stands in closed_loop.

  1. emergency stop
    During a pos_setpoint command, pressing an endstop switch has no effect.

My config:

In [101]: odrv0.axis0.min_endstop
gpio_num = 5 (int)
enabled = True (bool)
offset = -1000 (int)
is_active_high = False (bool)
debounce_ms = 100.0 (float)

In [102]: odrv0.axis0.max_endstop
gpio_num = 6 (int)
enabled = True (bool)
offset = 0 (int)
is_active_high = False (bool)
debounce_ms = 100.0 (float)

In a previous version was a min_endstop_state and max_endstop_state. Could you please add it again?

I added the

make_protocol_property(“endstop_state”, &endstop_state_)

in endstop.hpp.
If I press a switch it will not be shown in

In [16]: odrv0.axis0.max_endstop
gpio_num = 0 (int)
enabled = False (bool)
offset = 0 (int)
is_active_high = False (bool)
debounce_ms = 100.0 (float)
endstop_state = False (bool)

Greetings / Zennix

New version available.

  • Tested and working at startup
  • Tested and working with requested_state = 9
  • Offset tested and working
  • Tested and working. Commanded large 3,000,000 count move, and pressed home switch, which immediately stopped the motor and threw error 0x801

All tests completed on both axis0 and axis1. Active High and Active Low settings both tested

Hi Zennix, does this mean we will see the actuators in action very soon?


@Jerry, yes hopefully, that’s the missing thing. :crossed_fingers:

Thanks for your work. Here are my findings:

  1. GPIOs
    are correct.

  2. Homing

In [36]: odrv0.axis0.max_endstop.config
gpio_num = 6 (int)
enabled = True (bool)
offset = 0 (int)
is_active_high = False (bool)
debounce_ms = 100.0 (float)

In [37]: odrv0.axis0.min_endstop.config
gpio_num = 5 (int)
enabled = True (bool)
offset = -500 (int)
is_active_high = False (bool)
debounce_ms = 100.0 (float)

I double checked that the correct states are shown. Thank for integrating the states again.

In [44]: odrv0.axis0.min_endstop.endstop_state_
Out[44]: False

In [45]: odrv0.axis0.min_endstop.endstop_state_
Out[45]: True

After giving a:

odrv0.axis0.requested_state = AXIS_STATE_HOMING

The motor is spinning, but no reaction to the min or max switch.

  1. Emergency stop
    Want to test the moving but the commands didn’t move the motor anymore.
    AXIS_STATE_CLOSED_LOOP_CONTROL seems to be working, the motor holds it’s position.
    But no move.

Reconnected to ODrive 375F365A3137 as odrv0
In [54]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

In [55]: odrv0.axis0.controller.set_pos_setpoint = 0

In [56]: odrv0.axis0.controller.set_pos_setpoint = 1000

Seems that my version from 22th September isn’t the same as yours.

Greetings / Zennix

I did some additional testing.

GPIO 5 is my min_switch
GPIO 6 is my max_switch

Both GPIO states are shown correct.

pressed min_switch
In [28]: odrv0.axis0.min_endstop.endstop_state_
Out[28]: True
released min_switch
In [29]: odrv0.axis0.min_endstop.endstop_state_
Out[29]: False

pressed max_switch
In [30]: odrv0.axis0.max_endstop.endstop_state_
Out[30]: True
released max_switch
In [31]: odrv0.axis0.max_endstop.endstop_state_
Out[31]: False

  1. Homing
    GPIO5 is not recognised. Motor didn’t stop by pressing the min_switch

  2. Emergency stop

Reconnected to ODrive 375F365A3137 as odrv0
In [52]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
In [53]: odrv0.axis0.controller.set_pos_setpoint = 1000

has no effect. Motor is not spinning.

With an ASCII command the motor is spinning. The max_switch stops the motor. The min_switch has no effect.

Greetings / Zennix

odrv0.axis0.controller.set_pos_setpoint = 1000 does nothing

odrv0.axis0.controller.set_pos_setpoint(1000, 0, 0) or odrv0.axis0.controller.pos_setpoint = 1000 are the correct commands

I specifically tested GPIO5, so that’s weird. I will check the differences with ASCII commands but I don’t think that should have any difference from USB (just your incorrect command)

Oh Sorry :relaxed: You are right, thats the wrong command. I’m testing mostly with the ASCII interface.

Homing and emergency stop is working with GPIO 6 - 8. -> Great work!!! :clap:
GPIO 5 and 4 are recognised in AXIS_STATE_IDLE only. In AXIS_STATE_HOMING they have no effect.

For debouncing I had to add two caps 47nF between the GPIOs and GND.

I checked also if I can use one GPIO for both max_switches. That works. That stops both axis. :+1:

Thanks / Greetings / Zennix

Just updated to firmware 4.6, was hoping this would be in it, but I can’t seem to find odrv0.axis0.max_endstop. Any news on when this branch will be merged into the main branch?

1 Like


there is still a problem with GPIO less than 6. Could you verify that?
If you only need 3 switches your are fine. But some applications will need four switches and I can’t get these GPIOs to work.

Greetings / Zennix