function [uq, ud_comp] = SpeedCurrent_MPC_Simulink(omega, iq, omega_ref)
% 带速度和电流约束的非级联MPC(PMSM专用),兼容Simulink代码生成
% 输入: omega(当前速度, rad/s), iq(当前q轴电流, A), omega_ref(速度参考, rad/s)
% 输出: uq(q轴电压指令, V), ud_comp(d轴电压补偿, V,此处设为0,可扩展)
%% 1. 关键参数定义(预定义所有变量,避免未定义错误)
% 采样与硬件参数
Tms = 0.001; % 采样时间 (s)
u_max = 310; % 最大相电压(默认380V电网下的直流母线电压√2*220≈310V)
id = 0; % d轴电流指令(弱磁前设为0)
% 电机参数(根据实际电机调整)
J = 0.020; % 转动惯量 (kg·m²)
B = 0.008; % 粘性阻尼系数 (N·m/(rad/s))
P = 4; % 极对数
Kt = 1; % 转矩系数 (N·m/A)
R = 0.4; % 定子电阻 (Ω)
Lq = 6e-3; % q轴电感 (H)
Ld = 6e-3; % d轴电感 (H)(表贴式电机Ld=Lq)
Psi_f = 0.186; % 永磁磁链 (Wb)
% MPC核心参数
Np = 20; % 预测时域(步数)
Nc = 12; % 控制时域(步数)
% 权重矩阵(根据调试调整,速度权重>电流权重)
Q_omega = 0.1; % 速度误差权重
Q_iq = 10; % q轴电流误差权重
R_uq = 0.1; % q轴电压增量权重
% 物理约束(避免超调或硬件损坏)
omega_max = 3000; % 最大速度 (rad/s)
iq_max = 40; % 最大q轴电流 (A)
delta_uq_max = 50; % 电压增量约束(避免电压跳变,V)
%% 2. 状态空间模型(PMSM dq轴数学模型,3阶状态:id, iq, omega)
% 状态矩阵 Am (3×3):[id_dot; iq_dot; omega_dot] = Am*[id; iq; omega] + Bm*[ud; uq]
Am = [ -R/Ld, omega*(Lq/Ld), -Psi_f/(Ld);
-omega*(Ld/Lq), -R/Lq, 0;
0, (3*P*Kt)/(2*J), -B/J ];
% 输入矩阵 Bm (3×2):ud控制id,uq控制iq和omega
Bm = [1/Ld, 0;
0, 1/Lq;
0, 0 ];
% 输出矩阵 Cm (2×3):关注iq和omega(非级联控制目标)
Cm = [0, 1, 0; % 输出1:iq
0, 0, 1]; % 输出2:omega
%% 3. 模型离散化(零阶保持ZOH,适配数字控制)
% 构造增广矩阵用于离散化:[Am Bm; 0 0] (5×5)
aug_mat = [Am, Bm;
zeros(2, 3), zeros(2, 2)];
% 离散化矩阵(expm实现ZOH离散化,预定义尺寸避免Simulink推断错误)
M = expm(aug_mat * Tms);
Ad = M(1:3, 1:3); % 离散状态矩阵 (3×3)
Bd = M(1:3, 4:5); % 离散输入矩阵 (3×2)
%% 4. MPC增广模型(状态+前一时刻输入,解决增量控制)
% 增广状态:[id; iq; omega; uq_prev] (4×1),仅控制uq(ud=0)
nx_aug = 4; % 增广状态维度
nu_aug = 1; % 控制输入维度(仅uq)
ny_aug = 2; % 输出维度(iq, omega)
% 增广状态矩阵 A_aug (4×4)
A_aug = [Ad, Bd(:, 2); % Bd(:,2)是uq对原状态的影响
zeros(1, 3), 1];% 前一时刻uq的传递(u_prev(k+1)=u(k))
% 增广输入矩阵 B_aug (4×1)
B_aug = [Bd(:, 2); 1]; % 输入是uq增量Δuq,u(k)=u(k-1)+Δuq
% 增广输出矩阵 C_aug (2×4):输出iq和omega
C_aug = [0, 1, 0, 0; % 输出iq(与增广状态第2维对应)
0, 0, 1, 0]; % 输出omega(与增广状态第3维对应)
%% 5. 预测矩阵构建(预定义尺寸,适配Simulink代码生成)
% phi: 状态预测矩阵 (Np*ny_aug × nx_aug) = [C_aug*A_aug^1; C_aug*A_aug^2; ...; C_aug*A_aug^Np]
phi = zeros(Np*ny_aug, nx_aug);
% F: 控制预测矩阵 (Np*ny_aug × Nc*nu_aug) = [C_aug*B_aug, 0,...0; C_aug*A_aug*B_aug, C_aug*B_aug,...0; ...]
F = zeros(Np*ny_aug, Nc*nu_aug);
for i = 1:Np
% 填充phi:第i步状态预测
phi((i-1)*ny_aug+1:i*ny_aug, :) = C_aug * (A_aug^i);
% 填充F:第i步控制影响(仅控制时域内的输入)
for j = 1:min(i, Nc)
col_idx = (j-1)*nu_aug + 1;
F((i-1)*ny_aug+1:i*ny_aug, col_idx) = C_aug * (A_aug^(i-j)) * B_aug;
end
end
%% 6. 权重矩阵与参考轨迹(预定义尺寸,避免动态维度)
% 输出权重矩阵 Q_bar (Np*ny_aug × Np*ny_aug):对角矩阵,按输出维度分配权重
Q_bar = zeros(Np*ny_aug, Np*ny_aug);
for i = 1:Np
% 第i步的iq权重(Q_iq)和omega权重(Q_omega)
Q_bar((i-1)*ny_aug+1, (i-1)*ny_aug+1) = Q_iq; % iq权重
Q_bar((i-1)*ny_aug+2, (i-1)*ny_aug+2) = Q_omega; % omega权重
end
% 控制权重矩阵 R_bar (Nc*nu_aug × Nc*nu_aug):电压增量权重
R_bar = kron(eye(Nc), R_uq);
% 参考轨迹 r_seq (Np*ny_aug × 1):未来Np步跟踪iq_ref和omega_ref(iq_ref由速度计算)
% 简化:iq_ref = (J*(omega_ref - omega) + B*omega)/(3*P*Kt/2)(基于转矩平衡)
iq_ref = min( (J*(omega_ref - omega) + B*omega) / (3*P*Kt/2), iq_max );
r_seq = repmat([iq_ref; omega_ref], Np, 1); % 每步参考都是[iq_ref; omega_ref]
%% 7. 增广状态向量(当前状态+前一时刻输入,预定义尺寸)
% 初始化前一时刻uq(persistent变量,首次运行设为0,适配Simulink)
persistent uq_prev;
if isempty(uq_prev)
uq_prev = 0; % 初始电压为0,避免首次运行错误
end
% 当前增广状态:[id; iq; omega; uq_prev] (4×1)
x_aug_current = [id; iq; omega; uq_prev];
%% 8. 二次规划问题构建(带约束,适配quadprog)
% 目标函数:min_ΔU (0.5*ΔU'*H*ΔU + ΔU'*E)
H = F' * Q_bar * F + R_bar; % 二次项矩阵 (Nc×Nc)
E = F' * Q_bar * (phi * x_aug_current - r_seq); % 线性项向量 (Nc×1)
% 约束条件:ΔU ∈ [lb, ub](电压增量约束)
lb = -delta_uq_max * ones(Nc, 1); % 最小增量
ub = delta_uq_max * ones(Nc, 1); % 最大增量
% 使用quadprog求解优化问题(支持代码生成)
% 注意:Simulink代码生成要求指定优化选项,且算法必须支持代码生成(如'interior-point-convex')
% 初始化Delta_U
Delta_U = zeros(Nc,1);
% 尝试使用内点法
options = optimoptions('quadprog','Algorithm','active-set');
% 提供初始点
x0 = zeros(Nc, 1);
Delta_U = quadprog(H, E, [], [], [], [], lb, ub, x0, options);
% 提取第一个控制增量
Delta_uq = Delta_U(1); % 第一个控制增量
uq_current = uq_prev + Delta_uq;
% 电压限幅(确保在[-u_max, u_max]范围内)
uq_current = max(min(uq_current, u_max), -u_max);
% 更新前一时刻控制量(用于下一次)
uq_prev = uq_current;
% 输出当前控制量(q轴电压)
uq = uq_current;
% d轴补偿设为0
ud_comp = 0;
end电流调节次数太慢了