飞思卡尔XS128系列(二) PWM模块

摘要:
//脉宽调制。CvoidSteeringing_ PWM_ Init(void){PWMCTL_CON67=1;B或SB作为时钟源PWME_PWME7=0;PWMCAE_CAE7=1;//左对齐}voidMotor_ PWM_ Init(void){PWMCL_CON01=1;PWMCLK_PCLK1=1;

      为有别于其他讲解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 <cstdlib>  
#include <iostream>

#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的分段常值函数,并在开关时间上由一个恒值到另一个恒值的跳变。而映射到智能车上所谓一个恒值到另一个恒值就是速度的最小值到最大值。

       具体依旧打算令开篇详讲。

------------------------------------------------------------------------------------------

        不写了,还没吃饭了,饿哦~~

        从昨天开始打算好好的写博客,到今天一大早爬起来码字,真的对自己无语了,一定要坚持。写下自己在学习中的所思所想,相信这也是对自己的一种提高。

转载我博客文章郑重声明:技术性网站著名原创作者即可转载,商业性网站必须经过我的同意才能转载,否则追究责任——

pang123hui的博客:

博客园http://www.cnblogs.com/pang123hui/

CSDNhttp://blog.csdn.net/pang123hui/

     

免责声明:文章转载自《飞思卡尔XS128系列(二) PWM模块》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇交叉编译python2.7.7Windows server 2008启动remote dosktop services服务报错1079下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WebService基本使用

不使用任何框架,纯粹使用JDK开发一个服务端与客户端 服务端 package org.zln.ws.server;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.zln.ws.server.domain.User;import javax.jws.WebService;/*...

小程序换行符检测换行

先将换行符替换成自定义连接字符 var goods_detail = "" if(res.data.info.goods_info.goods_detail){ goods_detail = res.data.info.goods_info.goods_detail; var str=goods_detail.replace(/ /g,"|-&")...

从深处去掌握数据校验@Valid的作用(级联校验)

每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 【小家Java】深入了解数据校验:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例【小家Spring】让Controller支持对平铺参数执行数据校验(默认Spring MVC使用@V...

实用的css3小实例---1、卡片效果

实用的css3小实例---1、卡片效果 一、总结 一句话总结: 卡片效果主要是使用box-shadow属性: box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 1、box-shadow属性的语法及实例? 语法:box-shadow: h-shadow...

实践(1):简单的文件上传

文件上传 html、修改 <div class="template-upload"> <span>模版样式:</span> <button type="button" id="btn">选择模板</button> <input type="file" accept=".pptx,.ppt...

评论功能的简单实现

最近在写一个问答功能,类似于评论,几番找资料才有点感觉(主要是太菜了),为了加深印象就单独抽出来记下笔记,然后这篇写完就开始SpringBoot的复习了 1. 说明 网上看到有三种类型的评论,按照笔者的理解记下了过程(可能理解错了,望大神指出),所以列出的是笔者的理解,下面以模拟博客评论的场景来说明,(这些类型是笔者形容的,并没有这个词),总觉得很慌理解...