I have a BLDC electric motor, I'm currently trying to control via a PIDTune. This is mostly an attempt to reduce (remove) a small run away drift that ends up showing up in the motor signal u[t].

I've modelled this via:

ssm = StateSpaceModel[\[ScriptCapitalJ] \[Phi]''[t] + \[ScriptCapitalR] \[Phi]'[t] == \[ScriptCapitalT] u[t], {{\[Phi][t], 0}, {\[Phi]'[t], 0}, {u[t], 1}}, u[t], \[Phi]'[t], t]

And simulated:

params = { \[ScriptCapitalJ] -> 4.63 10^-5, \[ScriptCapitalR] -> 1 10^-5, \[ScriptCapitalT] -> 0.0335};
Plot[Evaluate[OutputResponse[ssm /. params, 1, {t, 0, 12}]], {t, 0, 12}]


This is a nice model response and mirrors the response of the real motor almost exactly.

So I tried to create a control system to add to the control signal and bring the system relatively quickly back to zero.

control = PIDTune[ssm /. params , {"PID"}]

But I continue to get the following error:

PIDTune::infgains: Unable to compute finite controller parameters because a denominator in the tuning formula is effectively zero.

I have tried all tuning methods within the documentation, however I continue to get errors.

Changing to a "PD" control

control = PIDTune[ssm /. params , {"PD"}]

Gives me control system, however when adding it to the feedback and then seeing the response I get a different error:

simul = SystemsModelFeedbackConnect[ssm, control] /. params

OutputResponse[simul, UnitStep[t - 3], {t, 0, 12}]

OutputResponse::irregss: A solution could not be found for the irregular state-space model with a characteristic equation of zero.

The error messages don't really make any sense to me...or explain what the issue is with the model...being that it simulates reality quite well....How can I relieve these errors, or create a feedback loop via PIDTune for my system?

Thank you for the help!

There is a similar example with a dcmotor within the documentation for PIDTune for reference which works fine (albeit a different tfm):

dcMotor = TransferFunctionModel[Unevaluated[{{k/(s ((j s + b) (l s + r) + k^2))}}], s, SamplingPeriod ->None, SystemsModelLabels -> {{None}, {None}}] /. pars;

PIDTune[dcMotor, "PID", "PIDData"]


As per M.K.s suggestion, I have changed the ssm slightly, or rather rewritten it to come directly to the equation of motion for angular velocity omega, instead of the motors angle phi. This change simplifies the ssm and allows PIDTune to come up with a solution.

As a small explanation, the ODE is derived via equation 6 of this paper as a simplified motor for control via amperage of u[t]. Though is is a relatively 'standard' equation used and can be found in many papers. J and R were found via nonlinearfitting of driving the motor at different amperages. As such, the model params, J, T, R are quite accurate.

ssmnew = StateSpaceModel[\[ScriptCapitalJ] \[Omega]'[t] + \[ScriptCapitalR] \[Omega][t] == \[ScriptCapitalT] u[t], {{\[Omega][t], 0}}, {{u[t]}}, {\[Omega][t]}, t]

control = PIDTune[ssmnew /. params, {"PID"}]
loop = SystemsModelFeedbackConnect[ssmnew, control] /. params
test1 OutputResponse[loop, UnitStep[t - 4], {t, 0, 12}]


 test2 = OutputResponse[control /. params, UnitStep[t - 3], {t, 0, 10}]

Unfortunately at this point, I am now getting either new errors, or a response that is completely wrong, using inputs of UnitStep or just 1

NDSolve::ndsz: At t == 4.000000000000114`, step size is effectively zero; singularity or stiff system suspected.


NDSolve::irfail: Unable to reduce the index of the system to 0 or 1.


  • $\begingroup$ Don't find your "charaistic" in ABBYLingvo. Is it a new English word? If so, what does it mean? $\endgroup$ – user64494 Jun 11 '19 at 16:45
  • $\begingroup$ I believe that is what some call a typo...it should be characteristic...i admit, its a pretty bad typo.... :D $\endgroup$ – morbo Jun 11 '19 at 16:47
  • $\begingroup$ What obstructs to correct it? This is your duty. $\endgroup$ – user64494 Jun 11 '19 at 17:08
  • $\begingroup$ Life outside of SE. $\endgroup$ – morbo Jun 11 '19 at 17:12

Not an answer, but too long for a comment.

Your definition of ssm seems to not comply with the syntax listed in the documentation. It can be changed, for example, to

ssm = StateSpaceModel[
\[ScriptCapitalJ] \[Phi]''[t] + \[ScriptCapitalR] \[Phi]'[
t] == \[ScriptCapitalT] u[t],
{{\[Phi][t], 0}, {\[Phi]'[t], 0}}, {{u[t], 1}}, {\[Phi][
t](*,\[Phi]'[t]*)}, t]

Then it produces no errors when evaluating

control = PIDTune[ssm /. params, {"PID"}]

But for the parameters given, the response function has a different plot from the one resulting from your definition of ssm. So if you can change the ssm that it has a valid syntax and still produces a response that is close to the one of a real motor, then you are done. And if not, I cannot probably help much more, but feel free to elaborate on your endeavours. For example, how have you obtained the model for your motor? Parameters? Are there any other requirements beside giving a proper response function?

| improve this answer | |
  • $\begingroup$ Ho @MK. Thanks for the suggestion! Ahh Please see the update in the post. I addressed your questions and changed via your suggestion the ssm. As far as other requirements go for the model, there arn't any specifically I can think of, besides it should represent the motor :). Or maybe I don't quiet understand what other requirements you might be looking for. Thanks for extended comment, it definitely got me further :) $\endgroup$ – morbo Jun 11 '19 at 13:28

Here's an example of a basic PD controller based on frequency domain tuning. The technique is described in any basic control book. Basic tuning rule-of-thumbs that have been applied (no further advanced tuning)

Let's write ssm as a transfer function:

tf = TransferFunctionModel[ssm]

Given some desired crossover w0, we choose

  • kp = 1/3 * 1/tf[w0]
  • wd = kp/kd = w0/3

and we make a PD controller c

c[kp_, wd_] := TransferFunctionModel[kp + kp/wd s, s]

As an example, we can show responses in a manipulate (as function of the desired crossover frequency).

Manipulate[kp = 1/(3. ((tf /. params)@wc)[[1, 1]]);
wd = wc/3;
ctf = SystemsModelSeriesConnect[c[kp, wd], tf /. params];
Evaluate[{BodePlot[c[kp, wd], {.01, 1000}, PlotLabel -> "Controller",
PlotLegends -> "Expressions"], 
BodePlot[tf /. params, {.01, 1000}, PlotLabel -> "Plant"], 
BodePlot[ctf, {.01, 1000}, PlotLabel -> "Controller times plant", StabilityMargins -> True], 
NyquistPlot[ctf, PlotLabel -> "Nyquist"]}], 
{{wc, 100, "Open-loop crossover"}, 10, 1000}]

Based on your requirements (unknown to me), you can add features to your controller. Hope this helps

| improve this answer | |
  • $\begingroup$ Ahh, thanks! I will test this method asap $\endgroup$ – morbo Jun 11 '19 at 15:49

The first thing is that I find it odd that your model has current as the input and speed as the output? Typically, it's voltage to speed, and also voltage to position.

However, the dominant pole approach seems to work for your model.

pid = PIDTune[ssm /. params, {Automatic, "DominantPole"}, "PIDData"];

enter image description here

OutputResponse[pid["ReferenceOutput"], UnitStep[t] - UnitStep[t - 4], {t, 
0, 10}];
Plot[%, {t, 0, 10}]

enter image description here

| improve this answer | |
  • $\begingroup$ Ahh that detail may be missing...i have a escon 24/2 current controller for the motor itself (converter)...and the motor is then controlled via the converter via mcu pwm signal (hence the model form)... the right side of the equation in SI units would then be tau*u[t] -> [Nm/A]*A....Thanks for the help! I will test this when i get home! $\endgroup$ – morbo Jun 11 '19 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.