R_flux_identification_wrapper.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**********************************
  2. * 电阻和磁链识别模块
  3. * 功能:使用递归最小二乘(RLS)算法在线估计电机电阻和磁链值
  4. **********************************/
  5. #if defined(MATLAB_MEX_FILE)
  6. #include "tmwtypes.h"
  7. #include "simstruc_types.h"
  8. #else
  9. #include "rtwtypes.h"
  10. #endif
  11. #include <math.h>
  12. // 全局变量
  13. float theta0_1_1; // 前一时刻的电阻估计值
  14. float theta0_2_1; // 前一时刻的磁链估计值
  15. float Pn0_1_1; // 误差协方差矩阵元素 (1,1)
  16. float Pn0_1_2; // 误差协方差矩阵元素 (1,2)
  17. float Pn0_2_1; // 误差协方差矩阵元素 (2,1)
  18. float Pn0_2_2; // 误差协方差矩阵元素 (2,2)
  19. float x_1_1; // 状态变量1(电阻估计值)
  20. float x_1_2; // 状态变量2(协方差矩阵元素 (1,1))
  21. float x_1_3; // 状态变量3(协方差矩阵元素 (1,2))
  22. float x_2_1; // 状态变量4(磁链估计值)
  23. float x_2_2; // 状态变量5(协方差矩阵元素 (2,1))
  24. float x_2_3; // 状态变量6(协方差矩阵元素 (2,2))
  25. float h_1_1; // 输入1(q轴电流)
  26. float h_2_1; // 输入2(电角速度)
  27. float r_K_1_1; // 卡尔曼增益1
  28. float r_K_2_1; // 卡尔曼增益2
  29. float Pn1_1_1; // 更新后的协方差矩阵元素 (1,1)
  30. float Pn1_1_2; // 更新后的协方差矩阵元素 (1,2)
  31. float Pn1_2_1; // 更新后的协方差矩阵元素 (2,1)
  32. float Pn1_2_2; // 更新后的协方差矩阵元素 (2,2)
  33. float theta1_1_1; // 当前时刻的电阻估计值
  34. float theta1_2_1; // 当前时刻的磁链估计值
  35. float r_temp_1_1; // 临时变量1
  36. float r_temp_1_2; // 临时变量2
  37. float r_temp_2_1; // 临时变量3
  38. float r_temp_2_2; // 临时变量4
  39. float r_Uq; // q轴电压输入
  40. // 输入输出宽度定义
  41. #define u_width 3 // 输入宽度:[q轴电流, 电角速度, q轴电压]
  42. #define y_width 2 // 输出宽度:[电阻估计值, 磁链估计值]
  43. /**
  44. * @brief 电阻和磁链识别初始化函数
  45. * @param xD: 状态变量数组
  46. * @note 初始化电阻和磁链估计值以及误差协方差矩阵
  47. */
  48. void R_flux_identification_Start_wrapper(real_T *xD)
  49. {
  50. // 初始化电阻估计值(初始值设为0.05Ω)
  51. theta0_1_1 = 0.05f;
  52. // 初始化磁链估计值(初始值设为0.01Wb)
  53. theta0_2_1 = 0.01f;
  54. // 初始化误差协方差矩阵
  55. Pn0_1_1 = 0.0008f * 2.0f; // 协方差矩阵 (1,1)
  56. Pn0_1_2 = 0.0008f * 0.0f; // 协方差矩阵 (1,2)
  57. Pn0_2_1 = 0.0008f * 0.0f; // 协方差矩阵 (2,1)
  58. Pn0_2_2 = 0.0008f * 2.0f; // 协方差矩阵 (2,2)
  59. // 初始化状态变量
  60. x_1_1 = theta0_1_1; // 状态1:电阻估计值
  61. x_2_1 = theta0_2_1; // 状态2:磁链估计值
  62. x_1_2 = Pn0_1_1; // 状态3:协方差矩阵 (1,1)
  63. x_1_3 = Pn0_1_2; // 状态4:协方差矩阵 (1,2)
  64. x_2_2 = Pn0_2_1; // 状态5:协方差矩阵 (2,1)
  65. x_2_3 = Pn0_2_2; // 状态6:协方差矩阵 (2,2)
  66. }
  67. /**
  68. * @brief 电阻和磁链识别输出函数
  69. * @param u: 输入数组 [q轴电流, 电角速度, q轴电压]
  70. * @param y: 输出数组 [电阻估计值, 磁链估计值]
  71. * @param xD: 状态变量数组
  72. * @note 输出当前的电阻和磁链估计值
  73. */
  74. void R_flux_identification_Outputs_wrapper(const real32_T *u,
  75. real32_T *y,
  76. const real_T *xD)
  77. {
  78. // 输出电阻估计值
  79. y[0] = x_1_1;
  80. // 输出磁链估计值
  81. y[1] = x_2_1;
  82. }
  83. /**
  84. * @brief 电阻和磁链识别更新函数
  85. * @param u: 输入数组 [q轴电流, 电角速度, q轴电压]
  86. * @param y: 输出数组 [电阻估计值, 磁链估计值]
  87. * @param xD: 状态变量数组
  88. * @note 使用递归最小二乘(RLS)算法更新电阻和磁链估计值
  89. */
  90. void R_flux_identification_Update_wrapper(const real32_T *u,
  91. real32_T *y,
  92. real_T *xD)
  93. {
  94. // 获取输入参数
  95. h_1_1 = u[0]; // q轴电流
  96. h_2_1 = u[1]; // 电角速度
  97. r_Uq = u[2]; // q轴电压
  98. // 获取前一时刻的状态
  99. Pn0_1_1 = x_1_2; // 协方差矩阵 (1,1)
  100. Pn0_1_2 = x_1_3; // 协方差矩阵 (1,2)
  101. Pn0_2_1 = x_2_2; // 协方差矩阵 (2,1)
  102. Pn0_2_2 = x_2_3; // 协方差矩阵 (2,2)
  103. // 计算卡尔曼增益
  104. r_temp_1_1 = 1.0f + (((h_1_1 * Pn0_1_1 + h_2_1 * Pn0_2_1) * h_1_1) + ((h_1_1 * Pn0_1_2 + h_2_1 * Pn0_2_2) * h_2_1));
  105. r_temp_1_1 = 1.0f / r_temp_1_1;
  106. r_K_1_1 = (Pn0_1_1 * h_1_1 + Pn0_1_2 * h_2_1) * r_temp_1_1;
  107. r_K_2_1 = (Pn0_2_1 * h_1_1 + Pn0_2_2 * h_2_1) * r_temp_1_1;
  108. // 更新误差协方差矩阵
  109. r_temp_1_1 = r_K_1_1 * h_1_1;
  110. r_temp_1_2 = r_K_1_1 * h_2_1;
  111. r_temp_2_1 = r_K_2_1 * h_1_1;
  112. r_temp_2_2 = r_K_2_1 * h_2_1;
  113. Pn1_1_1 = Pn0_1_1 - (r_temp_1_1 * Pn0_1_1 + r_temp_1_2 * Pn0_2_1);
  114. Pn1_1_2 = Pn0_1_2 - (r_temp_1_1 * Pn0_1_2 + r_temp_1_2 * Pn0_2_2);
  115. Pn1_2_1 = Pn0_2_1 - (r_temp_2_1 * Pn0_1_1 + r_temp_2_2 * Pn0_2_1);
  116. Pn1_2_2 = Pn0_2_2 - (r_temp_2_1 * Pn0_1_2 + r_temp_2_2 * Pn0_2_2);
  117. // 获取前一时刻的估计值
  118. theta0_1_1 = x_1_1; // 前一时刻的电阻估计值
  119. theta0_2_1 = x_2_1; // 前一时刻的磁链估计值
  120. // 更新电阻和磁链估计值
  121. // 公式:theta1 = theta0 + K * (Uq - (h1*theta0_1*0.999 + h2*theta0_2*0.999))
  122. // 其中0.999是一个近似系数,用于考虑其他因素的影响
  123. theta1_1_1 = theta0_1_1 + r_K_1_1 * (r_Uq - (h_1_1 * theta0_1_1 * 0.999f + h_2_1 * theta0_2_1 * 0.999f));
  124. theta1_2_1 = theta0_2_1 + r_K_2_1 * (r_Uq - (h_1_1 * theta0_1_1 * 0.999f + h_2_1 * theta0_2_1 * 0.999f));
  125. // 更新状态变量
  126. x_1_1 = theta1_1_1; // 更新电阻估计值
  127. x_2_1 = theta1_2_1; // 更新磁链估计值
  128. x_1_2 = Pn1_1_1; // 更新协方差矩阵 (1,1)
  129. x_1_3 = Pn1_1_2; // 更新协方差矩阵 (1,2)
  130. x_2_2 = Pn1_2_1; // 更新协方差矩阵 (2,1)
  131. x_2_3 = Pn1_2_2; // 更新协方差矩阵 (2,2)
  132. }
  133. /**********************************
  134. * 电阻和磁链识别算法原理
  135. *
  136. * 1. 基本原理:
  137. * - 使用递归最小二乘(RLS)算法在线估计电机的电阻和磁链值
  138. * - 基于电机的q轴电压方程:Uq = R*Iq + L*dIq/dt + ω*ψ
  139. * - 当Iq为恒定值时,dIq/dt = 0,方程简化为Uq = R*Iq + ω*ψ
  140. * - 通过测量Uq、Iq和ω来同时估计R和ψ
  141. *
  142. * 2. 数学推导:
  143. * a. 从q轴电压方程开始(假设dIq/dt ≈ 0):
  144. * Uq = R*Iq + ω*ψ
  145. * b. 令y = Uq,φ = [Iq, ω],θ = [R, ψ],则:
  146. * y = φ^T * θ
  147. * c. 这是一个线性模型,其中R和ψ是待估计的参数
  148. * d. 使用递归最小二乘(RLS)算法估计θ:
  149. * - 初始化:θ0 = [R0, ψ0]^T,P0 = 初始误差协方差矩阵
  150. * - 预测:?k = φk^T * θk-1
  151. * - 预测误差:ek = yk - ?k
  152. * - 卡尔曼增益:Kk = Pk-1*φk/(1 + φk^T*Pk-1*φk)
  153. * - 参数更新:θk = θk-1 + Kk*ek
  154. * - 协方差更新:Pk = (I - Kk*φk^T)*Pk-1
  155. *
  156. * 3. 算法流程:
  157. * - 初始化电阻和磁链估计值以及误差协方差矩阵
  158. * - 每次采样时,根据输入的q轴电流、电角速度和q轴电压计算卡尔曼增益
  159. * - 使用卡尔曼增益更新电阻和磁链估计值以及误差协方差矩阵
  160. * - 输出更新后的电阻和磁链估计值
  161. *
  162. * 4. 优点:
  163. * - 在线实时估计,能够适应电机参数的变化
  164. * - 同时估计电阻和磁链两个参数
  165. * - 计算量适中,适合在嵌入式系统中使用
  166. * - 不需要专门的测试信号,可以在正常运行时进行估计
  167. **********************************/