查看: 2459|回复: 1

[求助] QTIMER PWM

[复制链接]
  • TA的每日心情

    2021-3-26 23:31
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    2

    主题

    4

    帖子

    0

    新手上路

    Rank: 1

    积分
    37
    最后登录
    2024-5-21
    发表于 2021-7-19 15:15:35 | 显示全部楼层 |阅读模式
    本帖最后由 wxfreedom 于 2021-7-19 15:19 编辑

    最近在使用I.MX 1052 的QTIMER 输出PWM进行步进电机的S型控制曲线功能实现。目前功能已基本实现, 但是在波形输出上却出现了问题。
    正常的波形如下:
    STK截图20210719150419.png

    可以看到PWM输出在开始后是逐渐增大的。这里使用了QTIMER的输出比较中断,在中断中对下一次的pwm频率进行变更。
    第一个问题,在rtthread4.0.3系统下,当速度增大时,比如说加速至3r/s, 会出现偶尔中断有几个ms是没有pwm输出的,如下
    STK截图20210719150803.png
    有时会有好几段这样的无输出的波形,导致电机丢步。

    第二个问题:有时出现的波形不为方波,如下,导致步数不准确。
    STK截图20210719151104.png

    对比在裸机下实现的该功能,裸机目前是正常的,并未出现上诉问题。怀疑是系统调度等引起的问题,有大神可以指导下么

    代码如下
    1. static rt_err_t motor_S_curve_set(struct rt_device *device, motor_para_t *para, acc_config_t *acc_cfg)
    2. {
    3.         struct pwm_motor_cfg *pwm_cfg = (struct pwm_motor_cfg *)device->user_data;
    4.         CalcSpeed(pwm_cfg,acc_cfg);//根据参数生成加减速频率表
    5.         pwm_cfg->cal_para.AverageStep = para->pulse - 2 * pwm_cfg->cal_para.AccelTotalStep;
    6.         if(pwm_cfg->cal_para.AverageStep <= 0)         pwm_cfg->cal_para.AverageStep = 0;
    7.         stepper_start_run(pwm_cfg);//启动第一个pwm输出,开中断
    8.         rt_sem_take(&pwm_cfg->sem,RT_WAITING_FOREVER);
    9.         rt_free(pwm_cfg->cal_para.Form);
    10.         return RT_EOK;
    11. }
    复制代码
    1. void speed_decision(void *args)
    2. {
    3.         float temp_p = 0;
    4.         int step;
    5.         struct pwm_motor_cfg *cfg = (struct pwm_motor_cfg *)args;        
    6.         
    7.         if(cfg->status.status == ACCEL)
    8.         {
    9.                 cfg->status.pos++;
    10.                 if(cfg->status.pos  < cfg->cal_para.AccelTotalStep )
    11.                 {
    12.                         temp_p = cfg->cal_para.Form[cfg->status.pos];
    13. //                        if(temp_p < MIN_SPEED)
    14. //                                temp_p = MIN_SPEED;
    15.                         QTMR_SetupPwm(cfg->base,cfg->channel,temp_p,50,false,QTMR_SOURCE_CLOCK/8);
    16.                 }
    17.                 else        
    18.                 {
    19.                         if(cfg->cal_para.AverageStep > 0)                cfg->status.status = AVESPEED;        
    20.                         else if(cfg->cal_para.AverageStep == 0)        cfg->status.status = DECEL;
    21.                         else //到达最大速度后不减速,给信号量
    22.                         {
    23.                                 rt_sem_release(&cfg->sem);
    24.                         }
    25.                 }        
    26.         }
    27.         else if(cfg->status.status == AVESPEED)
    28.         {
    29.                 cfg->status.pos++;
    30.                 if(cfg->status.pos  < cfg->cal_para.AccelTotalStep + cfg->cal_para.AverageStep) ;
    31.                 else        cfg->status.status = DECEL;
    32.         }
    33.         else
    34.         {
    35.                 cfg->status.pos++;
    36.                 step = cfg->status.pos - cfg->cal_para.AccelTotalStep - cfg->cal_para.AverageStep;
    37.                 if(step < cfg->cal_para.AccelTotalStep)
    38.                 {
    39.                         temp_p = cfg->cal_para.Form[cfg->cal_para.AccelTotalStep - step];
    40.                         if(temp_p < MIN_SPEED)
    41.                                 temp_p = MIN_SPEED;
    42.                         QTMR_SetupPwm(cfg->base,cfg->channel,temp_p,50,false,QTMR_SOURCE_CLOCK/8);
    43.                 }
    44.                 else        
    45.                 {
    46.                         cfg->status.status = STOP;
    47.                         QTMR_StopTimer(cfg->base,cfg->channel);
    48.                         rt_sem_release(&cfg->sem);
    49.                 }
    50.         }
    51. }
    复制代码
    1. static void qtimer_isr(TMR_Type *base, int start)
    2. {
    3. //        for(int i=0;i<4;i++)
    4. //        {
    5. //                if(QTMR_GetStatus(base, (qtmr_channel_selection_t)i) != 0)
    6. //                {
    7. //                        QTMR_ClearStatusFlags(base, (qtmr_channel_selection_t)i, kQTMR_Compare2Flag);
    8. //                        if(hdr_tab[start+i].hdr != RT_NULL)
    9. //                        {
    10. //                                hdr_tab[start+i].hdr(hdr_tab[start+i].args);
    11. //                        }
    12. //                }
    13. //        }
    14.         
    15.         QTMR_ClearStatusFlags(base, kQTMR_Channel_3, kQTMR_Compare2Flag);
    16.         hdr_tab[11].hdr(hdr_tab[11].args);
    17. }

    18. void TMR3_IRQHandler(void)
    19. {
    20. //        rt_interrupt_enter();
    21.         qtimer_isr(TMR3,8);
    22. //    rt_interrupt_leave();
    23.         __DSB();
    24. }
    复制代码


    这里的加减速算法是采用的野火的电机文档下的S型建加速模型。

    求助啊
    回复

    使用道具 举报

    该用户从未签到

    712

    主题

    6371

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    24866
    最后登录
    2025-7-18
    发表于 2021-7-20 11:18:16 | 显示全部楼层
    请问有找出问题复现的规律了吗?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-19 10:00 , Processed in 0.087409 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表