I kept trying to run Sensorless using an Odrive v3.5-56V board, hoverboard motor, battery, etc. with 0.5.6 firmware, but it didn’t work. Please let me know how I can get it to run.
#!/usr/bin/env python3
import odrive
from odrive.enums import (
AXIS_STATE_FULL_CALIBRATION_SEQUENCE,
AXIS_STATE_CLOSED_LOOP_CONTROL
)
import time
import sys
# The location of DeviceLostException may vary depending on your odrive version.
# The following import covers most cases.
from odrive.libodrive import DeviceLostException
def main():
print("1) Finding ODrive…")
odrv0 = odrive.find_any()
print(f" Connected to ODrive {odrv0.serial_number}")
print("2) Clearing all errors…")
odrv0.clear_errors()
print("3) Running full calibration sequence…")
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
while odrv0.axis0.current_state != odrive.enums.AXIS_STATE_IDLE:
time.sleep(0.1)
print(" ✓ Calibration complete")
# Mark the motor as pre-calibrated
odrv0.axis0.motor.config.pre_calibrated = True
print("4) Saving configuration to EEPROM…")
try:
saved = odrv0.save_configuration()
print(" Saved:", saved)
except DeviceLostException:
print(" ⚠️ Expected: device disconnected during save_configuration()")
print("5) Rebooting ODrive…")
try:
odrv0.reboot()
except DeviceLostException:
print(" ⚠️ Expected: device disconnected during reboot()")
# Wait sufficiently before reconnecting
time.sleep(5)
print("6) Reconnecting to ODrive…")
odrv0 = odrive.find_any()
print(" Reconnected:", odrv0.serial_number)
# 7) Enable sensorless closed-loop control at runtime
print("7) Enabling sensorless closed-loop control…")
odrv0.axis0.config.enable_sensorless_mode = True
odrv0.axis0.config.startup_closed_loop_control = True
odrv0.clear_errors()
# 8) Switch to CLOSED_LOOP_CONTROL mode & issue speed command
print("8) Switching to CLOSED_LOOP_CONTROL at 10 rev/s")
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
odrv0.axis0.controller.input_vel = 10.0
print(" ▶ Motor should now spin (press Ctrl+C to stop)…")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n9) Stopping motor and returning to IDLE…")
odrv0.axis0.controller.input_vel = 0.0
odrv0.axis0.requested_state = odrive.enums.AXIS_STATE_IDLE
sys.exit(0)
if __name__ == "__main__":
main()
Hi - can you show how you’re setting up the ODrive from scratch? You’re missing a lot of motor and ODrive configuration (see here Getting Started — ODrive Documentation 0.5.6 documentation).
Also note sensorless doesn’t support position control, only velocity or torque control, and has a minimum speed limitation. What’s the exact task you’re trying to accomplish?
The exact thing I’m going to do at the moment is drive the motor sensorless first. If this worked, I’d drive the motor using the hall sensor installed in the motor.
However, after many attempts, I couldn’t run the motor. So, I tried it based on various references, such as chatgpt, YouTube videos below, and so on, but I still couldn’t run it.
So, could you tell me how to drive the motor sensorless?
I really want to drive the motor.
RoboDog Part 6 | How to Use ODrive BLDC Motor Controller
I’d definitely not recommend ChatGPT, it’s almost always wrong about ODrive commands 
Sensorless control has some more considerations and can be a bit harder to get set up if you’re just starting out. I’d recommend starting with hall sensors at first, we have a hoverboard guide here: Hoverboard motor and remote control setup guide — ODrive Documentation 0.5.6 documentation
Thank you for your information. As you advised, I ran it by referring to the site data and found the following error phenomenon.
In this case, I wonder if it’s a firmware problem.
For your information, I executed it with the code below.
#!/usr/bin/env python3
import time
import odrive
from odrive.enums import AxisState, MotorType, EncoderMode, ControlMode
from odrive.utils import dump_errors
from odrive.libodrive import DeviceLostException
def safe_save(odrv):
“”"
Save current configuration to EEPROM (save_configuration),
then automatically handle the device rebooting and reconnecting
(DeviceLostException).
“”"
try:
odrv.save_configuration()
except DeviceLostException:
print(“
Configuration saved, device is rebooting…”)
time.sleep(5) # Wait for board to reboot and reconnect
odrv = odrive.find_any()
print(f"
Reconnected to ODrive {odrv.serial_number}")
return odrv
def main():
# 1) Find ODrive & assign Axis
print(“
Searching for ODrive…”)
odrv0 = odrive.find_any()
print(f"
Connected to ODrive {odrv0.serial_number}")
axis0 = odrv0.axis0
# 2) Clear errors & check bus voltage
odrv0.clear_errors()
print("🔎 VBUS voltage:", odrv0.vbus_voltage) # Typically 24–56 V
# 3) Configure brake resistor (50 W, 2 Ω)
odrv0.config.enable_brake_resistor = True
odrv0.config.brake_resistance = 2.0
odrv0.config.dc_max_negative_current = -25.0
odrv0 = safe_save(odrv0)
axis0 = odrv0.axis0
# 4) Set motor parameters
axis0.motor.config.motor_type = MotorType.HIGH_CURRENT
axis0.motor.config.pole_pairs = 15
axis0.motor.config.calibration_current = 5.0
axis0.motor.config.requested_current_range = 25.0
axis0.motor.config.current_control_bandwidth = 150.0
axis0.motor.config.resistance_calib_max_voltage = 10.0
axis0.motor.config.torque_constant = 8.27 / 16.0
# 5) Configure Hall encoder
axis0.encoder.config.mode = EncoderMode.HALL
axis0.encoder.config.cpr = axis0.motor.config.pole_pairs * 6 # 15 × 6 = 90
axis0.encoder.config.calib_scan_distance = 150.0
axis0.encoder.config.bandwidth = 100.0
axis0.encoder.config.pre_calibrated = False
axis0.encoder.config.ignore_illegal_hall_state = True
# 6) Set controller gains & mode
axis0.controller.config.pos_gain = 1.0
axis0.controller.config.vel_gain = (
0.02
* axis0.motor.config.torque_constant
* axis0.encoder.config.cpr
)
axis0.controller.config.vel_integrator_gain = (
0.1
* axis0.motor.config.torque_constant
* axis0.encoder.config.cpr
)
axis0.controller.config.vel_limit = 10.0
axis0.controller.config.control_mode = ControlMode.VELOCITY_CONTROL
# Save all settings to EEPROM once
odrv0 = safe_save(odrv0)
axis0 = odrv0.axis0
# 7) Calibration sequence
odrv0.clear_errors()
print("🔧 MOTOR_CALIBRATION…")
axis0.requested_state = AxisState.MOTOR_CALIBRATION
while axis0.current_state != AxisState.IDLE:
time.sleep(0.1)
print("🔧 ENCODER_HALL_POLARITY_CALIBRATION…")
axis0.requested_state = AxisState.ENCODER_HALL_POLARITY_CALIBRATION
while axis0.current_state != AxisState.IDLE:
time.sleep(0.1)
print("🔧 ENCODER_OFFSET_CALIBRATION…")
axis0.requested_state = AxisState.ENCODER_OFFSET_CALIBRATION
while axis0.current_state != AxisState.IDLE:
time.sleep(0.1)
# Mark calibration complete & save
axis0.motor.config.pre_calibrated = True
axis0.encoder.config.pre_calibrated = True
odrv0 = safe_save(odrv0)
axis0 = odrv0.axis0
# 8) Enter closed-loop control & run speed test
odrv0.clear_errors()
print("⚙️ Entering CLOSED_LOOP_CONTROL…")
axis0.requested_state = AxisState.CLOSED_LOOP_CONTROL
time.sleep(0.5)
print("⚙️ Spinning at vel = 2 …")
axis0.controller.input_vel = 2.0
time.sleep(2.0)
# Stop and return to IDLE
axis0.controller.input_vel = 0.0
axis0.requested_state = AxisState.IDLE
# 9) Final state check
time.sleep(1.0)
print("🔎 Final check:")
print(" • vbus_voltage:", odrv0.vbus_voltage)
print(" • vel_estimate:", axis0.encoder.vel_estimate)
print(" • Iq_measured:", axis0.motor.current_control.Iq_measured)
print(" • Error dump:")
dump_errors(odrv0)
if name == “main”:
main()
You need to run HALL_PHASE_CALIBRATION instead of ENCODER_OFFSET_CALIBRATION when using hall sensors.
After you put it in CLOSED_LOOP_CONTROL and assign the input_vel, I’d recommend running dump_errors(odrv0) then.