Save encoder state in memory


#1

Hello guys

I am working on a six-axis robotic arm, and I am using BLDC’s in combination with incremental, 2400CPR encoders (no index).

Now I get that you need to calibrate the electrical phase difference between the encoder and the motor every boot, but it is kind of impossible to temporarily remove the load of the robotic arm on every boot. So calibrating the encoder is not possible on every boot.

Now I thought of this and I have designed my robotic arm so that it can not be moved in any way manually. This works because I use one-way transmission systems. So when I turn off the power and turn it back on again, there is no change of position possible. So I thought that I could log the offset, position, … values of the encoder, and manually place them back during startup (via a python program). But because is_ready is read only, I can not set it to True and as a result, I can not set the requested_state to closed loop control.

I don’t think that the calibration does something else because shadow_count does behave normally even when is_ready is False.

So my question is the following: Is there a way to still manually override the is_ready parameter?

If not, could I change the source code to build my own, custom firmware to add this functionality? If yes, where should I start changing the source code?

Much thanks in advance!


#2

There should be some instructions on using an index pulse on the docs page. You’ll need to do something similar, but without the index search. Tell the ODrive that motor and encoder are already calibrated. I forget exactly what the configs are, “is_calibrated” maybe?

If the startup sequencer doesn’t set is_ready if everything is set to pre_calibrated, then that’s something we should be able to change relatively quickly, but it should.


#3

odrv0.axis0.encoder.config.pre_calibrated is always True due to the saved config, but it does not change odrv0.axis0.encoder.is_ready during startup. Now I see that the offset (odrv0.axis0.encoder.config.offset) is being saved by the configuration. So the only problem is the fact that odrv0.axis0.encoder.is_ready is read-only.

I have an idea by adding a new odrv0.axis0.requested_state value that just changes the is_ready parameter from a firmware’s perspective. Or perhaps to add a new parameter so odrive knows to ignore the is_ready parameter and the fact that the encoder is not yet calibrated. Or to somehow make the is_ready parameter read-write.

Perhaps making this is_ready parameter read-write instead of read-only is an update to consider for the official firmware? Or to make a new parameter that tells the odrive that the position of the motor and encoder can’t be changed manually? The odrive could then ignore the fact that the encoder is never calibrated. Is there a place where I can suggest new features?

I will post an update about the custom firmware as soon as I have made a solution.


#4

So I still need to test it in the long run, but I think I have a temporarily solution:


The is_ready parameter was a make_protocol_ro_property(...). I changed this to a make_protocol_property(...) and it just worked. Now I can set the ‘read-only’ parameter and odrive thinks that the encoder is calibrated.

For anyone wanting to do this for themselves, just change this function in Firmware\MotorControl\encoder.hpp. But it is very, very important that you only force this parameter to be True if you have set the electrical phase manually to the last known values (so parameters like hall_state and offset) and that the encoder can not be manually moved. So this means that the external controller of the odrive needs to keep track of these values at all time. This isn’t a problem in my case, as I use a python program on my pc. If you don’t properly set these values, the motor will stall and eventually overheat.

If I have more time on my hands, I will look into programming a more elegant solution. Because just making this value read-write is not only dangerous but it also doesn’t make much sense.
The elegant solution means adding a function that is callable by the external controller that tells the odrive that the encoder can’t be moved manually. It then needs to set the encoder parameters with parameters you have given the function as it’s args and after that, it needs to set the is_ready parameter to True. It is still dangerous because it can’t check that those parameters are correct, but at least it gives us a proper way of doing this if you want to take the risk.


#6

I maybe could use an encoder with an index, but I don’t know if you may search for the index when under load (because the electrical phase is still unknown during boot). And I can’t really afford to let my robotic arm move on it’s own instead of by the computer simulation. It could lead to a hard stop.