上次是使用DMA与ADC采样相电流,后面经过验证,开环让电机转动可以提给一个固定的相电流。
iα和iβ手动给一个固定值,经过Clarke(结合基尔霍夫定律)变换,再经过Park变换、反Park变换,最后将输出的电压给到SVPWM模块。即实际控制中需要获取到电流,再反Park前电流一般会经过PI控制器。
开环控制配置的几个部分如下:
1、3路PWM波控制
我的流程是定时器1直接配置的3路PWM,注意要给驱动配置死区,这块的时间配置之后可以搜集一些资料。定时器1的技术模式采用TIM_CounterMode_CenterAligned2;定时器频率为每秒10K个数,MOS的开关频率是16k。
代码如下:
void Tim1_PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM1_Gpio();
///
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2; // Ôö¼ÆÊýģʽ
// MOS开关频率168000/ 10500 = 16k 168000/ 16800 = 10k
TIM_TimeBaseStructure.TIM_Period = 168000 / PWM_FREQ - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 5000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High ;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 0x6A;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
TIM_ITConfig(TIM1,TIM_IT_Update ,ENABLE);
}
2、三相电机芯片DRV8313
这个了解的不多,直接贴现成的代码吧。
void DRV8313_GPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitStructure.GPIO_Pin = SLEEP_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(SLEEP_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(SLEEP_GPIO_PORT, SLEEP_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = RESET_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(RESET_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(RESET_GPIO_PORT, RESET_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = FAULT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(FAULT_GPIO_PORT, &GPIO_InitStructure);
}
3、电角度的设置
作为重要的输入参数,本次开环测试中手动给定累加。
While(1){
Key_Scanning();
Anglee += 8;
if(Anglee >= 4000){
Anglee = 0;
}
printf("%d \n", Anglee);
switch (MYSTATE) {
case RUN: {
FOC_Model();
break;
}
case STOP:
break;
default:
break;
}
Delay(10);
}
4、Park、Clarke变换以及SVPWM
①手动给定采样电流:
I_AB.I1=12; //
I_AB.I2=74;
②Clarke变换
I_alfb.I1 = I_AB.I1;
I_alfb.I2= I_AB.I1*0.5773503+I_AB.I2*1.1547005;
上次笔记后面有给出直接的结论。
③查表进行正余弦计算
Cosine = Trig_Functions(Anglee);
④Park变换
I_dq.I1 = ((I_alfb.I1 * Cosine.hCos) + (I_alfb.I2 * Cosine.hSin)); //Id
I_dq.I2 = ((I_alfb.I2 * Cosine.hCos) - (I_alfb.I1 * Cosine.hSin)); //Iq
⑤手动给定参考电压后反Park变换
Volt_dq.V2=0.6;
Volt_dq.V1=0;
Volt_alfb.V1 = (Volt_dq.V1 * Cosine.hCos - Volt_dq.V2 * Cosine.hSin);//
Volt_alfb.V2 = (Volt_dq.V1 * Cosine.hSin + Volt_dq.V2 * Cosine.hCos);//
⑥SVPWM模块
SVPWM_algorithm(Volt_alfb);
void SVPWM_algorithm(Volt_Components Volt_alfb)
{
u8 bSector=0;
s32 T1,T2,wX,wY,wZ;
u32 tempT;
u16 TA,TB,TC;
Time_Components TIME_CCR;
bSector=0;
if(Volt_alfb.V2>0)bSector=bSector+1;
if((Volt_alfb.V1*1.7320508-Volt_alfb.V2)>0)bSector=bSector+2;
if((Volt_alfb.V1*1.7320508+Volt_alfb.V2)<0)bSector=bSector+4;
wX = TIME_PERIOD*(Volt_alfb.V2*1.7320508)/Volt_DC;
wY = TIME_PERIOD*(Volt_alfb.V1*1.5+Volt_alfb.V2*0.8660254)/Volt_DC;
wZ = TIME_PERIOD*(Volt_alfb.V2*0.8660254-Volt_alfb.V1*1.5)/Volt_DC;
switch(bSector){
case SECTOR_1:
T1= wZ;
T2= wY;
break;
case SECTOR_2:
T1= wY;
T2= -wX;
break;
case SECTOR_3:
T1= -wZ;
T2= wX;
break;
case SECTOR_4:
T1= -wX;
T2= wZ;
break;
case SECTOR_5:
T1= wX;
T2= -wY;
break;
case SECTOR_6:
T1= -wY;
T2= -wZ;
break;
default: ///0
break;
}
if(T1<0)
T1=0;
if(T2<0)
T2=0;
tempT=T1+T2;
if(tempT>TIME_PERIOD)
{
T1=T1*TIME_PERIOD/tempT;
T2=T2*TIME_PERIOD/tempT;
}
TA=(TIME_PERIOD-T1-T2)/4;
TB=TA+T1/2;//
TC=TB+T2/2;//
switch(bSector)
{
case SECTOR_1:
TIME_CCR.TIME1=TB;
TIME_CCR.TIME2=TA;
TIME_CCR.TIME3=TC;
break;
case SECTOR_2:
TIME_CCR.TIME1=TA;
TIME_CCR.TIME2=TC;
TIME_CCR.TIME3=TB;
break;
case SECTOR_3:
TIME_CCR.TIME1=TA;
TIME_CCR.TIME2=TB;
TIME_CCR.TIME3=TC;
break;
case SECTOR_4:
TIME_CCR.TIME1=TC;
TIME_CCR.TIME2=TB;
TIME_CCR.TIME3=TA;
break;
case SECTOR_5:
TIME_CCR.TIME1=TC;
TIME_CCR.TIME2=TA;
TIME_CCR.TIME3=TB;
break;
case SECTOR_6:
TIME_CCR.TIME1=TB;
TIME_CCR.TIME2=TC;
TIME_CCR.TIME3=TA;
break;
default://0
TIME_CCR.TIME1=TIME_PERIOD/4;
TIME_CCR.TIME2=TIME_PERIOD/4;
TIME_CCR.TIME3=TIME_PERIOD/4;
break;
}
if(TIME_CCR.TIME1<0) //Ô½½ç´¦Àí
TIM1->CCR1=0;
else if(TIME_CCR.TIME1>PWM_PERIOD)//Ô½½ç´¦Àí
TIM1->CCR1=PWM_PERIOD;
else
TIM1->CCR1 = TIME_CCR.TIME1;
if(TIME_CCR.TIME2<0)
TIM1->CCR2=0;
else if(TIME_CCR.TIME2>PWM_PERIOD)
TIM1->CCR2=PWM_PERIOD;
else
TIM1->CCR2= TIME_CCR.TIME2;
if(TIME_CCR.TIME3<0)
TIM1->CCR3=0;
else if(TIME_CCR.TIME3>PWM_PERIOD)
TIM1->CCR3=PWM_PERIOD;
else
TIM1->CCR3= TIME_CCR.TIME3;
}
这块理解可以直接看《现代永磁同步电机控制原理及MATLAAB仿真》(袁雷),书中直接给出计算流程,一些其他的流程可以看《SVPWM的原理及法则推导和控制算法详解》。
效果如下:
欢迎关注:
如需完整代码,赞赏1元后公众号留言自动发送。附带书籍和其他资料。