在线时间4 小时
UID3709274
注册时间2021-3-10
NXP金币0
TA的每日心情 | 衰 2021-3-26 23:31 |
---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
新手上路

- 积分
- 37
- 最后登录
- 2024-5-21
|
本帖最后由 wxfreedom 于 2021-7-19 15:19 编辑
最近在使用I.MX 1052 的QTIMER 输出PWM进行步进电机的S型控制曲线功能实现。目前功能已基本实现, 但是在波形输出上却出现了问题。
正常的波形如下:
可以看到PWM输出在开始后是逐渐增大的。这里使用了QTIMER的输出比较中断,在中断中对下一次的pwm频率进行变更。
第一个问题,在rtthread4.0.3系统下,当速度增大时,比如说加速至3r/s, 会出现偶尔中断有几个ms是没有pwm输出的,如下
有时会有好几段这样的无输出的波形,导致电机丢步。
第二个问题:有时出现的波形不为方波,如下,导致步数不准确。
对比在裸机下实现的该功能,裸机目前是正常的,并未出现上诉问题。怀疑是系统调度等引起的问题,有大神可以指导下么
代码如下
- static rt_err_t motor_S_curve_set(struct rt_device *device, motor_para_t *para, acc_config_t *acc_cfg)
- {
- struct pwm_motor_cfg *pwm_cfg = (struct pwm_motor_cfg *)device->user_data;
- CalcSpeed(pwm_cfg,acc_cfg);//根据参数生成加减速频率表
- pwm_cfg->cal_para.AverageStep = para->pulse - 2 * pwm_cfg->cal_para.AccelTotalStep;
- if(pwm_cfg->cal_para.AverageStep <= 0) pwm_cfg->cal_para.AverageStep = 0;
- stepper_start_run(pwm_cfg);//启动第一个pwm输出,开中断
- rt_sem_take(&pwm_cfg->sem,RT_WAITING_FOREVER);
- rt_free(pwm_cfg->cal_para.Form);
- return RT_EOK;
- }
复制代码- void speed_decision(void *args)
- {
- float temp_p = 0;
- int step;
- struct pwm_motor_cfg *cfg = (struct pwm_motor_cfg *)args;
-
- if(cfg->status.status == ACCEL)
- {
- cfg->status.pos++;
- if(cfg->status.pos < cfg->cal_para.AccelTotalStep )
- {
- temp_p = cfg->cal_para.Form[cfg->status.pos];
- // if(temp_p < MIN_SPEED)
- // temp_p = MIN_SPEED;
- QTMR_SetupPwm(cfg->base,cfg->channel,temp_p,50,false,QTMR_SOURCE_CLOCK/8);
- }
- else
- {
- if(cfg->cal_para.AverageStep > 0) cfg->status.status = AVESPEED;
- else if(cfg->cal_para.AverageStep == 0) cfg->status.status = DECEL;
- else //到达最大速度后不减速,给信号量
- {
- rt_sem_release(&cfg->sem);
- }
- }
- }
- else if(cfg->status.status == AVESPEED)
- {
- cfg->status.pos++;
- if(cfg->status.pos < cfg->cal_para.AccelTotalStep + cfg->cal_para.AverageStep) ;
- else cfg->status.status = DECEL;
- }
- else
- {
- cfg->status.pos++;
- step = cfg->status.pos - cfg->cal_para.AccelTotalStep - cfg->cal_para.AverageStep;
- if(step < cfg->cal_para.AccelTotalStep)
- {
- temp_p = cfg->cal_para.Form[cfg->cal_para.AccelTotalStep - step];
- if(temp_p < MIN_SPEED)
- temp_p = MIN_SPEED;
- QTMR_SetupPwm(cfg->base,cfg->channel,temp_p,50,false,QTMR_SOURCE_CLOCK/8);
- }
- else
- {
- cfg->status.status = STOP;
- QTMR_StopTimer(cfg->base,cfg->channel);
- rt_sem_release(&cfg->sem);
- }
- }
- }
复制代码- static void qtimer_isr(TMR_Type *base, int start)
- {
- // for(int i=0;i<4;i++)
- // {
- // if(QTMR_GetStatus(base, (qtmr_channel_selection_t)i) != 0)
- // {
- // QTMR_ClearStatusFlags(base, (qtmr_channel_selection_t)i, kQTMR_Compare2Flag);
- // if(hdr_tab[start+i].hdr != RT_NULL)
- // {
- // hdr_tab[start+i].hdr(hdr_tab[start+i].args);
- // }
- // }
- // }
-
- QTMR_ClearStatusFlags(base, kQTMR_Channel_3, kQTMR_Compare2Flag);
- hdr_tab[11].hdr(hdr_tab[11].args);
- }
- void TMR3_IRQHandler(void)
- {
- // rt_interrupt_enter();
- qtimer_isr(TMR3,8);
- // rt_interrupt_leave();
- __DSB();
- }
复制代码
这里的加减速算法是采用的野火的电机文档下的S型建加速模型。
|
|