odriverobotics / ODrive

High performance motor control
https://odriverobotics.com
MIT License
2.89k stars 1.5k forks source link

Add option to ignore endstops during startup #747

Open aaronjamt opened 3 months ago

aaronjamt commented 3 months ago

This is useful for devices where the endstop is pressed while power is off, due to gravity, springs, or otherwise. When the ODrive initially starts up, it sees the limit switch(es) pressed and disarms the motor(s) immediately. With this setting enabled, the limit switch will not cause the motor to disarm during inital startup, making the odrive.axis*.config.startup_* flags useful again.

As an example of a potential use case, I'm building a flight simulator, where the pod the rider sits is supported on 6 linear actuators. Each actuator has a lower endstop (odrive.axis*.min_endstop) and is configured with startup_encoder_index_search, startup_homing, and startup_closed_loop_control all enabled. However, currently, when powering on the machine, it needs 3 people to help hold the weight of the pod and a 4th operator to manually rotate the motors to lift each actuator off the endstops. Obviously, this is not ideal, and while there are potential solutions that we've thought of, the simplest (and, in my opinion, safest) is to just have it allow the startup sequence to run while the endstops are pressed. The settings for startup_encoder_index_search can be configured to make the actuators always move up, and then startup_homing takes over and moves the actuators away from the endstops.

If there are any concerns around this PR, I'd be happy to discuss them. As far as I can tell, using AXIS_STATE_UNDEFINED as a flag for initial startup seems to be correct, as it's used for that purpose in axis.cpp#458 and is used as the condition for the is_booting() variable in main.cpp#45-47.

CLAassistant commented 3 months ago

CLA assistant check
All committers have signed the CLA.

samuelsadok commented 3 months ago

Thanks for your contribution! This sounds like a reasonable use case.

As it is written currently, the endstops are edge triggered, so if the axis is just sitting on the endstop, it shouldn't trigger it. In other words, your use case should actually already be supported, the way the if condition is written, so if you ran into issues with it, it sounds like a bug and I would be interested to understand it.

Could you elaborate more what commands you ran and what behavior you observed? Specifically, when you just reboot the ODrive into idle (without the startup_* flags enabled), does dump_errors() show any endstop errors?

And just to make sure, you're using ODrive v3.6, correct? Because the newer (current generation) ODrives are not covered by this repository, see note here.

aaronjamt commented 3 months ago

Thanks for your contribution! This sounds like a reasonable use case.

As it is written currently, the endstops are edge triggered, so if the axis is just sitting on the endstop, it shouldn't trigger it. In other words, your use case should actually already be supported, the way the if condition is written, so if you ran into issues with it, it sounds like a bug and I would be interested to understand it.

I noticed that it appears to be edge triggered (checking .rose()) but it still seems to trigger on startup regardless.

Could you elaborate more what commands you ran and what behavior you observed? Specifically, when you just reboot the ODrive into idle (without the startup_* flags enabled), does dump_errors() show any endstop errors?

When I turn off all the startup_* flags, here's what happens (off memory, so I may have the names of the flags/states wrong, I apologize if so):

  1. Power up (then dump_errors(odrv0)): No errors
  2. Set .requested_state to AXIS_STATE_* (I believe I tried CLOSED_LOOP_CONTROL and HOMING, possibly also INDEX_SEARCH but not positive, may be able to test it tomorrow): Motors don't move and it immediately fails with MIN_ENDSTOP_PRESSED
  3. Run odrv0.clear_errors(): No errors again, motors remain idle
  4. Move one axis off bottom endstop and set requested_state again: it works fine, state is applied and operates normally

And just to make sure, you're using ODrive v3.6, correct? Because the newer (current generation) ODrives are not covered by this repository, see note here.

Yes, I'm using a V3.6 56V board (well, technically 3 boards for a total of 6 motors). I previously upgraded from the 24V boards, which I believe had the same issue, but am not 100% sure as I upgraded over a year ago and haven't used them since. Also, I noticed after submitting this PR that, for only 1 of my 3 ODrives, one axis would still fail on startup (a failure rate of 1 in 6), and after a bit more troubleshooting, I realized that it was actually failing during the index search, hence #748.