接SVPWM原理分析-基於STM32 MC SDK 5.0這篇文章,分析了基本原理和代碼
本章節講實戰操作,通過本文可以了解到程序的完整運行流程。,
1.硬件篇,要調試首先要了解基本的硬件狀態,本文調試使用的是STM32F302的主控。
MOS管驅動部分如圖1所示
配置接口如下:
PA7 ------> TIM1_CH1N
PB0 ------> TIM1_CH2N
PB1 ------> TIM1_CH3N
PA8 ------> TIM1_CH1
PA9 ------> TIM1_CH2
PA10 ------> TIM1_CH3
配置高級定時器TIM1 產生6路互補的PWM,帶剎車保護,詳細配置代碼如下,
把下面的程序段拷貝到main.c 中直接可以輸出PWM波形(BKIN下拉),方便讀者驗證
先看主程序:
Volt_Components Vtest; int8_t bSector; int32_t wX, wY, wZ, wUAlpha, wUBeta; int16_t hTimePhA=0, hTimePhB=0, hTimePhC=0; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM1_Init(); Vtest.qV_Component1=-5000; Vtest.qV_Component2=-2000; while (1) { HAL_Delay(500); HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); CALC_SVPWM( Vtest); }
第一部分,定時器的初始化,如何判斷初始化正確:
static void MX_TIM1_Init(void) { /* USER CODE BEGIN TIM1_Init 0 */ /* USER CODE END TIM1_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; /* USER CODE BEGIN TIM1_Init 1 */ /* USER CODE END TIM1_Init 1 */ htim1.Instance = TIM1;//設置頻率為16k htim1.Init.Prescaler = ((TIM_CLOCK_DIVIDER) - 1);//分頻系數為0 htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;//TIM中央對齊模式1計數模式 htim1.Init.Period = ((PWM_PERIOD_CYCLES) / 2);/*Period max 4500 設置了在下一個更新事件裝入活動的自動重裝載寄存器周期的值。 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;/*設置定時器時鍾CK_INT頻率與死區發生器以及數字濾波器采樣時鍾頻率分頻化。Val ue:*/ htim1.Init.RepetitionCounter = REP_RATE;/*是否使用重復定時器, 當該值不為0的時候,計數器計數值達到周期數時,該值減1,計數器重新計數,當該值減到0的時候才會產生事件。*/ htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF; sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; sBreakDeadTimeConfig.DeadTime = DEADTIME; sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; sBreakDeadTimeConfig.BreakFilter = 0; sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_LOW; sBreakDeadTimeConfig.Break2Filter = 0; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE; if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM1_Init 2 */ /* USER CODE END TIM1_Init 2 */ HAL_TIM_MspPostInit(&htim1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); // TIM1->CCR1=1000;// // TIM1->CCR2=4500/2; // TIM1->CCR3=75; }
以下內容是重點,關於確認TIM定制器的配置是否ok
HAL_TIM_MspPostInit(&htim1); //GPIO 初始化 //以下是測試代碼:判斷GPIO的初始化是否OK,可以判斷死區的設置時間是否正確 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); TIM1->CCR1=1000;// TIM1->CCR2=4500/2; TIM1->CCR3=75;
PWM輸出占空比的范圍測試:
htim1.Init.Period =4500 ,頻率16K,對應的周期為:62.5uS,設定死區時間1000ns=1us。約占1.6%
占空比范圍測試:
序號 |
CCRX的值 |
TIM1_CH1N 占空比大小 |
TIM1_CH1N 高電平時間 |
TIM1_CH1 占空比大小 |
TIM1_CH1 高電平時間 |
備注 |
1 |
100 |
0.64% |
0.4uS |
96.15% |
60us |
|
2 |
500 |
9.615% |
6us |
87.18% |
54.4us |
|
3 |
1000 |
21.05% |
13.2us |
76.28% |
47.6us |
|
4 |
2250 |
48.72% |
30.40 |
48.41% |
30.4us |
|
5 |
4420 |
96.79% |
60.40us |
0.32% |
0.2us |
|
6 |
4450 |
97.12% |
(62.5-1.8)us |
0 |
0 |
超限制 |
7 |
4490 |
98.08% |
(62.5-1.2)us |
0 |
0 |
|
8 |
70 |
0 |
0 |
96.8% |
(62.5-2)us |
|
9 |
5 |
0 |
0 |
98.4% |
(62.5-1)us |
|
從以上實驗可知,超出4420之后TIM1_CH1N輸出高電平,TIM1_CH1輸出低電平
實測在4420-4500和 0-100,存在一部分單橋臂占空比變化區間
通過以上測試可以得到CCRX的值的變化范圍,極其對應占空比的大小變化范圍。
結論如下:CCRX的變化為為:100-4400,對應的占空比變化范圍為:0.64%~96.79%。
如何判斷死區時間是否合適?
CH1,CH2為單片機的輸出信號,CH3為MOS輸出信號,可以看到,時序上有明顯的滯后
滯后的主要原因在於MOS驅動電路的延時,驅動芯片采購:IRS2005驅動芯片
有驅動芯片可以得到,延時時間在160ns-220ns(驅動延時)左右。實際的延時誤差值在235ns(包含兩部分,驅動延時和mos開啟延時)
通道2位PWM輸出,通道3位驅動芯片輸出端,延時位186ns。
CH1,CH2 位MCU輸出波形,CH3和CH4位驅動芯片輸出波形。
CH1 MOS輸出的波形, CH2為TIM1_CH1N,CH3為TIM1_CH1。實測占空比如下,調節TIM1_CH1的占空比其實就是調整
MOS輸出的占空比。上圖是CCRX的值為100是的數據。
當CCRX=2500時的波形如下所示:
當CCRX=4100時的波形如下所示:
通過以上可以看到,CCRX的值和MOS輸出的波形的占空比成正比,機CCRX值越大,MOS輸出的占空比越大。
死區時間的本質是為了防止上下管同時導通,造成MOS燒毀,或者損耗增大, 軟件設置死區時間為1000ns.
#define DEADTIME_NS ((uint16_t)1000) //死區時間(ns),范圍:0-3500,死區時間:
#define DEADTIME_NS ((uint16_t)1500) //死區時間(ns),范圍:0-3500,死區時間:
可以看到死區時間明顯改變,死區時間的大小和MOS的性能相關性比較大,一般來說推薦設置為1000ns,可以可以根據實際情況具體調整,判斷的依據,就是死區時間要大於MOS管的開區和關閉時間,即CH1的波形的上升時間和下降時間。
上升時間:100ns,下降時間100ns,選擇不同 MOS參數會有差異。
以上講了這么多,主要是梳理了一下PWM從MCU的引腳輸出到控制MOS的輸出,整個流程,同時也回答了,如何判斷MOS死區時間設置是否爭取的問題。整個流程供大家參考。以上提供的豐富的波形,方便大家調試才考使用。
3.第三部分,回到正題,驗證第一篇文章中SVPWM函數輸入的Vα和Vβ到3路占空比的計算公式,是否正確。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ #define SYSCLK_FREQ 72000000uL #define TIM_CLOCK_DIVIDER 1 #define ADV_TIM_CLK_MHz 144 #define ADC_CLK_MHz 12 #define HALL_TIM_CLK 72000000uL #define PWM_FREQUENCY 16000 #define SW_DEADTIME_NS 1000 /*!< Dead-time to be inserted by FW, only if low side signals are enabled */ #define DEAD_TIME_ADV_TIM_CLK_MHz (ADV_TIM_CLK_MHz * TIM_CLOCK_DIVIDER)
#define REP_RATE (1) //該參數可以調整電流環的刷新頻率,刷新周期:(REP_RATE + 1)/(2*PWM_FREQ) 秒 #define PWM_PERIOD_CYCLES (uint16_t)(ADV_TIM_CLK_MHz*\ (unsigned long long)1000000u/((uint16_t)(PWM_FREQUENCY)))
#define DEADTIME_NS ((uint16_t)1000) //死區時間(ns),范圍:0-3500,死區時間:
#define DEADTIME (uint16_t)((unsigned long long)SYSCLK_FREQ/ 1*(unsigned long long)DEADTIME_NS/1000000000uL) /* USER CODE END PM */ //SVPWM波形 #define SQRT_3 1.732051 //根號3 #define T (PWM_PERIOD_CYCLES * 2) //TIM1 ARR值的4倍((PWM_PERIOD_CYCLES) / 2) #define T_SQRT3 (uint16_t)(T * SQRT_3) #define SECTOR_1 (uint32_t)1 #define SECTOR_2 (uint32_t)2 #define SECTOR_3 (uint32_t)3 #define SECTOR_4 (uint32_t)4 #define SECTOR_5 (uint32_t)5 #define SECTOR_6 (uint32_t)6
void CALC_SVPWM(Volt_Components Stat_Volt_Input) { // int8_t bSector; // int32_t wX, wY, wZ, wUAlpha, wUBeta; // int16_t hTimePhA=0, hTimePhB=0, hTimePhC=0;
wUAlpha = Stat_Volt_Input.qV_Component1 * T_SQRT3; wUBeta = -(Stat_Volt_Input.qV_Component2 * T);
wX = wUBeta; wY = (wUBeta + wUAlpha)/2; wZ = (wUBeta - wUAlpha)/2;
//下面是查找定子電流的扇區號 if (wY<0) { if (wZ<0) { bSector = SECTOR_5; } else // wZ >= 0 if (wX<=0) { bSector = SECTOR_4; } else // wX > 0 { bSector = SECTOR_3; } } else // wY > 0 { if (wZ>=0) { bSector = SECTOR_2; } else // wZ < 0 if (wX<=0) { bSector = SECTOR_6; } else // wX > 0 { bSector = SECTOR_1; } }
switch(bSector) //根據所在扇區號,計算三相占空比 { case SECTOR_1: case SECTOR_4: hTimePhA = (T/8) + ((((T + wX) - wZ)/2)/131072); hTimePhB = hTimePhA + wZ/131072; hTimePhC = hTimePhB - wX/131072; break; case SECTOR_2: case SECTOR_5: hTimePhA = (T/8) + ((((T + wY) - wZ)/2)/131072); hTimePhB = hTimePhA + wZ/131072; hTimePhC = hTimePhA - wY/131072; break;
case SECTOR_3: case SECTOR_6: hTimePhA = (T/8) + ((((T - wX) + wY)/2)/131072); hTimePhC = hTimePhA - wY/131072; hTimePhB = hTimePhC + wX/131072; break; default: break; }
TIM1->CCR1 = hTimePhA; TIM1->CCR2 = hTimePhB; TIM1->CCR3 = hTimePhC; }
|
代碼分析可以,Vtest.qV_Component1即為Vα Vtest.qV_Component2即為Vβ,下文直接用Vα ,Vβ表示
Vα ,Vβ值的變化范圍為:-32767~+32767。可以根據上表的數據大小范圍,推算出不用扇區並計算出對應的hTimePhA,hTimePhB和hTimePhC的值。
注意Vα,Vβ(未轉換)的值模值不可超過32767,超出范圍的電壓矢量不可以生成。當控制矢量在空間旋轉 360°后,逆變器就能輸出一個周期的正弦波電壓。
扇區 |
Vα |
Vβ |
hTimePhA |
hTimePhB |
hTimePhC |
V1 |
V2 |
V3 |
A占空比 |
C占空比 |
D占空比 |
備注 |
I |
1000 |
-1000 |
2343 |
2293 |
2156 |
12.37 |
11.95 |
11.03 |
51.92% |
51.04% |
47.92% |
占空比1>2>3 |
I |
20000 |
-5000 |
3600 |
1576 |
890 |
19.28 |
8.421 |
4.755 |
80.13% |
35.14% |
19.81% |
圖21 |
II |
2000 |
-5000 |
2487 |
2593 |
1906 |
13.16 |
13.63 |
9.66 |
55.13% |
57.51% |
42.31% |
占空比2>1>3 |
Ii |
2000 |
-20000 |
2487 |
3622 |
876 |
12.97 |
19.24 |
4.093 |
55.13% |
80.51% |
19.55% |
圖22 |
III |
-2000 |
-2000 |
2063 |
2473 |
2163 |
10.59 |
12.52 |
11.32 |
45.69% |
53.99% |
48.08% |
占空比2>3>1 |
III |
-30000 |
-2000 |
398 |
4102 |
3828 |
2.384 |
21.95 |
20.73 |
8.654% |
91.05% |
85.26% |
圖23 |
IV |
-2000 |
2000 |
2063 |
2163 |
2437 |
10.59 |
10.98 |
12.86 |
45.69 |
48.08 |
53.99 |
占空比3>2>1 |
IV |
-20000 |
5000 |
890 |
2925 |
3611 |
5.118 |
15.43 |
19.18 |
19.55 |
65.96 |
80.19 |
圖24 |
V |
-2000 |
5000 |
2013 |
1908 |
2594 |
10.36 |
9.753 |
13.65 |
44.55 |
42.49 |
57.69 |
占空比3>1>2 |
V |
-2000 |
30000 |
2013 |
191 |
4310 |
10.37 |
1.062 |
23.14 |
44.55 |
4.167 |
95.83 |
圖25 |
VI |
2000 |
3000 |
2471 |
2029 |
2440 |
13.00 |
10.43 |
12.79 |
54.81 |
45.05 |
54.17 |
占空比1>3>2 |
VI |
20000 |
3000 |
3542 |
959 |
1370 |
18.94 |
5.201 |
7.017 |
78.59 |
21.41 |
30.45 |
Tu 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
hTimePhx=4500X占空比。
圖21
圖22
圖23
圖24
圖25
圖26
這樣理論分析就和實際的計算統一了,扇區也對上了。總結如下所示
4.通過以上3個部分,完成了Vα到Vβ的每個轉換過程的分析,通過實戰了解每個過程的變化。存在問題,歡迎大家指正
、