One ODrive S1 does not work

I recently bought two S1. One works fine, but the second one’s motor never rotates during any call.

S1 serial: 144157578035

Power input: ~36.7 V, healthy bus shown in logs

Symptom: motor never rotates during any cal; both MOTOR_CALIBRATION and Hall cal steps complete instantly without motion

Key logs:

disarm_reason: ODriveError.CALIBRATION_ERROR

procedure_result: ProcedureResult.PHASE_RESISTANCE_OUT_OF_RANGE

Hall test (06b): repeated hall_state changes (1–6) when turning by hand → encoder wiring OK

Swap test: same motor + cable spin normally on S1 144157576504; fail the same way on 144157578035

Tried higher cal drive: calibration_current=20 A, resistance_calib_max_voltage=8 V → no change

Open-loop/lock-in unavailable on this FW; torque/current probes had no effect (axis stays NOT_CALIBRATED)

Hi! What specific motor are you using? As well, what’s your calibration current and voltage (config.motor.calibration_current and config.motor.resistance_calib_max_voltage, if using ODrivetool). As well, could you post some pictures of the top and bottom of the board?

We use a BLDC motor (a wheel from HOVER-1 hoverboard)
We do not use ODrivetool.
calibration_current = 10.0
Se the entire Python script attached. Also attaching pictures.
Please note that we bought two S1s and the other one works perfectly.



Here is the output of the script:
bis@ubuntu:~/Documents/Robot/ODrive$ python3 01_config_and_calibrate.py

  • Searching for ODrive…
  • Connected: 144157578035
    Applying configuration…
    Saving configuration (device will reboot)…
  • Searching for ODrive…
  • Connected: 144157578035
    Running motor calibration…
    Saving motor calibration…
  • Searching for ODrive…
  • Connected: 144157578035
    Running Hall polarity calibration…
    Running Hall phase calibration…
    Saving the configuration…
  • Searching for ODrive…
  • Connected: 144157578035
  • Searching for ODrive…
  • Connected: 144157578035
    Closed loop…

— Diagnostics —
axis0
active_errors: no error
disarm_reason: no error
procedure_result: ProcedureResult.NOT_CALIBRATED
last_drv_fault: none
internal issues: none
disarm_reason: 0
vbus: 36.620853424072266


Here is the script:

import time
from odrive.enums import AxisState, EncoderId, MotorType, ControlMode, InputMode
from odrv_common import connect, safe_save, diag

odrv = connect()

print(“Applying configuration…”)

---------- Motor ----------

odrv.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
odrv.axis0.config.motor.pole_pairs = 15 # 30 poles → 15 PP
odrv.axis0.config.motor.torque_constant = 8.27 / 15.0 # ≈0.551 Nm/A
odrv.axis0.config.motor.current_soft_max = 20.0 # replaces current_lim
odrv.axis0.config.motor.calibration_current = 10.0

---------- Hall encoder ----------

odrv.hall_encoder0.config.enabled = True # top-level object
try:
odrv.hall_encoder0.config.cpr = 6 * 15
except AttributeError:
pass # some versions derive this automatically

Attach Hall encoder to axis (both commutation & load)

odrv.axis0.config.commutation_encoder = EncoderId.HALL_ENCODER0
odrv.axis0.config.load_encoder = EncoderId.HALL_ENCODER0
odrv.axis0.config.encoder_bandwidth = 100

---------- Controller ----------

odrv.axis0.controller.config.control_mode = ControlMode.VELOCITY_CONTROL
odrv.axis0.controller.config.input_mode = InputMode.VEL_RAMP
odrv.axis0.controller.config.vel_limit = 10

---------- Bus protection (36 V pack) ----------

odrv.config.dc_bus_overvoltage_trip_level = 43.5

print(“Saving configuration (device will reboot)…”)
safe_save(odrv)

---------- Reconnect after reboot ----------

odrv = connect()

---------- Calibrate & test ----------

— Motor calibration (one-time per motor/wiring) —

print(“Running motor calibration…”)
odrv.axis0.requested_state = AxisState.MOTOR_CALIBRATION
while odrv.axis0.current_state != AxisState.IDLE:
time.sleep(0.05)

Verify calibration stuck (new flag replaces ‘pre_calibrated’)

try:
print(“motor R/L valid:”,
odrv.axis0.config.motor.phase_resistance_inductance_valid)
except AttributeError:
pass

print(“Saving motor calibration…”)
safe_save(odrv)

Reconnect after save

odrv = connect()

— Run Hall calibrations (one-time per configuration) —

print(“Running Hall polarity calibration…”)
odrv.axis0.requested_state = AxisState.ENCODER_HALL_POLARITY_CALIBRATION
while odrv.axis0.current_state != AxisState.IDLE:
time.sleep(0.05)

print(“Running Hall phase calibration…”)
odrv.axis0.requested_state = AxisState.ENCODER_HALL_PHASE_CALIBRATION
while odrv.axis0.current_state != AxisState.IDLE:
time.sleep(0.05)

Mark pre-calibrated if the field exists, then SAVE so the map persists

for attr in (“pre_calibrated”, “is_pre_calibrated”):
if hasattr(odrv.hall_encoder0.config, attr):
setattr(odrv.hall_encoder0.config, attr, True)

print(“Saving the configuration…”)
safe_save(odrv)

---------- End safely in IDLE; no auto-run on boot ----------

odrv = connect()
odrv.axis0.requested_state = AxisState.IDLE
odrv.axis0.config.startup_motor_calibration = False
odrv.axis0.config.startup_encoder_index_search = False
odrv.axis0.config.startup_encoder_offset_calibration = False
odrv.axis0.config.startup_closed_loop_control = False
safe_save(odrv)

Final quick closed-loop poke (like your original), then cancel

odrv = connect()
print(“Closed loop…”)
odrv.axis0.requested_state = AxisState.CLOSED_LOOP_CONTROL
odrv.axis0.controller.input_vel = 1.2 # gentle start
t0 = time.time()
while time.time() - t0 < 6.0:
if odrv.axis0.current_state == AxisState.IDLE:
break
time.sleep(0.05)

Stop & idle

odrv.axis0.controller.input_vel = 0.0
time.sleep(0.3)
odrv.axis0.requested_state = AxisState.IDLE

diag(odrv)

Hi, is me posting on this forum the right way of requesting the replacement? We are building a robot and kind of got stuck without this controller. Should I buy a new one an then request a refund for this not working one? Please let me know what to do to get it replaced. Thank you

Hi! Very sorry for missing your last post!! Been a very busy few days, apologies for this falling through the cracks.

Yes, we’ll absolutely get this replaced, sorry for the issues – I’m excited to dig into what the root cause is once the unit is returned to us. Could you send an email to info@odriverobotics.com with a link to this forum post, your original order number, as well as the best shipping address for the replacement? We can get this dispatched right away, and provide return instructions for the faulty unit.