Closed pattacini closed 1 year ago
We may start off with a simple implementation where we just stick to the nominal current, w/o having access to those parameters that will need to be transmitted over CAN.
@mfussi66 can deal with this task, while I can act as a tutor.
Eventually, with the i2t implemented, we will be able to increase the current thresholds (overload, peak).
cc @maggia80 @sgiraz @Nicogene
Aside from the standard approaches reported in the OP, I have recently come across an interesting variant described in a technical note[^1] of the Faulhaber motors where a thermal model is employed.
Essentially, the Faulhaber motors equipped with an integrated Speed-Controller (SC)[^2] can enable the i2t
protection according to the rules reported in the screenshot above. The key point is to resort to an internal model of how the temperature evolves because of the dissipation, once we know the thermal resistance ($R_t$) and the time constants ($\tau$).
These latter parameters ($R_t$ and $\tau$) are described in the technical manual[^3]:
and reported in some datasheets (not all, unfortunately):
Given all this, we may consider implementing the thermal circuit below (just an example):
We know the thermal "current", which is $R_L \cdot i^2$, so we can find the temperature variation by:
$$ \Delta T = \frac{RLi^2 \cdot R{t1}}{R{t1} + R{t2}}. $$
Finally, we can filter this temperature setpoint with a first-order filter characterized by the time constant $\tau$. When the temperature $T$ reaches $T{crit}$ we limit the current to $I{nominal}$ instead of $I_{peak}$ until the moment when $T$ goes down below another threshold.
I like this approach, but we may miss sometimes from the datasheet the thermal constants ($Rt$ and $\tau$) and the critical temperature $T{crit}$[^4]. although we can ask Faulhaber for them.
Regarding our motor, the datasheet doesn't seem to contain all the required parameters, neither for the standard i2t (e.g., the time window) nor for the thermal model.
cc @maggia80 @mfussi66
[^1]: technical note [^2]: We don't have/use native SC on our Faulhaber motors, but we could implement the same strategy. [^3]: technical manual [^4]: We should also provide an estimate of the starting temperature.
Speaking with @maggia80, it turned out that Faulhaber is likely able to provide us with the missing parameters.
Regarding our motor, the datasheet doesn't seem to contain all the required parameters, neither for the standard i2t (e.g., the time window) nor for the thermal model.
Actually, the online datasheet is more complete and contains the required information. See https://www.faulhaber.com/en/products/series/2214bxtr/
Thanks @fiorisi 👍🏻
Therefore, I think we can start, @mfussi66. We need to:
A very quick sanity check with the values above:
$$ \begin{cases} \begin{matrix} RL = 30 \Omega \ R{t1} = 7 K/W \ R_{t2} = 49 K/W \end{matrix} \end{cases}. $$
If we think of starting from the temperature of the environment $T0 = 25$ $^oC$, then to get $\Delta T = 60$ $^oC$ to reach $85$ $^oC$ (way below $T{crit}$) we should deliver:
$$ i = \sqrt{\frac{60 \cdot \left( 7+49\right)}{30 \cdot 7}} = 4 A. $$
Well, 4 Amps is a bit off the motor specs. There must be something else 😕
Moved to the next sprint.
There must be something else 😕
A couple of comments:
A very quick sanity check with the values above:
{RL=30ΩRt1=7K/WRt2=49K/W.
If we think of starting from the temperature of the environment T0=25 oC, then to get ΔT=60 oC to reach 85 oC (way below Tcrit) we should deliver:
i=60⋅(7+49)30⋅7=4A.
Well, 4 Amps is a bit off the motor specs. There must be something else 😕
If I correctly remember we have to balance the Joule losses, the dissipated power and the temperature change in the motor windings. The balance should be the following:
$P_j - P_d = C {\partial T_w\over dt}$
Where:
This should become
$i^2 R_t - {{T_w - Ta} \over {R{th1} + R_{th2} }} = C {\partial T_w\over dt}$
Where:
We don't have $C$, but should be possible to compute it from the thermal time constant $\tau_{w1}$:
$C = {\tau{w1} \over {R{th1} + R_{th2} }}$
By solving the differential equation and initializing the widings temperature we should be able to check the model.
I did the quick calculations in stationary conditions, when $\frac{\partial T}{\partial t}=0$, with the idea that once we know the steady state we know how the system evolves toward it relying on the time constant.
I did the calculations wrong! I was basically confusing the heat source with a voltage generator rather than a current generator, in the electrical analogy.
Here's the correct form:
$$ \Delta T = RLi^2 \cdot \left( R{t1} + R_{t2} \right). $$
$$ i = \sqrt{\frac{60}{30 \cdot \left( 7+49 \right)}} = 188 \text{mA}. $$
The final outcome makes really sense to me.
We will need to accommodate a generic thermal model for a variety of motors (also of different brands). Hence, we should come up with a single equivalent thermal resistance and a single equivalent thermal time constant.
Let me attempt a recap after the notes above.
We aim to implement in our FW architecture (Simulink) a thermal model of the motor so that we can provide a further level of protection. We should be able to adapt the model to a wide variety of motor brands.
For simplicity, we can start with a first-order thermal model, where the input heat flow $\dot{Q}$ (measured in W) is determined by the electrical current $i$[^1] and the resulting electrical resistance of the circuit $R_L$:
[^1]: We can refer to the quadrature current here, as the direct current is regulated to 0
by the PID.
$$ \dot{Q} = R_L \cdot i^2. $$
The steady-state temperature variation wrt the environmental temperature $T_e$ is:
$$ \Delta T = \dot{Q} \cdot R_t, $$
where $R_t$ is the thermal resistance, whose unit is K/W.
The temporal evolution of the temperature $T$ while evolving to $T_e+\Delta T$ is specified by the time constant $\tau$.
Therefore, it suffices to implement a digital filter $F$ characterized by the same constant $\tau$ and deal with the output $\hat{T}\left(t\right)=T_e+F\left(\Delta T\right)=T_e+F\left(R_L \cdot i^2 \cdot R_t\right)$.
It seems that we have access to the quantities at stake from the Faulhaber datasheet.
In particular, the datasheet reports on two different sets of thermal resistances and time constants: one for the windings and one for the housing. Therefore, we should come up with a unique equivalent set (we could use just one or a combination) to monitor what we are interested in.
We would need to define these parameters: $R_L$, $Rt$, $\tau$, $T{crit}$. By contrast, the nominal current $I_N$ is already accounted for in our architecture.
We would need an estimate of $T_e$, unless we decide that we could assume $T_e = 25$ $^oC$[^2] to start with.
[^2]: We may add it up to the list of parameters.
Development started in https://github.com/robotology/icub-firmware-models/tree/14-amcbldc--model-the-i2t-overcurrent-pr.
In continuous time (to discretize at 10ms), it should result in the following model:
With 25.9 Ohms of terminal resistance, the motor gets toasted at about 220mA.
We use those values to be able to perform measurements with the thermocamera. However, the motor won't get toasted at that temperature.
For checking the motor's limits, I guess we should switch to the other set of params corresponding to the windings.
At any rate, we can temporarily overcome the current limits as the temperature increases slowly compared to other dynamics at stake.
In the digital domain with Tustin discretization and externally-defined coefficients, the filter could look like this:
$$ \frac{T_s R_L R_T (z + 1) } {(T_s + 2 \tau) z + T_s - 2 \tau} $$
Translated into configurable blocks:
Comparing the continuous model with the discretized one, there is a small quantization error that stabilizes over a long time.
Here is the step response with 250mA.
I transferred the filter in the architectural model and generated the code, which seems very lean:
Additionally, the Keil project was updated and compiled, and is now ready to be tested.
Nice!
Nitpicking: in the comment we can see $R{t1}$ and $R{t2}$. Could you update it? We've got only $R_t$.
Also, I would make it clearer that the coefficients depend on $T_s$.
So, $T_s$ may be a further input to the block Compute coefficients
.
⚠️ The square block for the current might be missing.
Also, I would make it clearer that the coefficients depend on Ts. So, Ts may be a further input to the block
Compute coefficients
.Nitpicking: in the comment we can see Rt1 and Rt2. Could you update it? We've got only Rt.
⚠️ The square block for the current might be missing.
Woops, silly oversight. Will fix locally, and then put it in a fork after @pattacini checks why the thermal model code is embedded in a function that requires explicit call in the mbdAgent
. It is undesired, since it would require a dedicated thread at 10ms.
after @pattacini checks why the thermal model code is embedded in a function that requires explicit call in the
mbdAgent
. It is undesired, since it would require a dedicated thread at 10ms.
We will now generate two step functions:
step_Time_1ms
step_Time_10ms
that we need to call accordingly in the glue code.
No new thread at 10ms then, just a quick scheduler in the 1ms (a subset of ert_main
).
Yesterday afternoon implemented the counter inside the step_time_1ms()
, that on the 10th tick calls the step_time_10ms()
. The thermal model runs, seemingly correctly, now it just needs proper testing.
To work around the 4096 lines limitation of the debugger printf, I'll publish the temperature on the STATUS CAN packet temporarily.
As soon as we publish some nice graphs validating the working principle of the model, we can merge upstream against the feat branch.
I'd expect some fiddling to fit the model with the observations. However, this is a different point.
It must be noted that the thermal camera cannot log data faster that one acquisition every 3 seconds. There are also internal parameters, such as emissivity, that need to be tuned depending on the motor housing material. At the moment I covered it with black rubber tape to avoid reflectivity effects.
Maybe we could also use a probe connected to an oscilloscope.
Nonetheless, this is a first acquisition. There is an initial offset between the two measurements that is caused by a previous run of the wrist setup, I did not have time to let it cool down due to timing constraints, but we can clearly see that the difference between the two over time increases.
here is the data: test_i2t.zip
@fgarini Suggests that the discrepancy might be caused by the fact that we are using the peak ("picco") current instead of its rms value, which in a 3-phase system is $$I{RMS} = I{peak} / \sqrt{3}.$$
At the moment, we're considering the instantaneous quadrature current squared for simplicity (the direct current is 0
), but the assumption may be wrong, actually.
We can switch to the 3-phase currents as input to the model but we need to agree on what kind of operation we should implement to replace the $i^2$ component.
While reflecting on the usage of the 3-phase currents I checked again the discretized model and I noticed I made a mistake during some premature optimization, which caused the steady-state value to be significantly higher.
I took the measurements again with the fixed firmware, but sadly I did not have the tripod, so they are a little shaky. I filtered them with a median filter with a window of 3 samples, and the results are much much better:
Given this result, I would try to run more tests while using the $I_q$, and switch to the 3-phase currents as needed.
I reckon we can close this task. In the upcoming sprints, we will address two more points:
We're required to implement in the architectural model the
i2t
protection. We may use some new parameters as per #8.Some further resources: