Avoiding calibration at startup

As mentioned on the Discord support channel, we at the Greppy team are making a 5 DoF robot arm integrated with ROS using 3 ODrives. Because of all the joint constraints & interactions, we can’t run calibration at every bootup. So we’re looking at doing the “Encoder Calibration” with “Encoder with Index signal” (following https://github.com/madcowswe/ODrive/tree/master/Firmware#encoder-with-index-signal )

I’d like to understand a bit more how this works. @madcowswe mentioned in the channel:

So there are two uncertainties that need to be calibrated out. One is what angle the encoder had when you mounted it to the motor shaft. There is no good way to do this repeatable enough, so it’s random, but stays the same once mounted: so we need to calibrate this once.

The other uncertainty is where is the encoder when the ODrive boots. […] The encoders are incremental so the ODrive doesn’t know where “0” is, the encoder only sends the equivalent of “+1, +1, +1, -1, +1”, etc, indicating that we moved one count up/down. We don’t make any assumptions about where the encoder is on startup, so we need to find out where it was. This is done with the index pulse. When the index pulse fires, that is “0”. So when we see it, we can start counting from there, and be correct.
finding where “0” is needs to be done at every startup, since we stop counting when shut down.

On boot the encoder count is just something, we don’t care. Then we find the index, at that time we reset the count and start from there. […] if we do this index search before we calibrate the 1st time, and then always do the index search on every bootup, then we can restore the calibration offset, because we know we are locked into the correct start-position, so the calibration is still valid

A couple follow up questions. The documentation says that “check that the motor scans for the index pulse but skips the encoder calibration”.

I’m guessing this means that there is still motion from the odrive on bootup?

Is there any way to call this manually, so our code could start it on odrive 1, then 2, then 3? Because all the odrive motors are connected to each other mechanically, having everything spinning at once on bootup can get a bit out of hand.

1 Like

When manually calibrated, motors will spin in one direction until the index pulse is found. You can choose which direction it turns. Maybe have it so that each axis always calibrates to a safe direction. Afaik a way to avoid this index pulse search altogether would be to use absolute sensors.

Another way to get rid of calibration would be a battery backup that keeps the position monitoring enabled when main supply is off. This way you’d maintain both calibration and even the position of the arm between each bootup.

btw is it possible to have ODrive powered from battery connected to AUX? It would be so sweet to have a small but powerful NiMH or LTO battery pack work as a dump load, power reserve and a backup battery at the same time :open_mouth:

1 Like

This will be available on firmware v0.4.0.

Nice @madcowswe – is there a branch it’s currently in?

If you want to take a look, the latest stuff on that is sam_oskar_testing. Note that this is not released and we can’t spend time on helping you if you have issues with it.

Just posting here for the next person.
You can now set this up (after you’ve gone through the full calibration once) by:

<odrv>.<axis>.motor.pre_calibrated = True
<odrv>.<axis>.encoder.pre_calibrated = True
<odrv>.<axis>.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION

You still need to have it do a couple of revolutions in the offset calibration, but heaps better than before.

Perhaps there’s also a way around this now too? It seems the <odrv>.<axis>.encoder.pre_calibrated = True isn’t working properly perhaps?

1 Like

Is there any good way around this or being able to jog the motor without having this parameter set (to ensure the motor doesn’t hit end stops)?

To avoid the calibration, should be searching for index on the subsequent boots. There is more information in the documentation.

We don’t yet have the ability to jog the motor (in an inefficient mode) before index has been found, but it’s a planned feature.

Thanks. Good to know. I guess I’ll just have to come up with some way to avoid it hitting end stops in the mean time

Hello @moorage I am also looking to avoid the Index Search while every power-up.
Is this solved in your system?

For my use-case, I was never able to get rid of the index search. However, I did notice that the hub motor version https://docs.odriverobotics.com/hoverboard.html doesn’t visually seem to have any index search at bootup.

Hello Moorage, thanks for the response.
This hub motor is already interfaced with a hall sensor, so they always know the index position of their encoder.
Might be that reason, why they don’t need Index Search.

Hey guys,

Just like to to chime in that I’ve set up my system to avoid index search entirely using the latest main release of the firmware with the AMT 203S absolute encoder connected to both the ODrive and my main controller (Teensy/Arduino) and having the main controller reading from the encoder and adjusting the .encoder params on the odrive over the ASCII protocol at startup.

If interested I can write out my pseudo-code in more detail.

Hello Lewis,
So latest release is having support for Absolute Encoder?
Or you are using TobinHall’s branch?

Not directly - but you can write to axis.encoder.circular_count(can’t remember exact param name - not at my workstation atm) and axis.encoder.is_ready on the latest release (previous releases prevented this).
I’m using an AMT203S encoder on the motor hooked up to my main controller (Teensy/Arduino) via SPI and to the ODrive via the A/B incremental pins.
On startup of the main controller I read the circular position of the encoder over SPI and write that value to odrv.axis.encoder.circular_count and set is_ready to true using the ASCII protocol.

Oh and it requires a one time calibration/alignment of the motor/encoder:

  • Set the motor to some stable initial position
  • Write this position to zero on the encoder (over SPI)
  • Then run the full calibration sequence using the odrive tool to generate the stored encoder.config.offset value
  • Save the configuration
  • the offset value is now set relative to your absolute encoder position!

Ensure your configuration was previously set to not use the index pulse in any way.

Now at startup you just need to set the circular_count and is_ready param and you can drive the bldc without any index_searching!

Works great if you don’t mind the overhead of a separate controller to talk to your encoders.

1 Like

Hi Lewis,

This looks awesome ! I would be interested to see your code !
I am looking to do the same with a raspberry pi to finally skip that calibration step with an absolute encoder.

Hey pak,

Sure - I’ll try to post it in the next week or so - it’s all bundled up in a project specific set of files for work at the moment - when I get the chance I’ll port it into a more palatable sketch or something and share that.

1 Like