-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EESM: Correction / Introduction of transfer ratios between rotor and stator #234
Conversation
Could @MpenaLea elaborate on the theory a little bit? |
https://github.com/upb-lea/gym-electric-motor/blame/5443a5157f1320a9d3f8852efc37ae9e77bc619c/gym_electric_motor/physical_systems/electric_motors/externally_excited_synchronous_motor.py#L98 A transformation is required to relate the model rotor parameters and variables to their physical counterpart. This transformation is not unique. It can be done, for example, as detailed in [C. Ong, Dynamic Simulation of Electric Machinery: Using MATLAB/SIMULINK. Prentice Hall PTR, 1998, isbn: 9780137237852, p. 267 and following], neglecting the effect of q-axis and damping windings in the rotor. From this transformation, one obtains: i_F = (2/3)(N_f/N_s) * i_f where the parameters and variables with "f" refer to the physical values, and with "F" these are referred to the stator circuit. N_s and N_f are the stator and field winding number of turns, respectively. The system of equations with rotor variables referred to the stator (F) results in a symmetrical coupling between d and F (L_dF = L_Fd), as is currently internally considered in the model. Appropriate transformations based on the above must be applied to have a valid physical interpretation of the results obtained from the model. Alternatively, the differential equations considered can be modified to only consider physical parameters and variables, e.g., as Q. K. Nguyen, et. al. DOI: [10.1109/ICPE.2015.7168165] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on what @M-Pena wrote I think the formulas look correct (besides the magic 77). I would request @bhk11 to also have a deeper look at the model_constants matrix as it is quite difficult to dig through it. I just wonder whether parameters such as r_s and l_d do not have to be transformed?
Also, as a general note, I would like to know whether these changes we introduce here can be expected to be in favor for everyone using GEM or if it is only important for this specific motor parameter set? Or in other words: Should we make this transformation optional inside GEM? Couldn't users do the transformation themselves? What is the most common case here - to transform or not to transform?
r_s mOhm 15.55 Stator resistance | ||
r_e mOhm 7.2 Excitation resistance | ||
l_d mH 1.66 Direct axis inductance | ||
l_q mH 0.35 Quadrature axis inductance | ||
l_m mH 1.589 Mutual inductance | ||
l_e mH 1.74 Excitation inductance | ||
p 1 3 Pole pair number | ||
k 1 65.21 Transfer ratio of number of windings (N_s / N_e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we introduce k as a parameter instead of N_s and N_e? Is that a common approach for EESM simulations?
mp['l_E'] = mp['k'] ** 2 * 3/2 * mp['l_e'] | ||
|
||
mp['i_k_rs'] = 2 / 3 / mp['k'] # ratio (i_E / i_e) | ||
mp['sigma'] = 1 - mp['l_M'] ** 2 / (mp['l_d'] * mp['l_E']) * 77 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the 77 here stand for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intended to check whether this is caught by any unit tests 😁
Apparently its not...
Forgot to delete afterwards
mp['l_E'] = mp['k'] ** 2 * 3/2 * mp['l_e'] | ||
|
||
mp['i_k_rs'] = 2 / 3 / mp['k'] # ratio (i_E / i_e) | ||
mp['sigma'] = 1 - mp['l_M'] ** 2 / (mp['l_d'] * mp['l_E']) * 77 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic number
[ 0, -mp['r_s'] / mp['sigma'], 0, mp['l_M'] * mp['r_E'] / (mp['sigma'] * mp['l_E']) * mp['i_k_rs'], 1 / mp['sigma'], 0, -mp['l_M'] * mp['k'] / (mp['sigma'] * mp['l_E']), 0, mp['l_q'] * mp['p'] / mp['sigma'], 0], | ||
[ 0, 0, -mp['r_s'], 0, 0, 1, 0, -mp['l_d'] * mp['p'], 0, -mp['p'] * mp['l_M'] * mp['i_k_rs']], | ||
[ 0, mp['l_M'] * mp['r_s'] / (mp['sigma'] * mp['l_d']), 0, -mp['r_E'] / mp['sigma'] * mp['i_k_rs'], -mp['l_M'] / (mp['sigma'] * mp['l_d']), 0, mp['k'] / mp['sigma'], 0, -mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d']), 0], | ||
[ mp['p'], 0, 0, 0, 0, 0, 0, 0, 0, 0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I use the linear model, which Mario provide to us, the matrix should look like:
self._model_constants = np.array([ # omega, i_d, i_q, i_e, u_d, u_q, u_e, omega * i_d, omega * i_q, omega * i_e [ 0, -mp['r_s'] / (mp['sigma'] * mp['l_d']), 0, mp['l_M'] * mp['r_E'] / (mp['sigma'] * mp['l_E'] * mp['l_d']) * mp['i_k_rs'], 1 / (mp['sigma'] * mp['l_d']), 0, -mp['l_M'] * mp['k'] / (mp['sigma'] * mp['l_E'] * mp['l_d']), 0, mp['l_q'] * mp['p'] / (mp['sigma'] * mp['l_d']), 0], [ 0, 0, -mp['r_s'] / (mp['l_q']), 0, 0, 1 / (mp['l_q']), 0, -mp['l_d'] * mp['p'] / (mp['l_q']), 0, -mp['p'] * mp['l_M'] * mp['i_k_rs'] / (mp['l_q'])], [ 0, mp['l_M'] * mp['r_s'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), 0, -mp['r_E'] / (mp['sigma'] * mp['l_E']) * mp['i_k_rs'], -mp['l_M'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), 0, mp['k'] / (mp['sigma'] * mp['l_E']), 0, -mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), 0], [ mp['p'], 0, 0, 0, 0, 0, 0, 0, 0, 0], ])
to my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest changes look correct as far as I can tell, accounting for the modifications done in lines 144-146. In your suggestion, I am missing some parameters in the equations for d(i_e)/dt. That whole matrix row must be divided by mp['i_k_rs']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would agree. According to my notes, I have written down the equation for di_E/dt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be correct now:
self._model_constants = np.array([ # omega, i_d, i_q, i_e, u_d, u_q, u_e, omega * i_d, omega * i_q, omega * i_e
[ 0, -mp['r_s'] / (mp['sigma'] * mp['l_d']), 0, mp['l_M'] * mp['r_E'] / (mp['sigma'] * mp['l_E'] * mp['l_d']) * mp['i_k_rs'], 1 / (mp['sigma'] * mp['l_d']), 0, -mp['l_M'] * mp['k'] / (mp['sigma'] * mp['l_E'] * mp['l_d']), 0, mp['l_q'] * mp['p'] / (mp['sigma'] * mp['l_d']), 0],
[ 0, 0, -mp['r_s'] / (mp['l_q']), 0, 0, 1 / (mp['l_q']), 0, -mp['l_d'] * mp['p'] / (mp['l_q']), 0, -mp['p'] * mp['l_M'] * mp['i_k_rs'] / (mp['l_q'])],
[ 0, mp['l_M'] * mp['r_s'] / (mp['sigma'] * mp['l_d'] * mp['l_E'] * mp['i_k_rs']), 0, -mp['r_E'] / (mp['sigma'] * mp['l_E']), -mp['l_M'] / (mp['sigma'] * mp['l_d'] * mp['l_E'] * mp['i_k_rs']), 0, mp['k'] / (mp['sigma'] * mp['l_E'] * mp['i_k_rs']), 0, -mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E'] * mp['i_k_rs']), 0],
[ mp['p'], 0, 0, 0, 0, 0, 0, 0, 0, 0],
])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't check the Jacobian yet. Would you agree to the changes for the _model_constants?
I am still somewhat questioning why we introduce the transfer ratio of number of windings instead of the number of windings themselves. Especially because all other motor parameters are actual physical properties. I don't mind as long as the logic is now correct, though. |
Mistakenly closed this pull request. Sorry |
[ -mp['r_s'] / (mp['l_d'] * mp['sigma']), mp['l_q'] / (mp['sigma'] * mp['l_d']) * omega * mp['p'], mp['l_M'] * mp['r_e'] / (mp['sigma'] * mp['l_d'] * mp['l_E']) * mp['i_k_rs'], 0], | ||
[ -mp['l_d'] / mp['l_q'] * omega * mp['p'], -mp['r_s'] / mp['l_q'], -omega * mp['p'] * mp['l_E'] / mp['l_q'] * mp['i_k_rs'], 0], | ||
[mp['l_M'] * mp['r_s'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), -omega * mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), -mp['r_E'] / mp['l_E'] * mp['i_k_rs'], 0], | ||
[ 0, 0, 0, 0], | ||
]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe lines 198-201 should be replaced with
[ -mp['r_s'] / (mp['l_d'] * mp['sigma']), mp['l_q'] / (mp['sigma'] * mp['l_d']) * omega * mp['p'], mp['l_M'] * mp['r_E'] / (mp['sigma'] * mp['l_d'] * mp['l_E']) * mp['i_k_rs'], 0],
[ -mp['l_d'] / mp['l_q'] * omega * mp['p'], -mp['r_s'] / mp['l_q'], -omega * mp['p'] * mp['l_M'] / mp['l_q'] * mp['i_k_rs'], 0],
[mp['l_M'] * mp['r_s'] / (mp['sigma'] * mp['l_d'] * mp['l_E']* mp['i_k_rs']), -omega * mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E']* mp['i_k_rs']), -mp['r_E'] / (mp['sigma'] * mp['l_E'])], 0],
[ 0, 0, 0, 0],
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the same solution.
-mp['p'] * mp['l_d'] / mp['l_q'] * state[self.I_SD_IDX] - mp['p'] * mp['l_m'] / mp['l_q'] * state[self.I_E_IDX], | ||
-mp['p'], | ||
-mp['p'] * mp['l_d'] / mp['l_q'] * state[self.I_SD_IDX] - mp['p'] * mp['l_M'] / mp['l_q'] * state[self.I_E_IDX] * mp['i_k_rs'], | ||
-mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correction to line 206
-mp['p'] * mp['l_M'] * mp['l_q'] / (mp['sigma'] * mp['l_d'] * mp['l_E'] * mp['i_k_rs']) * state[self.I_SQ_IDX],
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a / mp['sigma'] missing in line 204?
1.5 * mp['p'] * (mp['l_e'] * state[self.I_E_IDX] + (mp['l_d'] - mp['l_q']) * state[self.I_SD_IDX]), | ||
1.5 * mp['p'] * mp['l_e'] * state[self.I_SQ_IDX], | ||
1.5 * mp['p'] * (mp['l_E'] * state[self.I_E_IDX] * mp['i_k_rs'] + (mp['l_d'] - mp['l_q']) * state[self.I_SD_IDX]), | ||
1.5 * mp['p'] * mp['l_E'] * state[self.I_SQ_IDX], | ||
0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 211 and 212
1.5 * mp['p'] * (mp['l_M'] * state[self.I_E_IDX] * mp['i_k_rs'] + (mp['l_d'] - mp['l_q']) * state[self.I_SD_IDX]),
1.5 * mp['p'] * mp['l_M'] * mp['i_k_rs'] * state[self.I_SQ_IDX],
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This correction looks also fine to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks correct to me.
Refers to #233.