I get error code 2 with the encoder while using a scooter motor

Hello,

I recently got a new ODrive 3.6 and have connected my scooter motor with hall sensor to axis 1. I am trying to set it up such that I can control the torque applied by the motor. But when I try to set it up I get an error in the encoder.

This is the error I get.
EncoderError.CPR_POLEPAIRS_MISMATCH

I have tried all the possible pole pairs from 13 to 30 with the following script:

import odrive
import time
import tqdm

import odrive.enums

def checkOdrive(polePiars):
    print("Pole Piars:", polePiars)
    odrv0 = odrive.find_any()
    print("Connected!!")
    try:
        odrv0.erase_configuration()
    except:
        pass
    time.sleep(5)
    print("Erased!!")

    odrv0 = odrive.find_any()
    print("Connected Again.")
    odrv0.config.enable_brake_resistor = True
    odrv0.config.brake_resistance = 2.05
    odrv0.axis0.motor.config.pole_pairs = polePiars

    odrv0.axis1.motor.config.resistance_calib_max_voltage = 4
    odrv0.axis1.motor.config.requested_current_range = 25 #Requires config save and reboot
    odrv0.axis1.motor.config.current_control_bandwidth = 100
    odrv0.axis1.motor.config.torque_constant = 8.27 / 100

    odrv0.axis1.encoder.config.mode = odrive.enums.EncoderMode.HALL
    odrv0.axis1.encoder.config.cpr = polePiars * 6
    odrv0.axis1.encoder.config.calib_scan_distance = 150
    odrv0.config.gpio9_mode = odrive.enums.GpioMode.DIGITAL
    odrv0.config.gpio10_mode = odrive.enums.GpioMode.DIGITAL
    odrv0.config.gpio11_mode = odrive.enums.GpioMode.DIGITAL

    odrv0.axis1.encoder.config.bandwidth = 100
    odrv0.axis1.controller.config.pos_gain = 1
    odrv0.axis1.controller.config.vel_gain = 0.02 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
    odrv0.axis1.controller.config.vel_integrator_gain = 0.1 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
    odrv0.axis1.controller.config.vel_limit = 10
    odrv0.axis1.controller.config.control_mode = odrive.enums.ControlMode.VELOCITY_CONTROL
    print("Confiigured!!")
    try:
        odrv0.save_configuration()
    except:
        pass
    time.sleep(5)
    print("Saved")
    odrv0 = odrive.find_any()
    print("Found Again!!")
    odrv0.axis1.requested_state = odrive.enums.AxisState.MOTOR_CALIBRATION
    time.sleep(10)
    print("Motor error:", odrv0.axis1.motor.error)

    odrv0.axis1.motor.config.pre_calibrated = True
    
    odrv0.axis1.requested_state = odrive.enums.AxisState.ENCODER_HALL_POLARITY_CALIBRATION
    time.sleep(15)
    odrv0.axis1.encoder.error
    print("Hall error 1:", odrv0.axis1.encoder.error)

    odrv0.axis1.requested_state = odrive.enums.AxisState.ENCODER_OFFSET_CALIBRATION
    time.sleep(15)
    odrv0.axis1.encoder.error
    print("Hall error 2", odrv0.axis1.encoder.error)

    if (odrv0.axis1.encoder.error == 0):
        print("Success:", polePiars)

    odrv0.axis1.encoder.config.pre_calibrated = True
    print("DONE!!!!!!!!!!!!!!!!!!!!!!!")

if __name__ == "__main__":
    for idx in range(13, 40):
        checkOdrive(idx)

Here is a picture of the motor:

Can someone help me with this?

Thanks

Hi! Thanks for all the information, it really helps when diagnosing the issue :slight_smile:

This is definitely a 15 pole pair motor – no doubt about that, so you can just settle on that value.

First, check to make sure that odrive.enums.EncoderMode.HALL has the value of 1.

Second, check to make sure the ODrive is using the newest firmware – should be 0.5.6. You can check with odrv0.fw_version_minor and odrv0.fw_version_revision – should be 5 and 6 respectively to correspond with 0.5.6. Would recommend updating the firmware if it’s old.

Third, are you using 22nF capacitors on your hall lines? What about ferrite rings?

Fourth, when running encoder calibration, is the motor 100% free spinning? With no load whatsoever?

Thanks,

I have updated the firmware to 0.5.6
odrive.enums.EncoderMode.HALL has a value of 1
I do not have any ferrite rings on the signal wires. I have added 44nF capacitors between the signal lines and ground.
The rotor is integrated with the wheel and is very heavy. It is free to move but requires a lot of torque to spin.

I guess it is the weight of the rotor that is causing the issue. Is there a way I can increase the current used while calibrating the motor? Some way to avoid the problems caused by the inertia of the rotor?

Try changing odrv0.axis1.config.calibration_lockin.current to the maximum current of your motor (usually around 15A), then re-run the calibration. Could you take a video of it running the calibration and upload somewhere (e.g. youtube unlisted) and link the video here?

Thanks for the help. I was able to get it working on axis 1. But running the same configuration on axis 0 results in encoder error 16. I want to be able use both the axes.

Is there something I am missing. It is the same motor that I change to axis 0 and it gives the following:
AXIS_STATE_ENCODER_HALL_POLARITY_CALIBRATION
Error: encoder state 16, Invalid state

Sometimes those scooter motors can be kinda crappy, you can try this ODrive Reference — ODrive Documentation 0.5.6 documentation

Though I’m assuming this is with 22-44nF capacitors? If not I’d definitely add those. A ferrite ring would also be good.

Forgot to update. I was able to get it working. I added a few larger capacitors and added a torroids. The main things was that the wires were too close and there was some noise on the signal wires. Moving them away did the trick.

Great to hear! Yeah, that makes sense!