svpwm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. #include "foc/core/svpwm.h"
  2. #include "math/fast_math.h"
  3. #if 0
  4. static void __inline ModuleTime(u32 *T4, u32 *T6, u32 PWM_Period) {
  5. u32 period = PWM_Period * 95 / 100; //95%�ĵ���
  6. if (*T4 + *T6 > period){
  7. float ration = ((float)period)/((float)*T4 + (float)*T6);
  8. *T4 *= ration;
  9. *T6 *= ration;
  10. }
  11. }
  12. void SVPWM_ST(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out){
  13. u32 PWM_Period = PWM_half_period * 2;
  14. float wAlpha = SQRT3 * alpha_beta->alpha * 2.0f;
  15. float wBeta = -alpha_beta->beta * 2.0f;
  16. float X = wBeta * PWM_Period/vbus;
  17. float Y = (wBeta + wAlpha)*PWM_Period/vbus/2.0f;
  18. float Z = (wBeta - wAlpha)*PWM_Period/vbus/2.0f;
  19. s32 tA, tB, tC;
  20. s32 low, midle, high;
  21. if (Y < 0) {
  22. if (Z < 0) {
  23. *sector_out = 5;
  24. tA = PWM_Period/4 + (Y - Z)/4;
  25. tB = tA + Z/2;
  26. tC = tA - Y/2;
  27. low = tC;
  28. midle = tA;
  29. high = tB;
  30. }else {
  31. if (X <= 0 ) {
  32. *sector_out = 4;
  33. tA = PWM_Period/4 + (X - Z)/4;
  34. tB = tA + Z/2;
  35. tC = tB - X/2;
  36. low = tC;
  37. midle = tB;
  38. high = tA;
  39. }else {
  40. *sector_out = 3;
  41. tA = PWM_Period/4 + (Y - X)/4;
  42. tC = tA - Y/2;
  43. tB = tC + X/2;
  44. low = tB;
  45. midle = tC;
  46. high = tA;
  47. }
  48. }
  49. }else {
  50. if (Z >= 0) {
  51. *sector_out = 2;
  52. tA = PWM_Period/4 + (Y - Z)/4;
  53. tB= tA + Z/2;
  54. tC = tA - Y/2;
  55. low = tB;
  56. midle = tC;
  57. high = tA;
  58. }else {
  59. if (X <= 0 ) {
  60. *sector_out = 6;
  61. tA = PWM_Period/4 + (Y - X)/4;
  62. tC = tA - Y/2;
  63. tB = tC + X/2;
  64. low = tA;
  65. midle = tC;
  66. high = tB;
  67. } else {
  68. *sector_out = 1;
  69. tA = PWM_Period/4 + (X - Z)/4;
  70. tB = tA + Z/2;
  71. tC = tB - X/2;
  72. low = tA;
  73. midle = tB;
  74. high = tC;
  75. }
  76. }
  77. }
  78. phase_out->A = ( uint16_t )tA;
  79. phase_out->B = ( uint16_t )tB;
  80. phase_out->C = ( uint16_t )tC;
  81. phase_out->low = low;
  82. phase_out->midle = midle;
  83. phase_out->high = high;
  84. }
  85. void SVPWM_7(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out) {
  86. float alpha = alpha_beta->alpha * 2.0f / 3.0f;
  87. float beta = alpha_beta->beta * 2.0f / 3.0f;
  88. u8 sector = 0xFF;
  89. u32 A_duty, B_duty, C_duty;
  90. u32 low, midle, high;
  91. u32 T1, T2;
  92. float X, Y, Z;
  93. float modu = (float)(PWM_half_period) / vbus;
  94. if (beta >= 0.0f) {
  95. if (alpha >= 0.0f) {
  96. //quadrant I
  97. if (ONE_BY_SQRT3 * beta > alpha) {
  98. sector = SECTOR_2;
  99. } else {
  100. sector = SECTOR_1;
  101. }
  102. } else {
  103. //quadrant II
  104. if (-ONE_BY_SQRT3 * beta > alpha) {
  105. sector = SECTOR_3;
  106. } else {
  107. sector = SECTOR_2;
  108. }
  109. }
  110. } else {
  111. if (alpha >= 0.0f) {
  112. //quadrant IV5
  113. if (-ONE_BY_SQRT3 * beta > alpha) {
  114. sector = SECTOR_5;
  115. } else {
  116. sector = SECTOR_6;
  117. }
  118. } else {
  119. //quadrant III
  120. if (ONE_BY_SQRT3 * beta > alpha) {
  121. sector = SECTOR_4;
  122. } else {
  123. sector = SECTOR_5;
  124. }
  125. }
  126. }
  127. //X = SQRT3 * beta * modu;
  128. X = TWO_BY_SQRT3 * beta * modu;
  129. //Y = (1.5f * alpha + SQRT3_BY_2 * beta) * modu;
  130. Y = (alpha + ONE_BY_SQRT3 * beta) * modu;
  131. //Z = (-1.5f * alpha + SQRT3_BY_2 * beta) * modu;
  132. Z = (-alpha + ONE_BY_SQRT3 * beta) * modu;
  133. switch(sector) {
  134. case SECTOR_1: // 3
  135. T1 = -Z;
  136. T2 = X;
  137. break;
  138. case SECTOR_2: // 1
  139. T1 = Z;
  140. T2 = Y;
  141. break;
  142. case SECTOR_3: // 5
  143. T1 = X;
  144. T2 = -Y;
  145. break;
  146. case SECTOR_4: // 4
  147. T1 = -X;
  148. T2 = Z;
  149. break;
  150. case SECTOR_5: // 6
  151. T1 = -Y;
  152. T2 = -Z;
  153. break;
  154. case SECTOR_6: // 2
  155. T1 = Y;
  156. T2 = -X;
  157. break;
  158. default:
  159. break;
  160. }
  161. ModuleTime(&T1, &T2, PWM_half_period);
  162. /*
  163. u32 ta = (PWM_half_period - T1 - T2) / 2;
  164. u32 tb = ta + T1 ;
  165. u32 tc = tb + T2 ; */
  166. switch(sector) {
  167. case SECTOR_1: // 3
  168. A_duty = (PWM_half_period - T1 - T2) / 2;
  169. B_duty = A_duty + T1;
  170. C_duty = B_duty + T2;
  171. low = C_duty;
  172. midle = B_duty;
  173. high = A_duty;
  174. break;
  175. case SECTOR_2: // 1
  176. B_duty = (PWM_half_period - T1 - T2) / 2;
  177. A_duty = B_duty + T1;
  178. C_duty = A_duty + T2;
  179. low = C_duty;
  180. midle = A_duty;
  181. high = B_duty;
  182. break;
  183. case SECTOR_3: // 5
  184. B_duty = (PWM_half_period - T1 - T2) / 2;
  185. C_duty = B_duty + T1;
  186. A_duty = C_duty + T2;
  187. low = A_duty;
  188. midle = C_duty;
  189. high = B_duty;
  190. break;
  191. case SECTOR_4: // 4
  192. C_duty = (PWM_half_period - T1 - T2) / 2;
  193. B_duty = C_duty + T1;
  194. A_duty = B_duty + T2;
  195. low = A_duty;
  196. midle = B_duty;
  197. high = C_duty;
  198. break;
  199. case SECTOR_5: // 6
  200. C_duty = (PWM_half_period - T1 - T2) / 2;
  201. A_duty = C_duty + T1;
  202. B_duty = A_duty + T2;
  203. low = B_duty;
  204. midle = A_duty;
  205. high = C_duty;
  206. break;
  207. case SECTOR_6: // 2
  208. A_duty = (PWM_half_period - T1 - T2) / 2;
  209. C_duty = A_duty + T1;
  210. B_duty = C_duty + T2;
  211. low = B_duty;
  212. midle = C_duty;
  213. high = A_duty;
  214. break;
  215. default:
  216. break;
  217. }
  218. phase_out->A = A_duty;
  219. phase_out->B = B_duty;
  220. phase_out->C = C_duty;
  221. phase_out->low = low;
  222. phase_out->midle = midle;
  223. phase_out->high = high;
  224. *sector_out = sector;
  225. // printf("3sec %d, A:%d, B:%d, C:%d\n", sector, A_duty, B_duty, C_duty);
  226. }
  227. /* 7段式SVPWM
  228. * 返回设置3相PWM的3个CCR寄存器的值
  229. * 这里使用的是stm32的PWM mode1,在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
  230. * 在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
  231. * 整个时间的计算,前面X,Y,Z都是一样的,后面计算ABC三相的pwm CCR寄存器值的时候,需要注意,很多网络包括书本的资料都是用PWM2模式的
  232. 就是高电平的时间 pwm_period - ccr,我们用PWM1模式,所以最后abc的计算稍微有些不一样
  233. */
  234. void SVM_Get_Phase_Time(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out) {
  235. float alpha = alpha_beta->alpha * SQRT3_BY_2;
  236. float beta = alpha_beta->beta * SQRT3_BY_2;
  237. u32 PWM_Period = PWM_half_period * 2;
  238. u8 sector = 0xFF;
  239. u32 tA, tB, tC;
  240. u32 low, midle, high;
  241. float X, Y, Z;
  242. float modu = (float)(PWM_Period) / vbus;
  243. if (beta >= 0.0f) {
  244. if (alpha >= 0.0f) {
  245. //quadrant I
  246. if (ONE_BY_SQRT3 * beta > alpha) {
  247. sector = SECTOR_2;
  248. } else {
  249. sector = SECTOR_1;
  250. }
  251. } else {
  252. //quadrant II
  253. if (-ONE_BY_SQRT3 * beta > alpha) {
  254. sector = SECTOR_3;
  255. } else {
  256. sector = SECTOR_2;
  257. }
  258. }
  259. } else {
  260. if (alpha >= 0.0f) {
  261. //quadrant IV5
  262. if (-ONE_BY_SQRT3 * beta > alpha) {
  263. sector = SECTOR_5;
  264. } else {
  265. sector = SECTOR_6;
  266. }
  267. } else {
  268. //quadrant III
  269. if (ONE_BY_SQRT3 * beta > alpha) {
  270. sector = SECTOR_4;
  271. } else {
  272. sector = SECTOR_5;
  273. }
  274. }
  275. }
  276. X = TWO_BY_SQRT3 * beta * modu;
  277. Y = (alpha + ONE_BY_SQRT3 * beta) * modu;
  278. Z = (-alpha + ONE_BY_SQRT3 * beta) * modu;
  279. switch(sector) {
  280. case SECTOR_1: // 3
  281. { u32 T4 = -Z;
  282. u32 T6 = X;
  283. tC = (PWM_Period - T4 - T6)/4;
  284. tB = tC + T6/2;
  285. tA = tB + T4/2;
  286. low = tA;
  287. midle = tB;
  288. high = tC;
  289. break;
  290. }
  291. case SECTOR_2: // 1
  292. {
  293. u32 T6 = Y;
  294. u32 T2 = Z;
  295. tC = (PWM_Period - T6 - T2)/4;
  296. tA = tC + T6/2;
  297. tB = tA + T2/2;
  298. low = tB;
  299. midle = tA;
  300. high = tC;
  301. break;
  302. }
  303. case SECTOR_3: // 5
  304. {
  305. u32 T2 = X;
  306. u32 T3 = -Y;
  307. tA = (PWM_Period - T2 - T3)/4;
  308. tC = tA + T3/2;
  309. tB = tC + T2/2;
  310. low = tB;
  311. midle = tC;
  312. high = tA;
  313. break;
  314. }
  315. case SECTOR_4: // 4
  316. {
  317. u32 T1 = -X;
  318. u32 T3 = Z;
  319. tA = (PWM_Period - T1 - T3)/4;
  320. tB = tA + T3/2;
  321. tC = tB + T1/2;
  322. low = tC;
  323. midle = tB;
  324. high = tA;
  325. break;
  326. }
  327. case SECTOR_5: // 6
  328. {
  329. u32 T1 = -Y;
  330. u32 T5 = -Z;
  331. tB = (PWM_Period - T1 - T5)/4;
  332. tA = tB + T5/2;
  333. tC = tA + T1/2;
  334. low = tC;
  335. midle = tA;
  336. high = tB;
  337. break;
  338. }
  339. case SECTOR_6: // 2
  340. {
  341. u32 T4 = Y;
  342. u32 T5 = -X;
  343. tB = (PWM_Period - T4 - T5)/4;
  344. tC = tB + T5/2;
  345. tA = tC + T4/2;
  346. low = tA;
  347. midle = tC;
  348. high = tB;
  349. break;
  350. }
  351. default:
  352. break;
  353. }
  354. phase_out->A = tA;
  355. phase_out->B = tB;
  356. phase_out->C = tC;
  357. phase_out->low = low;
  358. phase_out->midle = midle;
  359. phase_out->high = high;
  360. *sector_out = sector;
  361. }
  362. #endif
  363. void SVM_Duty_Fix(AB_t *alb, s16q5_t vbus, u32 PWM_half_period, FOC_OutP *out) {
  364. s16q5_t alpha = S16_mul(alb->a, SQRT3_BY_2_Q14, 14);
  365. s16q5_t beta = S16_mul(alb->b, SQRT3_BY_2_Q14, 14);
  366. u32 PWM_Period = PWM_half_period * 2;
  367. u8 sector = 0xFF;
  368. u32 tA, tB, tC;
  369. u32 low, midle;
  370. u32 X, Y, Z;
  371. s16q5_t mod = ((PWM_Period << 10) / vbus) >> 5;
  372. if (beta >= 0) {
  373. if (alpha >= 0) {
  374. //quadrant I
  375. if (S16_mul(ONE_BY_SQRT3_Q14, beta, 14) > alpha) {
  376. sector = SECTOR_2;
  377. } else {
  378. sector = SECTOR_1;
  379. }
  380. } else {
  381. //quadrant II
  382. if (-S16_mul(ONE_BY_SQRT3_Q14, beta, 14) > alpha) {
  383. sector = SECTOR_3;
  384. } else {
  385. sector = SECTOR_2;
  386. }
  387. }
  388. } else {
  389. if (alpha >= 0.0f) {
  390. //quadrant IV5
  391. if (-S16_mul(ONE_BY_SQRT3_Q14 ,beta, 14) > alpha) {
  392. sector = SECTOR_5;
  393. } else {
  394. sector = SECTOR_6;
  395. }
  396. } else {
  397. //quadrant III
  398. if (S16_mul(ONE_BY_SQRT3_Q14, beta, 14) > alpha) {
  399. sector = SECTOR_4;
  400. } else {
  401. sector = SECTOR_5;
  402. }
  403. }
  404. }
  405. s16q5_t temp = S16_mul(ONE_BY_SQRT3_Q14, beta, 14);
  406. X = S16_mul(TWO_BY_SQRT3_Q14, S16_mul(beta, mod, 5), 14);
  407. Y = S16_mul((alpha + temp), mod, 5);
  408. Z = S16_mul((-alpha + temp) ,mod, 5);
  409. switch(sector) {
  410. case SECTOR_1: // 3
  411. { u32 T4 = -Z;
  412. u32 T6 = X;
  413. tC = (PWM_Period - T4 - T6)/4;
  414. tB = tC + T6/2;
  415. tA = tB + T4/2;
  416. low = tA;
  417. midle = tB;
  418. //high = tC;
  419. break;
  420. }
  421. case SECTOR_2: // 1
  422. {
  423. u32 T6 = Y;
  424. u32 T2 = Z;
  425. tC = (PWM_Period - T6 - T2)/4;
  426. tA = tC + T6/2;
  427. tB = tA + T2/2;
  428. low = tB;
  429. midle = tA;
  430. //high = tC;
  431. break;
  432. }
  433. case SECTOR_3: // 5
  434. {
  435. u32 T2 = X;
  436. u32 T3 = -Y;
  437. tA = (PWM_Period - T2 - T3)/4;
  438. tC = tA + T3/2;
  439. tB = tC + T2/2;
  440. low = tB;
  441. midle = tC;
  442. //high = tA;
  443. break;
  444. }
  445. case SECTOR_4: // 4
  446. {
  447. u32 T1 = -X;
  448. u32 T3 = Z;
  449. tA = (PWM_Period - T1 - T3)/4;
  450. tB = tA + T3/2;
  451. tC = tB + T1/2;
  452. low = tC;
  453. midle = tB;
  454. //high = tA;
  455. break;
  456. }
  457. case SECTOR_5: // 6
  458. {
  459. u32 T1 = -Y;
  460. u32 T5 = -Z;
  461. tB = (PWM_Period - T1 - T5)/4;
  462. tA = tB + T5/2;
  463. tC = tA + T1/2;
  464. low = tC;
  465. midle = tA;
  466. //high = tB;
  467. break;
  468. }
  469. case SECTOR_6: // 2
  470. {
  471. u32 T4 = Y;
  472. u32 T5 = -X;
  473. tB = (PWM_Period - T4 - T5)/4;
  474. tC = tB + T5/2;
  475. tA = tC + T4/2;
  476. low = tA;
  477. midle = tC;
  478. //high = tB;
  479. break;
  480. }
  481. default:
  482. break;
  483. }
  484. out->n_Duty[0] = tA;
  485. out->n_Duty[1] = tB;
  486. out->n_Duty[2] = tC;
  487. out->n_lowDuty = low;
  488. out->n_midDuty = midle;
  489. //out->n_highDuty = high;
  490. out->n_Sector = sector;
  491. }