历史上的今天
返回首页

历史上的今天

今天是:2024年08月27日(星期二)

正在发生

2021年08月27日 | 飞思卡尔XS128系列(二) PWM模块

2021-08-27 来源:eefocus

为有别于其他讲解PWM模块的文章,本文不打算拿出大篇幅对PWM模块各个寄存器进行详细讲解,因为那些东西网上、书店到处都是。如果英语好的话,可以参考datasheet,762页的PDF文档,可惜了我那可怜的英文水平……


本文将结合着实际智能小车的控制来写点东西,多写点控制策略上的东西。


如在寄存器方面有何疑问,都可以留言,我都尽力解答。


首先我电磁车上关于PWM的代码:

//PWM.C


void Steering_PWM_Init(void)

 {

    PWMCTL_CON67 = 1; //PWM通道67级联,B或SB作为时钟源

    PWME_PWME7 = 0;

    PWMPRCLK_PCKB = 0x3; //预分频 B 8分频 10MHz

    PWMSCLB = 0x01;   //SB_CLK = B_CLK / (2*1) == 5MHz

    PWMPOL_PPOL7 = 1; //起始高电平

     PWMCLK_PCLK7 = 1; //PWM模块时钟选择SB

    PWMCNT6 = 0x00; //PWMCNTx:通道计数寄存器

     PWMCNT7 = 0x00;

    PWMPER67 = 50000; // 周期==(1/5M)*(50000)=10ms; 

    

    PWMCAE_CAE7 = 0;  //左对齐 

 }


void Motor_PWM_Init(void)

{


    PWMCTL_CON01 = 1;   //PWM通道01,45级联,A或SA作为时钟源

    PWMCTL_CON45 = 1;

    

    PWMPRCLK_PCKA = 0x2; //预分频 A 4分频 20MHz

    PWMSCLA = 0x01;  //SB_CLK = B_CLK / (2*1) == 10MHz

    PWMPOL_PPOL1 = 1;

    PWMPOL_PPOL5 = 1;

    PWMCLK_PCLK1 = 1;

    PWMCLK_PCLK5 = 1;

    PWMCNT0 = 0x00;

    PWMCNT1 = 0x00;

    PWMCNT4 = 0x00;

    PWMCNT5 = 0x00;

    PWMPER01 = 10000; // 1ms ;1KHz 

    PWMPER45 = 10000; // 1ms :1KHz

    

    PWMCAE_CAE1 = 0;

    PWMCAE_CAE5 = 0;  

}


//控制舵机

void Set_PWM67(uint16 duty, uint16 period)

{

    if(duty <= period)

    {

        PWMPER67 = period;

        PWMDTY67 = duty;    

    }

   

    

}


//控制电机

void Set_PWM01(uint16 duty, uint16 period)

{

    if(duty <= period)

    {

        PWMPER01 = period;

        PWMDTY01 = duty;    

    }

     

}


void Set_PWM45(uint16 duty, uint16 period)

{

    if(duty <= period)

    {

        PWMPER45 = period;

        PWMDTY45 = duty;    

    }

     

}



//PWM.h


/******************************************************************************

*           PWM模块

*******************************************************************************/



void Steering_PWM_Init(void);


void Motor_PWM_Init(void);


void Set_PWM01(uint16 duty, uint16 period);


void Set_PWM67(uint16 duty, uint16 period);


void Set_PWM45(uint16 duty, uint16 period);


#define Start_PWM01()   {PWME_PWME1 = 1;}

#define Stop_PWM01()    {PWME_PWME1 = 0;}


#define Start_PWM67()   {PWME_PWME7 = 1;}

#define Stop_PWM67()    {PWME_PWME7 = 0;}


#define Start_PWM45()   {PWME_PWME5 = 1;}

#define Stop_PWM45()    {PWME_PWME5 = 0;}


首先,上述代码默认PWM通道是关闭的,所以在使用时需要先用定义的宏去打开PWM模块。


舵机部分:


PWM控制的无非就是舵机和电机。咱们先谈谈舵机,先使用宏Start_PWM67();打开67通道级联的PWM模块,然后就可以对舵机的转角进行实际操作了。


转角的控制一般有查表的开环控制和PD的闭环控制,查表就是先根据位置量列出一个数组分别对应着各位置量时的转角参数。


如:


左右极限值和中心值为:2120/5380/3750

const uint16 steer_arr[253] = {

        2120, 2132, 2145, 2158, 2171, 2184, 2197, 2210,

        2223, 2236, 2249, 2262, 2275, 2288, 2301, 2314,

        2326, 2339, 2352, 2365, 2378, 2391, 2404, 2417,

        2430, 2443, 2456, 2469, 2482, 2495, 2508, 2521,

        2533, 2546, 2559, 2572, 2585, 2598, 2611, 2624,

        2637, 2650, 2663, 2676, 2689, 2702, 2715, 2728,

        2740, 2753, 2766, 2779, 2792, 2805, 2818, 2831,

        2844, 2857, 2870, 2883, 2896, 2909, 2922, 2935,

        2947, 2960, 2973, 2986, 2999, 3012, 3025, 3038,

        3051, 3064, 3077, 3090, 3103, 3116, 3129, 3141,

        3154, 3167, 3180, 3193, 3206, 3219, 3232, 3245,

        3258, 3271, 3284, 3297, 3310, 3323, 3336, 3348,

        3361, 3374, 3387, 3400, 3413, 3426, 3439, 3452,

        3465, 3478, 3491, 3504, 3517, 3530, 3543, 3555,

        3568, 3581, 3594, 3607, 3620, 3633, 3646, 3659,

        3672, 3685, 3698, 3711, 3724, 3737, 3750, 3762,

        3775, 3788, 3801, 3814, 3827, 3840, 3853, 3866,

        3879, 3892, 3905, 3918, 3931, 3944, 3956, 3969,

        3982, 3995, 4008, 4021, 4034, 4047, 4060, 4073,

        4086, 4099, 4112, 4125, 4138, 4151, 4163, 4176,

        4189, 4202, 4215, 4228, 4241, 4254, 4267, 4280,

        4293, 4306, 4319, 4332, 4345, 4358, 4370, 4383,

        4396, 4409, 4422, 4435, 4448, 4461, 4474, 4487,

        4500, 4513, 4526, 4539, 4552, 4565, 4577, 4590,

        4603, 4616, 4629, 4642, 4655, 4668, 4681, 4694,

        4707, 4720, 4733, 4746, 4759, 4771, 4784, 4797,

        4810, 4823, 4836, 4849, 4862, 4875, 4888, 4901,

        4914, 4927, 4940, 4953, 4966, 4978, 4991, 5004,

        5017, 5030, 5043, 5056, 5069, 5082, 5095, 5108,

        5121, 5134, 5147, 5160, 5173, 5185, 5198, 5211,

        5224, 5237, 5250, 5263, 5276, 5289, 5302, 5315,

        5328, 5341, 5354, 5367, 5380

};


这是我电磁车的,一开始我也是用的开环查表的方式,可能有人要说了,怎么这么多,这要手工排不排到眼花啊?其实这是因为传感器是模拟量,一般没这么多啊,好吧,如果各位和我一样懒,其实咱们可以另外写一个程序帮我们在建表。


如:

#include

#include


#define min 2120 

#define max 5380

#define count 253


using namespace std;


int main(int argc, char *argv[])

{

    int i = 0;

    cout << "const uint16 steering_arr[count] = {";

    

    for(i = 0;i <= count - 1;i++)

    {

        if(i) cout << ", ";

        if(!(i%8)) cout << endl << "/t";

        cout << min + (max - min) * i / (count - 1);

    }

    cout<<",/n";

    cout << endl << "};" << endl;

    return 0;

}


这下简单了吧!呵呵,谁叫咱会偷懒呢,还有一点要注意的是因为这里位置量比较多,所以整个列表都是均匀排布的,当位置量较少时,最好是中间密,两边疏,这样有利于智能车的直道的稳定性。

或是如下PD控制:

#define KP_steering_ 8

#define KD_steering_ 3


#define KP_steering 16

#define KD_steering 6


uint16 temp;

sint16 error;

   

pre_pos_ = pos_;

error = pos_ - pre_pos_;


   if(pos_ <= 30 && pos_ >= -30)

   {    

        temp = Steer_Angle_Center + KP_steering_  * ~pos_ - KD_steering_  * error;

        

        if(temp < 2120)

        {

            Set_PWM67(2120, 50000);

            test_steering = 2120; 

        }

        else if(temp > 5380)

        {

            Set_PWM67(5300, 50000);

            test_steering = 5380; 

        }

        else

        {

            Set_PWM67(temp, 50000);

            test_steering = temp;   

        }

        

   }

   else if(pos_ > 30 || pos_ < -30)

   {

        temp = Steer_Angle_Center + KP_steering * ~pos_ - KD_steering * error;

        

        if(temp < 2120)

        {

            Set_PWM67(2120, 50000);

            test_steering = 2120; 

        }

        else if(temp > 5380)

        {

            Set_PWM67(5380, 50000);

            test_steering = 5380; 

        }

        else

        {

            Set_PWM67(temp, 50000);

            test_steering = temp;   

        }

   }

   else

   {

        _asm(nop);

   }


电机部分:


谈到电机,必然先谈电机驱动,前几届的队伍多半是用33886作为智能车的电机驱动芯片,但我个人认为33886驱动能力有限,且发热量过半,还因为飞思卡尔比赛的原因使该芯片一篇难求,水涨船高,蛮贵的,其实不如使用4个功率MOS管搭建H桥电路来用于电机驱动,具体做法以及如何搭线(如何搭线关系到是否可以反转制动)不打算在这里详说,有时间专门写篇文章讨论这个。


言归正传,还是谈电机控制,电机控制无非是一开始就给个速度让它跑,


如:

//假设电机驱动,一路用PWM,另一路用IO口置低电平

Start_PWM01();

Set_PWM01(5000,10000);


这种开环控制因为电池电压以及实际路况等原因,必然不是最好的。


PID控制的引入可以很好的解决这个问题,我采用的是PID与BANG-BANG控制相结合的方法,由PID是控制精度,BANG-BANG是控制力度,达到了比较好的效果。

这里简单讲讲BANG-BANG控制,对调速范围宽、静态误差小和动态响应快的随动系统来说,单闭环控制是不能满足要求的,所以随动系统采用电流环、速度环和位置环来完成控制。在随动系统控制中,PID控制具有结构简单且在对象模型不确知的情况下也可达到有效控制的特点,但对模型参数变化及干扰的适应能力较差。BANG-BANG控制在系统偏差大,可加大系统的控制力度,提高系统的快速性,因此,BANG-BANG控制是随动系统中不可缺少的控制方式。说明白点就是即时间最优控制的各个分量u(t)都是时间t的分段常值函数,并在开关时间上由一个恒值到另一个恒值的跳变。而映射到智能车上所谓一个恒值到另一个恒值就是速度的最小值到最大值。

推荐阅读

史海拾趣

德崧电子(D-SWITCH)公司的发展小趣事

作为一家有社会责任感的企业,德崧电子始终关注环保和可持续发展。公司在生产过程中积极采用环保材料和工艺,减少对环境的影响。同时,公司还积极参与公益事业,为社会做出贡献。例如,在疫情期间,德崧电子捐赠了一批医疗设备和物资给当地的医疗机构,为抗击疫情做出了积极贡献。这种勇于担当社会责任的精神不仅赢得了社会的赞誉,也为公司树立了良好的企业形象。

EVER-WAY公司的发展小趣事

随着公司规模的扩大和产品质量的提升,EVER-WAY公司开始积极拓展国内外市场。公司制定了详细的市场拓展计划,通过参加国际展会、开展国际贸易合作等方式,逐步打开了国际市场的大门。同时,公司还加强了与国内客户的合作,通过提供定制化服务、优化供应链管理等方式,赢得了客户的信任和支持。这些市场拓展的跨越不仅为公司带来了更多的商业机会,也进一步提升了公司的品牌价值和市场地位。

Eureka Microelectronics Inc公司的发展小趣事

Eureka一直重视研发实力的提升和技术创新。公司拥有一支专业的研发团队,致力于新技术的研发和应用。近年来,Eureka在人工智能、物联网等领域取得了多项技术突破,推出了一系列具有竞争力的新产品。这些技术的突破和应用,不仅提升了Eureka的产品性能和质量,也推动了公司在行业内的领先地位。

广东华裕(GDHY)公司的发展小趣事

随着Eureka产品线的不断拓展,公司开始积极拓展海外市场。通过与国际知名电子制造商的合作,Eureka的产品逐渐打入国际市场。同时,公司也积极参与国际展会和技术交流活动,提升了品牌知名度和影响力。这些努力不仅帮助Eureka扩大了市场份额,也促进了公司与国际同行的交流与合作。

天二科技(EVER OHMS)公司的发展小趣事

面对不断变化的市场需求和技术挑战,天二科技始终坚持持续创新和客户至上的经营理念。公司与客户保持紧密合作,深入了解客户的需求和反馈,不断推出符合市场需求的新产品和解决方案。同时,天二科技还注重培养员工的创新意识和能力,鼓励员工积极参与技术创新和研发工作。这种持续创新和客户至上的经营理念使得天二科技在电子行业中始终保持领先地位。

DESCO公司的发展小趣事

作为一家有社会责任感的企业,DESCO公司始终关注环境保护和可持续发展。公司采用环保材料和生产工艺,减少生产过程中的污染排放。同时,DESCO还积极参与社会公益活动,为当地社区和弱势群体提供帮助和支持。这些举措赢得了社会各界的广泛赞誉和认可。

问答坊 | AI 解惑

关于音频驱动 求问

音频配置文件有alsa.conf 和 asound.conf  看了alsa.conf,里面有 @hooks [         {                 func load               ...…

查看全部问答>

CE5.0下串口丢失字符现象

我用串口2自收发,串口先发送54个字符,然后在接收,并且会比较发送是否与接收的字符相同。用PING 命令不停地发送40960大小的包,打开5个以上的命令行,执行ping命令,同时从网上下载文件,或者renew一下重新获取IP地址(IP为动态分配)串口会出现 ...…

查看全部问答>

MMC/SD/CE-ATA区别

我需要做SD卡升级系统这功能,很多地方不清楚.MMC/SD/CE-ATA,在驱动这个层次上的区别是什么??…

查看全部问答>

嵌入式待遇并不高,为什么大家还要去学他呢?

据我所知,还不如java开发管理软件工资高。…

查看全部问答>

求助ccs

附件 Image00000.bmp (447.12 KB) 2008-2-25 12:30 附件 ...…

查看全部问答>

dsp课件讲义

这是我们上课用的课件,比较好。所以上传与大家分享…

查看全部问答>

RTP/RTCP/RTSP协议初探 [转载]

RTP/RTCP/RTSP协议初探 [转载]一.产生的背景随着互连网的发展,人们已经不满足于传统的HTTP,FTP和电子邮件等文本信息和服务,而对内容丰富多彩的多媒体信息,服务以及多媒体通信方式提出了需求,包括声音,图象,图形,视频信息等等,而这些不 ...…

查看全部问答>

華為公司電路板(PCB)設計規範

華為公司電路板(PCB)設計規範…

查看全部问答>