Summary
On an ODrive v3.5 24V, ENCODER_HALL_POLARITY_CALIBRATION fails with EncoderError.ILLEGAL_HALL_STATE (error 16) on axis 0 only. Axis 1 calibrates and runs perfectly. Swapping the two motors between channels does not move the problem — it stubbornly stays on axis 0.
Hall signals are provably clean at standstill. The failure only occurs while the motor is driven. I’ve run a systematic set of tests and narrowed it down to what looks like a localized hardware/grounding anomaly on Axis 0.
Setup
| Item | Value |
|---|---|
| Board | ODrive v3.5, hw_version_variant = 24 |
| Firmware | reports 0.0.0, fw_version_unreleased = 1 |
| Host tool | odrive Python package 0.6.11.post1, Python 3.14.7, Windows |
| Motors | two identical 24V hoverboard hub motors (Model: WT25HB24V20180124) |
| Pole pairs | 15 (measured: 91 hall transitions per mechanical revolution) |
| Supply | 7S Li-ion → XL4016 buck converter → 22.0–22.1 V |
| Brake resistor | none, enable_brake_resistor = False |
Relevant config, identical on both axes:
encoder.config.mode = 1 (HALL)
encoder.config.cpr = 90
motor.config.pole_pairs = 15
encoder.config.calib_scan_distance = 150
encoder.config.bandwidth = 100
gpio9/10/11 and gpio12/13/14 mode = 0 (DIGITAL)
config.dc_bus_overvoltage_trip_level = 24.5
config.dc_max_negative_current = -1.0
Symptom
Axis 1 — full sequence succeeds:
MOTOR_CALIBRATION OK R = 0.1745 Ω L = 304 µH
ENCODER_HALL_POLARITY_CALIBRATION OK hall_polarity = 0
ENCODER_OFFSET_CALIBRATION OK phase_offset = 75, direction = 1
Closed loop velocity control verified at 1.0 and 1.5 turn/s, tracking within 1%.
Axis 0 — motor calibration fine, polarity calibration always fails:
MOTOR_CALIBRATION OK R = 0.1784 Ω L = 310 µH
ENCODER_HALL_POLARITY_CALIBRATION FAIL after 4.0 s
encoder.error = 16 (ILLEGAL_HALL_STATE)
ibus peak 1.17 A — the motor does spin
Key Troubleshooting Tests & Findings
- Hall signal quality at standstill: Hand-turning the wheel gives a perfect 120° Gray code (187 transitions sampled via
get_gpio_states(), zero illegal states). Pull-ups are working fine on all 6 pins. - Motor swap: Moving phases and halls together to the other channel proved that the issue stays on Axis 0. Both motors work flawlessly on Axis 1.
- Hardware Errata check: Verified that
axis0.encoder.hall_statestrictly maps to GPIO 9/10/11. The known silkscreen label swap errata does not apply here. - Hardware Filters: Added 22 nF ceramic capacitors between all 6 hall lines and GND close to J4. It made absolutely no difference for Axis 0.
- The Cross-Axis Smoking Gun: When driving Axis 0, Axis 1 (stationary) immediately gets pulled into an ILLEGAL_HALL_STATE (111). Conversely, driving Axis 1 leaves Axis 0 perfectly stable at error 0. Because Hall sensors are open-collector, reading
111means they lost their ability to pull low, suggesting a major localized ground bounce or 5V rail shift near Axis 0 during PWM cycles. - The Current Loop Clue: Looking at current loop noise during lockin commands, I noticed a massive asymmetry in the current sensing calibration offsets:
axis1.DC_calib_phC= -0.148axis0.DC_calib_phC= -1.107 ← Massive 1.1V negative offset discrepancy on Phase C.
Current Hypotheses & Questions
The massive -1.107 offset on Axis 0 Phase C suggests a damaged current sense shunt amplifier (e.g., OPA365) or a micro-crack/cold solder joint on Phase C’s shunt resistor. This likely forces the SVPWM algorithm to aggressively distort voltage vectors to compensate for a ghost current, creating massive localized EMI or localized ground lifting that triggers the 111 illegal state.
Since I am planning to upgrade this project to a 4-Wheel Drive (4WD) architecture using a second ODrive v3.5 board over CAN bus, I need to get this axis sorted out.
- Has anyone seen such a large
DC_caliboffset anomaly before, and is it a known failure mode for the shunt op-amps on legacy v3.5 boards? - Since
pre_calibrated = Trueis rejected by the firmware unless a successful calibration routine finishes, would the cleanest workaround be to comment out theILLEGAL_HALL_STATEsafety check inencoder.cppand flash a custom firmware? - Any layout advice when wiring two ODrive v3.5 boards together to a master MCU via CAN to prevent cross-board ground loops from making this worse?
Thanks for your insights!