I just stumbled on ODrive yesterday and I’m already totally floored by the demos. I cloned the repos right away and stared at the firmware code, looking specifically for the calibration of electrical phase with incremental encoders. From a fortunate misunderstanding, I tried to wrap my head around the inductance estimating routine measure_phase_inductance, thinking that an inductance vs. shaft angle relationship was used to measure initial electrical phase. While I stumbled upon calib_enc_offset a little later and realized inductance was instead used to tune the control gains, I’m still invested in understanding the inductance measurement here, as I’m trying an inductance-based calibration method in a DIY motor controller of my own. (I plan to use this in a bipedal robot where there are significant static loads at startup so I’m trying to avoid moving the motor much to extract the initial angle).

I come from an AVR background and will profess I’m not at all familiar with the STM32 and its peripheral interface, so I apologize if the code answers these questions amply already. I wanted to better understand the following:

How is dI/dt estimated? My guess is the magnitude of steady-state current ripple from a voltage pulse train through one of the output phases. The timings of the current measurements on each end of the dI look like they’re right on transitions between forward and reverse voltages, with an effective inductor voltage that looks like the steady-state mean: 0.5f * (voltage_high - voltage_low).

How reliable is this inductance estimate? In my tests of coil inductance vs. phase angle, the inductance varies around 20% peak-to-peak, so I’m hoping to discriminate in the uH regime. With a hefty number of samples (5000 by default!), what is the main contributor to imprecision if any?

it’s not measuring the inductance, it’s measuring how much current it takes to move the motor at different angles.

Because it has a very reliable position indicator (the encoder), it can force the motor to a known position (driving it like a stepper to get it into place), and then gradually shift the signals, and measure the effect by the movement of the encoder.

Am I correct to recognize that you’re describing calib_enc_offset? I’m interested in understanding the entirely different measure_phase_inductance routine, but just mentioned calibration to justify my interest in it with [maybe too-colorful of] a backstory…

Yes I think you understand the inductance measurement correctly, but just in case, let me say how it works in my own words:

So as you may know, we have the equation L * dI/dt = V, which we rearrange into L = V / (dI/dt). As you correctly ascertained, we send a square wave of voltage in, and look at the resulting triangle wave of current. We estimate dI/dt by discrete time delta_I / timestep, and also average over all the samples. The voltage we have to be careful: in this equation it’s the voltage across the inductor, which is equal to the voltage deflection from the average, since the average voltage is taken up by the resistance V_R = I * R. I’ll leve it to you to verify that the equation we have for V_L is indeed the square wave amplitude away from the average.

Like you saw, the number of samples is very large, so the precision is actually really good. When I first wrote this function, I did a test on some regular hobby motors, and I could clearly see the inductance variation as a function of rotor angle. The main source of error is any systematic error in the current sensing or timing, but yeah if you can calibrate that away by say computing reference values from a known motor, I would say your rotor angle observation idea is likely to work, if such an inductance variation is present in the motor over angle.