I am using sFOC shield to implement stabilization of a 2 axis gimbal. I have a gyroscope on the inner gimbal, so the sFOC shield with an STM32 is running a custom velocity loop with the gyroscope, with the sFOC torque mode set to use FOC current mode.
In order to get good speed tracking for a single axis, I started by first tuning the current loop. Since I couldn’t get accurate time stamps with simple FOC studio, I added monitor_port->print(micros(), 0); before printing of the Iq. Then keeping the motor fixed, current loop setpoints are given to obtain plots as shown below.
This gives an estimate of the current loop bandwidth, which from the above figure is approx. 74Hz.
rise time ~ 4.26ms => time const = 4.26/2 ~ 2.12ms => w_bw = 470 rad/s ~ 74Hz. These responses are with P = 50, I = 3800. I am trying to increase the current loop bandwidth to > 100 Hz, so I tried playing with the q axis PI controller gains (d axis PI gains are set to same values as q axis gains always) to do this, but at higher gains, I see higher overshoot, oscillations in the current response, as well as increasing audible noise from the motor. The current loop filter is set to 0.01, which I suspect may be playing a part in restricting the achievable bandwidth.
My setup is :
sFOC version : v2.3.2
Motor : GM110-8 Gimbal Motor. This comes with AS5048A encoder which I am using in PWM mode for FOC, and the encoder measurements are not being used anywhere else. The measured line-to-line resistance and inductance is 17Ohm and 23mH. Since this is a star winding, the phase resistance value being used while creating the motor class is set to 8.5Ohm.
I would appreciate help to see if I may be doing this incorrectly or if I am missing something fundamental. If it helps, I am using inline current sensing at the moment. Is the high value of the inductance a contributor here?
There’s 2 options, really. Increase the current loop bandwidth and filter cutoff frequencies, or implement some feed forward or pmsm decoupling.
It’s pretty easy to get a bandwidth of a few hundred hertz, but the downsides you already noted still apply, mainly related to noise. That GitHub link explains quite well.
With feed forward we can do much higher frequencies with a low controller bandwidth. I’ve done some experimentation with this, and the problem I’ve found is that the velocity estimate we currently do isn’t really good enough. I did a little experimentation with a flux observer to estimate the velocity using current sensing and it was much better, but doesn’t really fit into how the library works at the moment.
Thanks @Candas1 for the link. I’ll have a look. @Copper280z Got your point about setting current loop gain and filter bandwidths concurrently to get overall current control bandwidth.
By feedforward, do you mean a feedforward term in the current controller? Also, for the purposes of stabilization, I am not using encoder derived velocity, but using gyro measurements in the speed control which provides setpoint for the current controller.
Yes, feedforward in the current controller. For example you can use ohms law for steady state to calculate the voltage required for a given current based on phase resistance, you can also use the kv or torque constant to calculate the BEMF at the current shaft velocity and add that in, in order to reduce the amount you rely on the current controller to do.
Interesting idea. Use the voltage-based torque control even in foc_current mode, so the current PID only corrects the spikes from dynamic effects. I’d love to see some data plotting from that, to get an idea how much benefit you really get from current sensors.
Yes, exactly. If you’re after high dynamics it’s a huge change, as otherwise you’re waiting on the current controller integrator to build up to start making torque, then the motor starts turning. Voltage mode on it’s own has real downsides though, as you’re relying on your model being perfect, and it never is. With a FF path from motion profile to winding voltage the motor starts turning pretty much right at the instant the profile starts without any error building up. The combination really is the best of both worlds.
@Copper280z great thanks for the inputs. With regard to feedforward, these will be implemented on the q-axis current controller right? No change to the d-axis PID. Is this a correct interpretation?
Another thing to consider is that the current sensing noise is a limiting factor in how much the current controller can be pushed. So maybe a simple kalman filter to produce a smooth current signal that could be used instead of the direct measurement would help to increase the current loop bandwidth further.
It’s not clear that a kalman filter is the correct tool for this particular job, you’re not really using it for sensor fusion or using the input to help predict the next value.
With nothing special I’ve had current controllers tuned to between 300Hz and 2kHz bandwidth.
I am a bit unsure of implementing FF on both axes. My interpretation is that q-axis is the torque producing component of current, while d axis current is constrained to be zero always to maintain orthogonality between the stator and rotor magnetic fields. If FF is only done for the q-axis, then Ohm’s law and BEMF relations could be used. Not sure what FF would look like for the d-axis. Am I missing something here?
Secondly, a simple KF could be used where process model uses the q-axis equation as given here (How to Model Brushless Electric Motors for the Design of Lightweight Robotic Systems , See (39)). The current sensor can be treated as a measurement eqn as Iq_measured = Iq_true + noise. This requires knowing the parameters as given in the equation. Looks like this could produce a smooth version of the q-axis current. Again, I am not sure if a similar KF needs to be run for the d-axis current too.
Finally, 300Hz-2kHz bandwidths are with sFOC shield board? since that is what I am using.
I’ve done 300-500hz with the sfoc shield and stm32, and 2khz with a teensy driving a drv8302. The lower bandwidth wasn’t because of any limitation, I just didn’t need more.
Cool. I’m currently using the sfoc shield with a nucleo board. I am aiming for atleast 500 Hz current bandwidth, and presently am getting ~250Hz, with the limitation arising from the LPF time constant and the current sense noise. I checked the Vq being commanded and it was saturated to 24V (the supply voltage) only for a short while when responding to a step input, so I suspect there might be improvement possible. Would appreciate help/refs on the equations for feedforward implementation. Are the FF terms the same as what @Candas1 mentioned here ?([FEATURE] Foc_current mode and Current feed forward · Issue #317 · simplefoc/Arduino-FOC · GitHub)
We already have the math implementation in voltage mode with estimation here and here.
But we wanted to first prove it’s worth adding this to foc_current mode.
Maybe it’s the right opportunity now.