Well I am not sure if the velocity LPF is of concern here. The point I am making is : Ignoring the noise in the encoder sensing, given the sampling rate of the rotor angle (100us for loopFOC()), the encoder resolution (22mdeg/LSB), the motor needs to have turned with an average speed of 220 deg/s to register one LSB on the encoder. Given that gimbal motors operate in speed regimes slower than this, implementation of current feedforward might not work as well since the computed speed will be zero for many cycles.
The velocity LPF only serves to smooth out the effect of encoder noise due to differentiation of rotor angle.
The lowpass filter is like a running average, so even if you only get one encoder tick every few frames, the filtered velocity will remain non-zero. You could even adjust the time factor on the fly, for a more stable value at low speed and better response time at high speed.
Tried both the pole placement and low side sensing and the results are surprisingly much better. Basically, the motor we have has R = 8.5ohm and L = 33mH. The following current loop gains are set for a 300Hz bandwidth :
Kp ~ 62, Ki ~ 16022
The filter bandwidth is chosen to be 4 times the current loop bandwidth so tf is set to 0.00013.
Here’s a plot of Iq current with the rotor locked.
With low side current sense, the loopFOC takes 25us (!) compared to 132 us with inline current sensing. We had tried the pole placement earlier, but the slower sampling rate of inline current sensing meant that bandwidth could not be achieved and resulted in the motor making a lot of noise when running the current loop.
The bandwidth achieved is well over 300 Hz, mostly since the L value I am not sure is accurate, but this is sufficient for our purposes.
If the loopFOC takes 25us = 40kHz, and the PWM freq is set to 25kHz, this doesn’t seem right. I think the PWM should be 3-4 times faster than the current loop?
Btw, to generate the plot above, we keep the rotor locked and run only the FOC current mode and run through a bunch of Iq commands. The signals are logged to an array with a timestamp (using micros()) and then played back after the test, so the 25uS is probably accurate. This is an automatic sequence so it’s repeatable thing.