Skip to content
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

Merged
merged 6 commits into from
May 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@

class ExternallyExcitedSynchronousMotor(SynchronousMotor):
"""
===================== ========== ============= ===========================================
===================== ========== ============= =================================================
Motor Parameter Unit Default Value Description
===================== ========== ============= ===========================================
===================== ========== ============= =================================================
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)
j_rotor kg/m^2 0.3883 Moment of inertia of the rotor
===================== ========== ============= ===========================================
===================== ========== ============= =================================================

=============== ====== =============================================
=============== ====== ===========================================================================
Motor Currents Unit Description
=============== ====== =============================================
=============== ====== ===========================================================================
i_sd A Direct axis current
i_sq A Quadrature axis current
i_e A Excitation current
Expand All @@ -31,10 +32,10 @@ class ExternallyExcitedSynchronousMotor(SynchronousMotor):
i_c A Current through branch c
i_alpha A Current in alpha axis
i_beta A Current in beta axis
=============== ====== =============================================
=============== ====== =============================================
=============== ====== ===========================================================================
=============== ====== ===========================================================================
Motor Voltages Unit Description
=============== ====== =============================================
=============== ====== ===========================================================================
u_sd V Direct axis voltage
u_sq V Quadrature axis voltage
u_e V Exciting voltage
Expand All @@ -43,13 +44,13 @@ class ExternallyExcitedSynchronousMotor(SynchronousMotor):
u_c V Voltage through branch c
u_alpha V Voltage in alpha axis
u_beta V Voltage in beta axis
=============== ====== =============================================
=============== ====== ===========================================================================

======== ===========================================================
======== =========================================================================================
Limits / Nominal Value Dictionary Entries:
-------- -----------------------------------------------------------
-------- -----------------------------------------------------------------------------------------
Entry Description
======== ===========================================================
======== =========================================================================================
i General current limit / nominal value
i_a Current in phase a
i_b Current in phase b
Expand All @@ -70,7 +71,7 @@ class ExternallyExcitedSynchronousMotor(SynchronousMotor):
u_sd Voltage in direct axis
u_sq Voltage in quadrature axis
u_e Voltage in excitation circuit
======== ===========================================================
======== =========================================================================================


Note:
Expand Down Expand Up @@ -98,14 +99,15 @@ class ExternallyExcitedSynchronousMotor(SynchronousMotor):

#### Parameters taken from DOI: 10.1109/ICELMACH.2014.6960287 (C. D. Nguyen; W. Hofmann)
_default_motor_parameter = {
"p": 3,
"l_d": 1.66e-3,
"l_q": 0.35e-3,
"l_m": 1.589e-3,
"l_e": 1.74e-3,
"j_rotor": 0.3883,
"r_s": 15.55e-3,
"r_e": 7.2e-3,
'p': 3,
'l_d': 1.66e-3,
'l_q': 0.35e-3,
'l_m': 1.589e-3,
'l_e': 1.74e-3,
'j_rotor': 0.3883,
'r_s': 15.55e-3,
'r_e': 7.2e-3,
'k': 65.21,
}
HAS_JACOBIAN = True
_default_limits = dict(omega=12e3 * np.pi / 30, torque=0.0, i=150, i_e=150, epsilon=math.pi, u=320)
Expand All @@ -123,21 +125,32 @@ class ExternallyExcitedSynchronousMotor(SynchronousMotor):
def _update_model(self):
# Docstring of superclass
mp = self._motor_parameter
sigma = 1 - mp["l_m"] ** 2 / (mp["l_d"] * mp["l_e"])

# Transform rotor quantities to stator side (uppercase index denotes transformation to stator side)
mp['r_E'] = mp['k'] ** 2 * 3/2 * mp['r_e']
mp['l_M'] = mp['k'] * 3/2 * mp['l_m']
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'])

# fmt: off

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'] / sigma, 0, mp['l_m'] * mp['r_e'] / (sigma * mp['l_e']), 1 / sigma, 0, -mp['l_m'] / (sigma * mp['l_e']), 0, mp['l_q'] * mp['p'] / sigma, 0],
[ 0, 0, -mp['r_s'], 0, 0, 1, 0, -mp['l_d'] * mp['p'], 0, -mp['p'] * mp['l_m']],
[ 0, mp['l_m'] * mp['r_s'] / (sigma * mp['l_d']), 0, -mp['r_e'] / sigma, -mp['l_m'] / (sigma * mp['l_d']), 0, 1 / sigma, 0, -mp['p'] * mp['l_m'] * mp['l_q'] / (sigma * mp['l_d']), 0],
[ mp['p'], 0, 0, 0, 0, 0, 0, 0, 0, 0],
# 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"], 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],
])
# fmt: on

self._model_constants[self.I_SD_IDX] = self._model_constants[self.I_SD_IDX] / mp["l_d"]
self._model_constants[self.I_SQ_IDX] = self._model_constants[self.I_SQ_IDX] / mp["l_q"]
self._model_constants[self.I_E_IDX] = self._model_constants[self.I_E_IDX] / mp["l_e"]
self._model_constants[self.I_E_IDX] = self._model_constants[self.I_E_IDX] / mp["l_E"] / mp["i_k_rs"]

# fmt: on

def electrical_ode(self, state, u_dq, omega, *_):
def electrical_ode(self, state, u_dqe, omega, *_):
"""
The differential equation of the Synchronous Motor.

Expand All @@ -149,6 +162,7 @@ def electrical_ode(self, state, u_dq, omega, *_):
Returns:
The derivatives of the state vector d/dt([i_sd, i_sq, epsilon])
"""

return np.matmul(
self._model_constants,
np.array(
Expand All @@ -157,14 +171,14 @@ def electrical_ode(self, state, u_dq, omega, *_):
state[self.I_SD_IDX],
state[self.I_SQ_IDX],
state[self.I_E_IDX],
u_dq[0],
u_dq[1],
u_dq[2],
u_dqe[0],
u_dqe[1],
u_dqe[2],
omega * state[self.I_SD_IDX],
omega * state[self.I_SQ_IDX],
omega * state[self.I_E_IDX],
omega * state[self.I_E_IDX]
]
),
)
)

def _torque_limit(self):
Expand All @@ -174,46 +188,41 @@ def _torque_limit(self):
return self.torque([0, self._limits["i_sq"], self._limits["i_e"], 0])
else:
i_n = self.nominal_values["i"]
_p = mp["l_m"] * i_n / (2 * (mp["l_d"] - mp["l_q"]))
_q = -(i_n**2) / 2
_p = mp["l_M"] * i_n / (2 * (mp["l_d"] - mp["l_q"]))
_q = - i_n ** 2 / 2
if mp["l_d"] < mp["l_q"]:
i_d_opt = -_p / 2 - np.sqrt((_p / 2) ** 2 - _q)
i_d_opt = - _p / 2 - np.sqrt((_p / 2) ** 2 - _q)
else:
i_d_opt = -_p / 2 + np.sqrt((_p / 2) ** 2 - _q)
i_q_opt = np.sqrt(i_n**2 - i_d_opt**2)
i_d_opt = - _p / 2 + np.sqrt((_p / 2) ** 2 - _q)
i_q_opt = np.sqrt(i_n ** 2 - i_d_opt ** 2)
return self.torque([i_d_opt, i_q_opt, self._limits["i_e"], 0])

def torque(self, currents):
# Docstring of superclass
mp = self._motor_parameter
return (
1.5
* mp["p"]
* (mp["l_m"] * currents[self.I_E_IDX] + (mp["l_d"] - mp["l_q"]) * currents[self.I_SD_IDX])
* currents[self.I_SQ_IDX]
)
return 1.5 * mp["p"] * (mp["l_M"] * currents[self.I_E_IDX] * mp["i_k_rs"] + (mp["l_d"] - mp["l_q"]) * currents[self.I_SD_IDX]) * currents[self.I_SQ_IDX]

def electrical_jacobian(self, state, u_in, omega, *args):

mp = self._motor_parameter
sigma = 1 - mp["l_m"] ** 2 / (mp["l_d"] * mp["l_e"])
# fmt: off

return (
np.array([ # dx'/dx
[ -mp['r_s'] / mp['l_d'], mp['l_q'] / (sigma * mp['l_d']) * omega * mp['p'], mp['l_m'] * mp['r_e'] / (sigma * mp['l_d'] * mp['l_e']), 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'], 0],
[mp['l_m'] * mp['r_s'] / (sigma * mp['l_d'] * mp['l_e']), -omega * mp['p'] * mp['l_m'] * mp['l_q'] / (sigma * mp['l_d'] * mp['l_e']), -mp['r_e'] / mp['l_e'], 0],
[ 0, 0, 0, 0],
[ -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],
]),
np.array([ # dx'/dw
mp['p'] * mp['l_q'] / mp['l_d'] * state[self.I_SQ_IDX],
-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["p"] * mp["l_q"] / (mp["l_d"] * mp["sigma"]) * state[self.I_SQ_IDX],
-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"] * mp["i_k_rs"]) * state[self.I_SQ_IDX],
mp["p"],
]),
np.array([ # dT/dx
1.5 * mp['p'] * (mp['l_d'] - mp['l_q']) * state[self.I_SQ_IDX],
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_d"] - mp["l_q"]) * state[self.I_SQ_IDX],
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],
0,
])
)
Expand Down
Loading