svpwm.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #include "foc/svpwm.h"
  2. #include "math/fast_math.h"
  3. static void __inline ModuleTime(u32 *T4, u32 *T6, u32 PWM_Period) {
  4. u32 period = PWM_Period * 95 / 100; //95%�ĵ���
  5. if (*T4 + *T6 > period){
  6. float ration = ((float)period)/((float)*T4 + (float)*T6);
  7. *T4 *= ration;
  8. *T6 *= ration;
  9. }
  10. }
  11. void SVPWM_ST(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out){
  12. u32 PWM_Period = PWM_half_period * 2;
  13. float wAlpha = SQRT3 * alpha_beta->alpha * 2.0f;
  14. float wBeta = -alpha_beta->beta * 2.0f;
  15. float X = wBeta * PWM_Period/vbus;
  16. float Y = (wBeta + wAlpha)*PWM_Period/vbus/2.0f;
  17. float Z = (wBeta - wAlpha)*PWM_Period/vbus/2.0f;
  18. s32 tA, tB, tC;
  19. s32 low, midle, high;
  20. if (Y < 0) {
  21. if (Z < 0) {
  22. *sector_out = 5;
  23. tA = PWM_Period/4 + (Y - Z)/4;
  24. tB = tA + Z/2;
  25. tC = tA - Y/2;
  26. low = tC;
  27. midle = tA;
  28. high = tB;
  29. }else {
  30. if (X <= 0 ) {
  31. *sector_out = 4;
  32. tA = PWM_Period/4 + (X - Z)/4;
  33. tB = tA + Z/2;
  34. tC = tB - X/2;
  35. low = tC;
  36. midle = tB;
  37. high = tA;
  38. }else {
  39. *sector_out = 3;
  40. tA = PWM_Period/4 + (Y - X)/4;
  41. tC = tA - Y/2;
  42. tB = tC + X/2;
  43. low = tB;
  44. midle = tC;
  45. high = tA;
  46. }
  47. }
  48. }else {
  49. if (Z >= 0) {
  50. *sector_out = 2;
  51. tA = PWM_Period/4 + (Y - Z)/4;
  52. tB= tA + Z/2;
  53. tC = tA - Y/2;
  54. low = tB;
  55. midle = tC;
  56. high = tA;
  57. }else {
  58. if (X <= 0 ) {
  59. *sector_out = 6;
  60. tA = PWM_Period/4 + (Y - X)/4;
  61. tC = tA - Y/2;
  62. tB = tC + X/2;
  63. low = tA;
  64. midle = tC;
  65. high = tB;
  66. } else {
  67. *sector_out = 1;
  68. tA = PWM_Period/4 + (X - Z)/4;
  69. tB = tA + Z/2;
  70. tC = tB - X/2;
  71. low = tA;
  72. midle = tB;
  73. high = tC;
  74. }
  75. }
  76. }
  77. phase_out->A = ( uint16_t )tA;
  78. phase_out->B = ( uint16_t )tB;
  79. phase_out->C = ( uint16_t )tC;
  80. phase_out->low = low;
  81. phase_out->midle = midle;
  82. phase_out->high = high;
  83. }
  84. void SVPWM_7(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out) {
  85. float alpha = alpha_beta->alpha * 2.0f / 3.0f;
  86. float beta = alpha_beta->beta * 2.0f / 3.0f;
  87. u8 sector = 0xFF;
  88. u32 A_duty, B_duty, C_duty;
  89. u32 low, midle, high;
  90. u32 T1, T2;
  91. float X, Y, Z;
  92. float modu = (float)(PWM_half_period) / vbus;
  93. if (beta >= 0.0f) {
  94. if (alpha >= 0.0f) {
  95. //quadrant I
  96. if (ONE_BY_SQRT3 * beta > alpha) {
  97. sector = SECTOR_2;
  98. } else {
  99. sector = SECTOR_1;
  100. }
  101. } else {
  102. //quadrant II
  103. if (-ONE_BY_SQRT3 * beta > alpha) {
  104. sector = SECTOR_3;
  105. } else {
  106. sector = SECTOR_2;
  107. }
  108. }
  109. } else {
  110. if (alpha >= 0.0f) {
  111. //quadrant IV5
  112. if (-ONE_BY_SQRT3 * beta > alpha) {
  113. sector = SECTOR_5;
  114. } else {
  115. sector = SECTOR_6;
  116. }
  117. } else {
  118. //quadrant III
  119. if (ONE_BY_SQRT3 * beta > alpha) {
  120. sector = SECTOR_4;
  121. } else {
  122. sector = SECTOR_5;
  123. }
  124. }
  125. }
  126. //X = SQRT3 * beta * modu;
  127. X = TWO_BY_SQRT3 * beta * modu;
  128. //Y = (1.5f * alpha + SQRT3_BY_2 * beta) * modu;
  129. Y = (alpha + ONE_BY_SQRT3 * beta) * modu;
  130. //Z = (-1.5f * alpha + SQRT3_BY_2 * beta) * modu;
  131. Z = (-alpha + ONE_BY_SQRT3 * beta) * modu;
  132. switch(sector) {
  133. case SECTOR_1: // 3
  134. T1 = -Z;
  135. T2 = X;
  136. break;
  137. case SECTOR_2: // 1
  138. T1 = Z;
  139. T2 = Y;
  140. break;
  141. case SECTOR_3: // 5
  142. T1 = X;
  143. T2 = -Y;
  144. break;
  145. case SECTOR_4: // 4
  146. T1 = -X;
  147. T2 = Z;
  148. break;
  149. case SECTOR_5: // 6
  150. T1 = -Y;
  151. T2 = -Z;
  152. break;
  153. case SECTOR_6: // 2
  154. T1 = Y;
  155. T2 = -X;
  156. break;
  157. default:
  158. break;
  159. }
  160. ModuleTime(&T1, &T2, PWM_half_period);
  161. /*
  162. u32 ta = (PWM_half_period - T1 - T2) / 2;
  163. u32 tb = ta + T1 ;
  164. u32 tc = tb + T2 ; */
  165. switch(sector) {
  166. case SECTOR_1: // 3
  167. A_duty = (PWM_half_period - T1 - T2) / 2;
  168. B_duty = A_duty + T1;
  169. C_duty = B_duty + T2;
  170. low = C_duty;
  171. midle = B_duty;
  172. high = A_duty;
  173. break;
  174. case SECTOR_2: // 1
  175. B_duty = (PWM_half_period - T1 - T2) / 2;
  176. A_duty = B_duty + T1;
  177. C_duty = A_duty + T2;
  178. low = C_duty;
  179. midle = A_duty;
  180. high = B_duty;
  181. break;
  182. case SECTOR_3: // 5
  183. B_duty = (PWM_half_period - T1 - T2) / 2;
  184. C_duty = B_duty + T1;
  185. A_duty = C_duty + T2;
  186. low = A_duty;
  187. midle = C_duty;
  188. high = B_duty;
  189. break;
  190. case SECTOR_4: // 4
  191. C_duty = (PWM_half_period - T1 - T2) / 2;
  192. B_duty = C_duty + T1;
  193. A_duty = B_duty + T2;
  194. low = A_duty;
  195. midle = B_duty;
  196. high = C_duty;
  197. break;
  198. case SECTOR_5: // 6
  199. C_duty = (PWM_half_period - T1 - T2) / 2;
  200. A_duty = C_duty + T1;
  201. B_duty = A_duty + T2;
  202. low = B_duty;
  203. midle = A_duty;
  204. high = C_duty;
  205. break;
  206. case SECTOR_6: // 2
  207. A_duty = (PWM_half_period - T1 - T2) / 2;
  208. C_duty = A_duty + T1;
  209. B_duty = C_duty + T2;
  210. low = B_duty;
  211. midle = C_duty;
  212. high = A_duty;
  213. break;
  214. default:
  215. break;
  216. }
  217. phase_out->A = A_duty;
  218. phase_out->B = B_duty;
  219. phase_out->C = C_duty;
  220. phase_out->low = low;
  221. phase_out->midle = midle;
  222. phase_out->high = high;
  223. *sector_out = sector;
  224. // printf("3sec %d, A:%d, B:%d, C:%d\n", sector, A_duty, B_duty, C_duty);
  225. }
  226. /* 7段式SVPWM
  227. * 返回设置3相PWM的3个CCR寄存器的值
  228. * 这里使用的是stm32的PWM mode1,在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
  229. * 在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
  230. * 整个时间的计算,前面X,Y,Z都是一样的,后面计算ABC三相的pwm CCR寄存器值的时候,需要注意,很多网络包括书本的资料都是用PWM2模式的
  231. 就是高电平的时间 pwm_period - ccr,我们用PWM1模式,所以最后abc的计算稍微有些不一样
  232. */
  233. void SVM_Get_Phase_Time(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out) {
  234. float alpha = alpha_beta->alpha * SQRT3_BY_2;
  235. float beta = alpha_beta->beta * SQRT3_BY_2;
  236. u32 PWM_Period = PWM_half_period * 2;
  237. u8 sector = 0xFF;
  238. u32 tA, tB, tC;
  239. u32 low, midle, high;
  240. float X, Y, Z;
  241. float modu = (float)(PWM_Period) / vbus;
  242. if (beta >= 0.0f) {
  243. if (alpha >= 0.0f) {
  244. //quadrant I
  245. if (ONE_BY_SQRT3 * beta > alpha) {
  246. sector = SECTOR_2;
  247. } else {
  248. sector = SECTOR_1;
  249. }
  250. } else {
  251. //quadrant II
  252. if (-ONE_BY_SQRT3 * beta > alpha) {
  253. sector = SECTOR_3;
  254. } else {
  255. sector = SECTOR_2;
  256. }
  257. }
  258. } else {
  259. if (alpha >= 0.0f) {
  260. //quadrant IV5
  261. if (-ONE_BY_SQRT3 * beta > alpha) {
  262. sector = SECTOR_5;
  263. } else {
  264. sector = SECTOR_6;
  265. }
  266. } else {
  267. //quadrant III
  268. if (ONE_BY_SQRT3 * beta > alpha) {
  269. sector = SECTOR_4;
  270. } else {
  271. sector = SECTOR_5;
  272. }
  273. }
  274. }
  275. X = TWO_BY_SQRT3 * beta * modu;
  276. Y = (alpha + ONE_BY_SQRT3 * beta) * modu;
  277. Z = (-alpha + ONE_BY_SQRT3 * beta) * modu;
  278. switch(sector) {
  279. case SECTOR_1: // 3
  280. { u32 T4 = -Z;
  281. u32 T6 = X;
  282. tC = (PWM_Period - T4 - T6)/4;
  283. tB = tC + T6/2;
  284. tA = tB + T4/2;
  285. low = tA;
  286. midle = tB;
  287. high = tC;
  288. break;
  289. }
  290. case SECTOR_2: // 1
  291. {
  292. u32 T6 = Y;
  293. u32 T2 = Z;
  294. tC = (PWM_Period - T6 - T2)/4;
  295. tA = tC + T6/2;
  296. tB = tA + T2/2;
  297. low = tB;
  298. midle = tA;
  299. high = tC;
  300. break;
  301. }
  302. case SECTOR_3: // 5
  303. {
  304. u32 T2 = X;
  305. u32 T3 = -Y;
  306. tA = (PWM_Period - T2 - T3)/4;
  307. tC = tA + T3/2;
  308. tB = tC + T2/2;
  309. low = tB;
  310. midle = tC;
  311. high = tA;
  312. break;
  313. }
  314. case SECTOR_4: // 4
  315. {
  316. u32 T1 = -X;
  317. u32 T3 = Z;
  318. tA = (PWM_Period - T1 - T3)/4;
  319. tB = tA + T3/2;
  320. tC = tB + T1/2;
  321. low = tC;
  322. midle = tB;
  323. high = tA;
  324. break;
  325. }
  326. case SECTOR_5: // 6
  327. {
  328. u32 T1 = -Y;
  329. u32 T5 = -Z;
  330. tB = (PWM_Period - T1 - T5)/4;
  331. tA = tB + T5/2;
  332. tC = tA + T1/2;
  333. low = tC;
  334. midle = tA;
  335. high = tB;
  336. break;
  337. }
  338. case SECTOR_6: // 2
  339. {
  340. u32 T4 = Y;
  341. u32 T5 = -X;
  342. tB = (PWM_Period - T4 - T5)/4;
  343. tC = tB + T5/2;
  344. tA = tC + T4/2;
  345. low = tA;
  346. midle = tC;
  347. high = tB;
  348. break;
  349. }
  350. default:
  351. break;
  352. }
  353. phase_out->A = tA;
  354. phase_out->B = tB;
  355. phase_out->C = tC;
  356. phase_out->low = low;
  357. phase_out->midle = midle;
  358. phase_out->high = high;
  359. *sector_out = sector;
  360. }