-
Notifications
You must be signed in to change notification settings - Fork 72
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
six phase motor - inprogress #267
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
import math | ||
|
||
import numpy as np | ||
|
||
from .six_phase_motor import SixPhaseMotor | ||
|
||
|
||
class SixPhasePMSM(SixPhaseMotor): | ||
""" | ||
===================== ========== ============= =========================================== | ||
Motor Parameter Unit Default Value Description | ||
===================== ========== ============= =========================================== | ||
r_s Ohm 64.3e-3 Stator resistance | ||
l_d H 125e-6 Direct axis inductance | ||
l_q H 126e-6 Quadrature axis inductance | ||
l_x H 39e-6 x-axis inductance | ||
l_y H 35e-6 y-axis inductance | ||
p 1 5 Pole pair number | ||
psi_PM Vs 4.7e-3 flux linkage of the permanent magnets | ||
===================== ========== ============= =========================================== | ||
|
||
=============== ====== ============================================= | ||
Motor Currents Unit Description | ||
=============== ====== ============================================= | ||
i_sd A Direct axis current | ||
i_sq A Quadrature axis current | ||
i_sx A | ||
i_sy A | ||
i_salpha A Stator current in alpha direction | ||
i_sbeta A Stator current in beta direction | ||
i_sX A | ||
i_sY A | ||
i_sa1 A | ||
i_sa2 A | ||
i_sb1 A | ||
i_sb2 A | ||
i_sc1 A | ||
i_sc2 A | ||
|
||
=============== ====== ============================================= | ||
=============== ====== ============================================= | ||
Motor Voltages Unit Description | ||
=============== ====== ============================================= | ||
u_sd V Direct axis voltage | ||
u_sq V Quadrature axis voltage | ||
u_sx V | ||
u_sx V | ||
u_a1 V | ||
u_a2 V | ||
u_b1 V | ||
u_b2 V | ||
u_c1 V | ||
u_c2 V | ||
=============== ====== ============================================= | ||
|
||
======== =========================================================== | ||
Limits / Nominal Value Dictionary Entries: | ||
-------- ----------------------------------------------------------- | ||
Entry Description | ||
======== =========================================================== | ||
i General current limit / nominal value | ||
======== =========================================================== | ||
|
||
""" | ||
I_SD_IDX = 0 | ||
I_SQ_IDX = 1 | ||
I_SX_IDX = 2 | ||
I_SY_IDX = 3 | ||
CURRENTS_IDX = [0, 1, 2, 3] | ||
CURRENTS = ["i_sd", "i_sq", "i_sx", "i_sy"] | ||
VOLTAGES = ["u_sd", "u_sq", "u_sx", "u_sy"] | ||
|
||
@property | ||
def motor_parameter(self): | ||
# Docstring of superclass | ||
return self._motor_parameter | ||
|
||
@property | ||
def initializer(self): | ||
# Docstring of superclass | ||
return self._initializer | ||
|
||
#### Parameters taken from https://ieeexplore.ieee.org/document/10372153 | ||
_default_motor_parameter = {"p": 5, "l_d": 125e-6, "l_q": 126e-6, "l_x": 39e-6, "l_y": 35e-6, "r_s": 64.3e-3, "psi_PM": 4.7e-3,} | ||
#_default_limits = ?maximum | ||
#_default_nominal_values = ?rated | ||
_default_initializer = { | ||
"states": {"i_sd": 0.0, "i_sq": 0.0, "i_sx": 0.0, "i_sy": 0.0}, | ||
"interval": None, | ||
"random_init": None, | ||
"random_params": (None, None), | ||
} | ||
|
||
_model_constants = None | ||
|
||
_initializer = None | ||
|
||
def __init__( | ||
self, | ||
motor_parameter=None, | ||
nominal_values=None, | ||
limit_values=None, | ||
motor_initializer=None, | ||
): | ||
# Docstring of superclass | ||
nominal_values = nominal_values or {} | ||
limit_values = limit_values or {} | ||
super().__init__(motor_parameter, nominal_values, limit_values, motor_initializer) | ||
self._update_model() | ||
self._update_limits() | ||
|
||
def _update_model(self): | ||
"""Updates the motor's model parameters with the motor parameters. | ||
|
||
Called internally when the motor parameters are changed or the motor is initialized. | ||
""" | ||
mp = self._motor_parameter | ||
self._model_constants = np.array([ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be helpful to specify via comment which matrix column belongs to which regressor (please see other motor types for reference). |
||
# omega, i_d, i_q, i_x, i_y, u_d, u_q, u_x, u_y, omega * i_d, omega * i_q, omega * i_x, omega * i_y | ||
[ 0, -mp['r_s'], 0, 0, 0, 1, 0, 0, 0, 0, mp['l_q'], 0, 0], | ||
[-mp['psi_PM'], 0, -mp['r_s'], 0, 0, 0, 1, 0, 0, -mp['l_d'], 0, 0, 0], | ||
[ 0, 0, 0, -mp['r_s'], 0, 0, 0, 1, 0, 0, 0, 0, -mp['l_y']], | ||
[ 0, 0, 0, 0, -mp['r_s'], 0, 0, 0, 1, 0, 0, mp['l_x'], 0] | ||
Comment on lines
+120
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks very good to me. Good job! |
||
|
||
]) | ||
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_SX_IDX] = self._model_constants[self.I_SX_IDX] / mp["l_x"] | ||
self._model_constants[self.I_SY_IDX] = self._model_constants[self.I_SY_IDX] / mp["l_y"] | ||
|
||
|
||
def electrical_ode(self, state, u_dqxy, omega, *_): | ||
""" | ||
The differential equation of the Six phase PMSM. | ||
|
||
Args: | ||
state: The current state of the motor. [i_sd, i_sq, i_sx, i_sy] | ||
omega: electrical rotational speed | ||
u_qdxy: The input voltages [u_sd, u_sq, u_sx, u_sy] | ||
|
||
Returns: | ||
The derivatives of the state vector d/dt([i_sd, i_sq, i_sx, i_sy]) | ||
""" | ||
return np.matmul( | ||
self._model_constants, | ||
np.array( | ||
[ | ||
omega, | ||
state[self.I_SD_IDX], | ||
state[self.I_SQ_IDX], | ||
state[self.I_SX_IDX], | ||
state[self.I_SY_IDX], | ||
u_dqxy[0], | ||
u_dqxy[1], | ||
u_dqxy[2], | ||
u_dqxy[3], | ||
omega * state[self.I_SD_IDX], | ||
omega * state[self.I_SQ_IDX], | ||
omega * state[self.I_SX_IDX], | ||
omega * state[self.I_SY_IDX], | ||
] | ||
), | ||
) | ||
|
||
|
||
def i_in(self, state): | ||
# Docstring of superclass | ||
return state[self.CURRENTS_IDX] | ||
|
||
def reset(self, state_space, state_positions, **__): | ||
# Docstring of superclass | ||
if self._initializer and self._initializer["states"]: | ||
self.initialize(state_space, state_positions) | ||
return np.asarray(list(self._initial_states.values())) | ||
else: | ||
return np.zeros(len(self.CURRENTS) + 1) | ||
|
||
#from pmsm | ||
def torque(self, currents): | ||
# Docstring of superclass | ||
mp = self._motor_parameter | ||
return ( | ||
1.5 * mp["p"] * (mp["psi_PM "] + (mp["l_d"] - mp["l_q"]) * currents[self.I_SD_IDX]) * currents[self.I_SQ_IDX] | ||
) | ||
|
||
#torque limit ? | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import math | ||
|
||
import numpy as np | ||
|
||
from .electric_motor import ElectricMotor | ||
|
||
|
||
class SixPhaseMotor(ElectricMotor): | ||
""" | ||
The SixPhaseMotor and its subclasses implement the technical system of Six Phase Motors. | ||
|
||
""" | ||
|
||
# transformation matrix from abc to alpha-beta representation | ||
# VSD is the modeling approach used for multi-phase machines, which represents a generalized form of the clarke transformation | ||
# for the six phase machine with Winding configuration in the stator- and rotor-fixed coordinate systems with δ =(2/3)*π and γ =π/6 | ||
_t46= 1/ 3 * np.array([ | ||
[1, -0.5, -0.5, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0], | ||
[0, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0.5, 0.5, -1], | ||
[1, -0.5, -0.5, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0], | ||
[0, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0.5, 0.5, -1] | ||
]) | ||
|
||
# i_s - stator current | ||
@staticmethod | ||
def t_46(quantities): | ||
""" | ||
Transformation from abc representation to alpha-beta representation | ||
|
||
Args: | ||
quantities: The properties in the abc representation like ''[i_sa1, i_sb1, i_sc1, i_sa2, i_sb2, i_sc2]'' | ||
|
||
Returns: | ||
The converted quantities in the alpha-beta representation like ''[i_salpha, i_sbeta, i_sX, i_sY]'' | ||
""" | ||
return np.matmul(SixPhaseMotor._t46, quantities) | ||
|
||
@staticmethod | ||
def q(quantities, epsilon): | ||
""" | ||
Transformation of the abc representation into dq using the electrical angle | ||
|
||
Args: | ||
quantities: the properties in the abc representation like ''[i_sa1, i_sb1, i_sc1, i_sa2, i_sb2, i_sc2]'' | ||
epsilon: electrical rotor position | ||
|
||
Returns: | ||
The converted quantities in the dq representation like ''[i_sd, i_sq, i_sx, i_sy, i_s0+, i_s0-]''. | ||
since 2N topology is considered (case where the neutral points are not connected) i_s0+, i_s0- will not be taken into account | ||
""" | ||
""" | ||
t_vsd = 1/ 3 * np.array([ | ||
[1, -0.5, -0.5, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0], | ||
[0, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0.5, 0.5, -1], | ||
[1, -0.5, -0.5, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0], | ||
[0, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0.5, 0.5, -1], | ||
[1, 1, 1, 0, 0, 0], | ||
[0, 0, 0, 1, 1, 1] | ||
]) | ||
tp_alphaBetaXY = np.array([ | ||
[cos, sin, 0, 0, 0, 0], | ||
[-sin, cos, 0, 0, 0, 0], | ||
[0, 0, cos, sin, 0, 0], | ||
[0, 0, -sin, cos, 0, 0], | ||
[0, 0, 0, 0, 1, 0] | ||
[0, 0, 0, 0, 0, 1] | ||
]) | ||
Comment on lines
+60
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first diagonal block entry has a positive sense of rotation, but the second one should have a negative. (As of now, both are coded the same). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The sense of rotation is still documented in the wrong way here |
||
""" | ||
t_vsd = 1/ 3 * np.array([ | ||
[1, -0.5, -0.5, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0], | ||
[0, 0.5 * np.sqrt(3), -0.5 * np.sqrt(3), 0.5, 0.5, -1], | ||
[1, -0.5, -0.5, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0], | ||
[0, -0.5 * np.sqrt(3), 0.5 * np.sqrt(3), 0.5, 0.5, -1], | ||
]) | ||
|
||
def rotation_matrix(theta): | ||
return np.array([ | ||
[math.cos(theta), math.sin(theta)], | ||
[-math.sin(theta), math.cos(theta)] | ||
]) | ||
|
||
t1 = rotation_matrix(epsilon) | ||
t2 = rotation_matrix(-epsilon) | ||
tp_alphaBetaXY = np.block([ | ||
[t1, np.zeros(t1.shape[0],t1.shape[1])], | ||
[np.zeros(t2.shape[0],t2.shape[1]), t2], | ||
]) | ||
Comment on lines
+82
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. scipy provides a command that should make this snippet more clear https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.block_diag.html |
||
tp_vsd = np.matmul(tp_alphaBetaXY, t_vsd) | ||
return np.matmul(tp_vsd, quantities) | ||
|
||
|
||
|
||
|
||
def _torque_limit(self): | ||
""" | ||
Returns: | ||
Maximal possible torque for the given limits in self._limits | ||
""" | ||
raise NotImplementedError() |
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.
u_sy