SVPWM-实战

接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为单片机的输出信号,CH3MOS输出信号,可以看到,时序上有明显的滞后

滞后的主要原因在于MOS驱动电路的延时,驱动芯片采购:IRS2005驱动芯片

   

有驱动芯片可以得到,延时时间在160ns-220ns(驱动延时)左右。实际的延时误差值在235ns(包含两部分,驱动延时和mos开启延时)

   

通道2PWM输出,通道3位驱动芯片输出端,延时位186ns。

   

   

   

   

   

   

CH1,CH2 MCU输出波形,CH3CH4位驱动芯片输出波形。

   

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参数会有差异。

   

以上讲了这么多,主要是梳理了一下PWMMCU的引脚输出到控制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α,(未转换)的值模值不可超过32767,超出范围的电压矢量不可以生成。当控制矢量在空间旋转 360°后,逆变器就能输出一个周期的正弦波电压。

   

扇区

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β的每个转换过程的分析,通过实战了解每个过程的变化。存在问题,欢迎大家指正

   

 

   

 

 

 

   

 

posted @ 2020-11-21 23:34  Aliank  阅读(2137)  评论(1编辑  收藏  举报