Absolute encoder AMT203-V and Odrive without startup ENCODER_OFFSET_CALIBRATION

I’m trying to connect the absolute encoder AMT203-V to ODRIVE via Arduino as wrote Lewis_Siempelkamp (https://discourse.odriverobotics.com/u/lewis_siempelkamp/summary)
but I’m having trouble - the motor torque is much less than expected, I guess I didn’t take into account the offset changing

I know that maybe absolute encoder support will soon be in the firmware of Odrive, but I’d like to figure out how it works myself.

Could you look at my code and tell me what’s wrong?
I managed to connect an encoder. ODrive sees it and I can control it via Arduino.
But I’m not quite sure how to set up the correct encoder.offset to make things work.

I rebuilt the firmware with the changes in ascii_protocol.cpp (added a new command to set set_linear_count via Arduino)

if (cmd[0] == 'e') { 
        unsigned motor_number;
        int value;
        int numscan = sscanf(cmd, "e %u %i", &motor_number, &value);
        if (numscan < 2) {
            respond(response_channel, use_checksum, "invalid command format");
        } else if (motor_number >= AXIS_COUNT) {
            respond(response_channel, use_checksum, "invalid motor %u", motor_number);
        } else {
            Axis* axis = axes[motor_number];


I connected the AMT203-V encoder to the ODrive with the N5065 motor

and performed initial initialization by
and saved the settings using odrv0.save_configuration()
at json, I got the following

“axis0”: {
“config”: {
“startup_motor_calibration”: false,
“startup_encoder_index_search”: false,
“startup_encoder_offset_calibration”: false,
“startup_closed_loop_control”: false,
“startup_sensorless_control”: false,
“enable_step_dir”: false,
“counts_per_step”: 2,
“watchdog_timeout”: 0,
“step_gpio_pin”: 1,
“dir_gpio_pin”: 2

“encoder”: {
“config”: {
“mode”: 0,
“use_index”: false,
“find_idx_on_lockin_only”: false,
“pre_calibrated”: false,
“zero_count_on_find_idx”: true,
“cpr”: 4096,
“offset”: 7063,
“offset_float”: 1.1783593893051147,
“enable_phase_interpolation”: true,
“bandwidth”: 1000,
“calib_range”: 0.019999999552965164,
“calib_scan_distance”: 50.26548385620117,
“calib_scan_omega”: 12.566370964050293,
“idx_search_unidirectional”: false,
“ignore_illegal_hall_state”: false

In addition, I set the encoder to zero with the Arduino command

   SPI.begin();    //start transmition
   SPI_T(0x70);   // set to zero command              
   digitalWrite(CS,HIGH);  //just to make sure   
   SPI.end();    //end transmition     

Below is a part of the code from the .ino file and startup procedure without ENCODER_OFFSET_CALIBRATION

  1. I’m turning on the Odrive and the Arduino
  2. then I’m sending a command to initialize the motor

odrive_serial.run_state(0, ODriveArduino::AXIS_STATE_MOTOR_CALIBRATION, true);

  1. I initialize the encoder via SPI and get its position, let’s say it’s 100 out of 4096


  1. Writing down linear_count
 odrive_serial << "e " << 0 << encpos;    
  1. turning on encoder.is_ready=true
 odrive_serial << "w axis" << 0 << ".encoder.is_ready " << 1 << '\n';
 odrive.run_state(0, ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL, false);

Until I turn off the ODrive, everything works and CLOSED_LOOP_CONTROL keeps the motor in place with sufficient torque
But after switching ODrive off and then on and initializing by these items (1-6)
is_ready is not set immediately = True but only after a few attempts
And the torque on the motor is less than after normal initialization.
I think I forgot to take the offset into account somehow, but I saved the Odrive configuration and it shouldn’t change

And there’s another question. If I know the encoder position and have saved the configuration, can I do without AXIS_STATE_MOTOR_CALIBRATION ?

Thanks in advance

Hi Mirage_2142,

Sorry I missed this one. The AMT203 isn’t really supported, but I can help you out. I also have an AMT203 driver for the ODrive here: https://github.com/Wetmelon/ODrive/tree/feature/amt20/Firmware/Encoders

So for an absolute encoder your process is:

  1. odrv0.erase_configuration()
  2. Motor Calibration
  3. Encoder offset calibration
  4. Set motor.config.pre_calibrated = True
  5. Set encoder.config.pre_calibrated = True
  6. Save & reboot

As long as you don’t physically move the encoder on the shaft of the motor, the offset won’t change (you don’t have to do anything with set_linear_count)

If you’re not using RazorsEdge firmware, the is_ready won’t work for absolute encoders, which may be a problem.