2019-07-20 21:41发布
likunxue 发表于 2016-4-16 01:34 如果速度要求不高, 按原子哥说的,用 PWM输出按正弦波方式细分一下,就行了, 保证工作又移稳定又安于, 最多到 ...
正点原子 发表于 2016-4-15 22:54 细分!!
qjw123456 发表于 2016-4-16 12:42 直接用定时器细分么?不用专门的细分驱动器?我现在是用单纯的IO口输出脉冲时序来控制步进电机,用PWM输 ...
likunxue 发表于 2016-4-16 13:13 PWM的宽度就是导通时间, 宽度越大,导通时间就长, 平均电流就大, 用这个关系,计算好正弦波电流对应的 ...
最多设置5个标签!
直接用定时器细分么?不用专门的细分驱动器?我现在是用单纯的IO口输出脉冲时序来控制步进电机,用PWM输出按正弦波方式怎么细分啊,求指教
具体要怎么细分呢?新手不是太懂
PWM的宽度就是导通时间, 宽度越大,导通时间就长, 平均电流就大, 用这个关系,计算好正弦波电流对应的脉宽就行了, 然后直接查表输出
慢慢来吧! 别急, 以下为正弦波输出部份代码, 你可参考一下
/********************************************************************************************
函数名:失量调制参数初始化函数
调 用: SVPWM_int(void)
参 数: 无
********************************************************************************************/
void SVPWM_int(void)
{
const int M = 128; //最大细分128细分
float K, fx = 0.00f;
int i,n;
K = (float)20/255; //线性系数
for(i = 0; i< M; i++)
{
fx = (float)i/M;
SVP.SIN = 4096*(fx + K * sin(6.2831852 * fx));//A相电流表
n = M -i;
fx = (float)n/M;
SVP.SIN[i+M] = 4096*(fx + K * sin(6.2831852 * fx));//B相电流表
// SVP.SIN = sin((3.1415926/256)*i)*4096; //计算正弦表 0 ~ 128 Q12格式
// SVP.SIN[i+128] = cos((3.1415926/256)*i)*4096; //计算正弦表 128 ~ 256
}
SVP.PWMPRD = PWMPTD -1;
SVP.VDC = (296 *811)/10000; //直流则母线电压 (采样值/0.000811)
SVP.VDCinvT = SVP.PWMPRD/SVP.VDC; //存放 PWMPRD/VDC的数据
SVP.VDCmax = (SVP.PWMPRD * 7071)/10000; //合成失量的最大值
SVP.K = 0.02*4096; //制动转矩控制比;Q12
SVP.Counter = 0; //SPWM计数器(微步计数器)
SVP.sector = 0; //当前扇区号
SVP.PMAI = SVP.PWMPRD*0.96; //最大脉冲宽度 PWMPTD 96%
SVP.PMXI = SVP.PWMPRD*0.04; //最小窄脉宽度 PWMPTD 4%
SVP.Uret = 500; //外部电压设定值
//电流环PI参数初始化
SVP.SetPoint = 40; //目标值电流
SVP.SumError = 0 ; //前一次的误差
SVP.P = 204; //比例常数 0.2*1024
SVP.I = 51; //积分常数 0.5*1024
}
/********************************************************************************************
函 数 名: TIM1_IRQHandler: 定时器1中断函数
调 用: 无
参 数: 无
返 回 值: 无
********************************************************************************************/
void TIM1_UP_IRQHandler(void)
{
if(BIT_ADM(TIM1->SR,0)== 1)//溢出中断
{
int T1,T2,SA,SB;
u8 K = (u8)SVP.Counter; //取微步计数器低8位的值 (加减这个值电机转动, )
BIT_ADM(TIM1->SR,0) = 0; //清除定时器1中断标志位
if(SVP.Uret > SVP.VDCmax)SVP.Uret = SVP.VDCmax; //最大失量电压限制
SVP.Uret = 500;
//K = 224;
if(SVP.Uret < 100) SVP.Uret = 100;
SVP.ua = ((s32)SVP.Uret *MY_COS[K])>>12; //得到SVPWM输入的二相正弦电压
SVP.ub = ((s32)SVP.Uret *MY_SIN[K])>>12;
SVP.teta = K;
SVP.sector = 0;
if(SVP.ua > 0)SVP.sector = 1;
if(SVP.ub > 0)SVP.sector += 2; //得到AB相换相数据(扇区号)
switch(SVP.sector)
{
case 3:{//第1扇区(+A,+B ->1 0 1 0)
T1 = SVP.ua;
T2 = SVP.ub;
SA = ((SVP.PWMPRD - T1)*SVP.K)>>12; //计算A相转矩脉宽
SB = ((SVP.PWMPRD - T2)*SVP.K)>>12; //计算B相转矩脉宽
TIM1->CCR2 = SA; //U4 +
TIM1->CCR1 = SA + T1; //U5
TIM1->CCR3 = SB; //U3 +
TIM1->CCR4 = SB + T2; //U2
}break;
case 1:{//第4扇区(+A,-B ->1 0 0 1)
T1 = SVP.ua;
T2 = -SVP.ub;
SA = ((SVP.PWMPRD - T1)*SVP.K)>>12; //计算A相转矩脉宽
SB = ((SVP.PWMPRD - T2)*SVP.K)>>12; //计算B相转矩脉宽
TIM1->CCR2 = SA; //U4 +
TIM1->CCR1 = SA + T1; //U5
TIM1->CCR3 = SB + T2; //U3 -
TIM1->CCR4 = SB; //U2
}break;
case 0:{//第3扇区(-A,-B ->0 1 0 1)
T1 = -SVP.ua;
T2 = -SVP.ub;
SA = ((SVP.PWMPRD - T1)*SVP.K)>>12; //计算A相转矩脉宽
SB = ((SVP.PWMPRD - T2)*SVP.K)>>12; //计算B相转矩脉宽
TIM1->CCR2 = SA + T1; //U4 -
TIM1->CCR1 = SA; //U5
TIM1->CCR3 = SB + T2; //U3 -
TIM1->CCR4 = SB ; //U2
}break;
case 2:{//第2扇区(-A +B ->0 1 1 0)
T1 = -SVP.ua;
T2 = SVP.ub;
SA = ((SVP.PWMPRD - T1)*SVP.K)>>12; //计算A相转矩脉宽
SB = ((SVP.PWMPRD - T2)*SVP.K)>>12; //计算B相转矩脉宽
TIM1->CCR2 = SA + T1; //U4 -
TIM1->CCR1 = SA; //U5
TIM1->CCR3 = SB; //U3 +
TIM1->CCR4 = SB + T2; //U2
}break;
}
}
}
感觉这个程序太难了对我这个新手来说,简直吃不燃啊
一周热门 更多>