智能车制作

标题: 电磁车的PWM控制 [打印本页]

作者: GTR1113    时间: 2012-4-10 20:15
标题: 电磁车的PWM控制
用AD采样陀螺仪和加速度计的值,假如是12位精度,那么采集到的是两个0到4095 之间的值,   通过官网的方案解说也可以知道施加到电机上的电压 U 的值是定义为: U=K_voltage*(K_angle*angle+K_anglespeed*anglespeed), 现在知道了角度和角速度的AD采样值 ,K_voltage,K_angle,K_anglespeed 这三个参数要调试得出,假设也得到了,现在的问题是怎么把 U 转化成驱动电机的占空比啊 ????
作者: 吉他手    时间: 2012-4-10 20:35
请注意,参考设计方案是将最终电机的控制量U限定在(-1,1)之间。因此这个量本身就是输出PWM的占空比。比如,输出量为0.5,那么输出PWM占空比就是电机正向驱动电压PWM的占空比为50%。其它 类似。。。
作者: GTR1113    时间: 2012-4-10 21:58
吉他手 发表于 2012-4-10 20:35
请注意,参考设计方案是将最终电机的控制量U限定在(-1,1)之间。因此这个量本身就是输出PWM的占空比。比如, ...

但是我还有想不明白的。不知道你看没看官网的代码。
//------------------------------------------------------------------------------
//      MOTOR SPEED CONTROL OUTPUT
//
void MotorSpeedOut(void) {
float fLeftVal, fRightVal;

fLeftVal = g_fLeftMotorOut;
fRightVal = g_fRightMotorOut;
if(fLeftVal > 0)    fLeftVal += MOTOR_OUT_DEAD_VAL;
else if(fLeftVal < 0)   fLeftVal -= MOTOR_OUT_DEAD_VAL;

if(fRightVal > 0)   fRightVal += MOTOR_OUT_DEAD_VAL;
else if(fRightVal < 0)  fRightVal -= MOTOR_OUT_DEAD_VAL;
  
if(fLeftVal > MOTOR_OUT_MAX) fLeftVal = MOTOR_OUT_MAX;
if(fLeftVal < MOTOR_OUT_MIN) fLeftVal = MOTOR_OUT_MIN;
if(fRightVal > MOTOR_OUT_MAX) fRightVal = MOTOR_OUT_MAX;
if(fRightVal < MOTOR_OUT_MIN) fRightVal = MOTOR_OUT_MIN
;
   
SetMotorVoltage(fLeftVal, fRightVal);
}

#define MOTOR_OUT_DEAD_VAL    g_Argument.fDeadVoltage     //Unit : Full output
g_Argument.fDeadVoltage   = DEAD_VOLTAGE_DEFAULT;
#define DEAD_VOLTAGE_DEFAULT   0x40

通过上面这3句代码可以知道   MOTOR_OUT_DEAD_VAL=0x40 ;      
也就是    MOTOR_OUT_DEAD_VAL=64 ;

所以上面函数中的:
if(fLeftVal > 0)    fLeftVal += MOTOR_OUT_DEAD_VAL;
else if(fLeftVal < 0)   fLeftVal -= MOTOR_OUT_DEAD_VAL;
表示如果 fLeftVal > 0 那么 fLeftVal += MOTOR_OUT_DEAD_VAL;
表示如果 fLeftVal < 0 那么 fLeftVal - = MOTOR_OUT_DEAD_VAL;

这样一来的结果就是:
如果 fLeftVal > 0 ,  fLeftVal 就是一个大于 MOTOR_OUT_DEAD_VAL 即 64 的数
如果 fLeftVal < 0 ,  fLeftVal 就是一个小于 MOTOR_OUT_DEAD_VAL 即 64 的数

那么函数中的程序段:
if(fLeftVal > MOTOR_OUT_MAX) fLeftVal = MOTOR_OUT_MAX;
if(fLeftVal < MOTOR_OUT_MIN) fLeftVal = MOTOR_OUT_MIN;
if(fRightVal > MOTOR_OUT_MAX) fRightVal = MOTOR_OUT_MAX;
if(fRightVal < MOTOR_OUT_MIN) fRightVal = MOTOR_OUT_MIN
;
的作用是起到限幅值的作用,
而MOTOR_OUT_MAX 和 MOTOR_OUT_MIN 分别是宏定义:
#define MOTOR_OUT_MAX     1.0
#define MOTOR_OUT_MIN     -1.0   
那么上面得到的 fLeftVal (一个大于64的浮点数)就被限幅值的那四句代码给限制到了 MOTOR_OUT_MAX 和 MOTOR_OUT_MIN之间,即1.0 到 -1.0之间,那么1.0到64点多 之间的数就被这么”无情“的处理掉了,这样对么???

作者: 吉他手    时间: 2012-4-10 22:31
GTR1113 发表于 2012-4-10 21:58
但是我还有想不明白的。不知道你看没看官网的代码。
//---------------------------------------------- ...

首先你不要被代码中的表现迷惑了。
#define MOTOR_OUT_DEAD_VAL    g_Argument.fDeadVoltage
这种代码说明电机的死区是由系统存储的参数g_Argument.fDeadVoltage确定的。而g_Argument.fDeadVoltage是通过串口设置的。一般设置成0,或者小于1的一个小数。

所以,你按照这种想法重新去认识参考代码即可。

作者: GTR1113    时间: 2012-4-11 13:30
吉他手 发表于 2012-4-10 22:31
首先你不要被代码中的表现迷惑了。
#define MOTOR_OUT_DEAD_VAL    g_Argument.fDeadVoltage
这种代码说 ...

谢谢指点,我按这个思路再看看
作者: GTR1113    时间: 2012-4-14 00:24
吉他手 发表于 2012-4-10 20:35
请注意,参考设计方案是将最终电机的控制量U限定在(-1,1)之间。因此这个量本身就是输出PWM的占空比。比如, ...

限制在-1到1来表示占空比是怎么实现的啊  ????
好久了都没搞懂啊。下面这个程序我能看懂,PWM的占空比就是 nOut
但是我搞不懂的是:怎么样把检测到的角度和角速度按照公式U=K(K1*angle+K2*anglespeed),化成-1.0到1.0之间啊???   
首先,按照官网参考方案来说,K1应该是(float)180/ (float)(GRAVITY_MAX - GRAVITY_MIN) ,
K2是[attach]22806[/attach]。
K1,K2都出来了,那该怎么确定占空比是多少呢????
//------------------------------------------------------------------------------
void SetMotorVoltage(float fLeftVoltage, float fRightVoltage) {
                                                // Voltage : > 0 : Move forward;
                                                //           < 0 : Move backward
short nPeriod;
int nOut;

nPeriod = (short)getReg(PWM_PWMCM);

//--------------------------------------------------------------------------
if(fLeftVoltage > 1.0)    fLeftVoltage = 1.0;
else if(fLeftVoltage < -1.0)  fLeftVoltage = -1.0;

if(fRightVoltage > 1.0)   fRightVoltage = 1.0;
else if(fRightVoltage < -1.0) fRightVoltage = -1.0;
                                             
//--------------------------------------------------------------------------                                                                                            
if(fLeftVoltage > 0) {
  setReg(PWM_PWMVAL1, 0);
  nOut = (int)(fLeftVoltage * nPeriod);
  setReg(PWM_PWMVAL0, nOut);
} else {
  setReg(PWM_PWMVAL0, 0);
  fLeftVoltage = -fLeftVoltage;
nOut = (int)(fLeftVoltage * nPeriod);
  setReg(PWM_PWMVAL1, nOut);
}                                    
//--------------------------------------------------------------------------
if(fRightVoltage > 0) {
  setReg(PWM_PWMVAL2, 0);
  nOut = (int)(fRightVoltage * nPeriod);
  setReg(PWM_PWMVAL3, nOut);
} else {
  setReg(PWM_PWMVAL3, 0);
  fRightVoltage = -fRightVoltage;
  nOut = (int)(fRightVoltage * nPeriod);
  setReg(PWM_PWMVAL2, nOut);
}
MOTOR_SETLOAD;                              // Reload the PWM value
}                                            


作者: 吉他手    时间: 2012-4-14 08:52
GTR1113 发表于 2012-4-14 00:24
限制在-1到1来表示占空比是怎么实现的啊  ????
好久了都没搞懂啊。下面这个程序我能看懂,PWM的占空 ...

你对于K1,K2(对应于P,D)参数的确定理解是错误的。
给出的公式只是用于计算两个传感器的比例值。而这K1,K2(或者P,D)参数是于控制参数。需要通过实验整定。。
再按这个思路考虑。。。。

作者: GTR1113    时间: 2012-4-14 09:03
吉他手 发表于 2012-4-14 08:52
你对于K1,K2(对应于P,D)参数的确定理解是错误的。
给出的公式只是用于计算两个传感器的比例值。而这K ...

也就是整定P,D参数,使得angle*P+anglespeed*D的结果在-1.0到1.0之间????
作者: freedom213    时间: 2013-1-30 12:13
求解释啊,大神们 ,我也看不懂这儿啊啊啊啊啊:Q:@
作者: GTR1113    时间: 2013-2-21 20:00
freedom213 发表于 2013-1-30 12:13
求解释啊,大神们 ,我也看不懂这儿啊啊啊啊啊

你可以把angle*P+anglespeed*D的结果的范围设定到-1000到1000之间,而非-1.0到1.0之间,这个是自己规定的,然后自己调节P和D使得上面的结果的数值在你设定的范围之内,并且最大值差不多1000,最小值-1000,就行了。就这个意思,自己好好理解理解

作者: 毕业设计    时间: 2013-3-6 10:32
nPeriod = (short)getReg(PWM_PWMCM);

楼主,请教一个问题哈,这句话是什么意思,那个nperiod得出来的是个什么东西?
作者: 毕业设计    时间: 2013-3-6 10:33
GTR1113 发表于 2013-2-21 20:00
你可以把angle*P+anglespeed*D的结果的范围设定到-1000到1000之间,而非-1.0到1.0之间,这个是自己规定的 ...

nPeriod = (short)getReg(PWM_PWMCM);

请教一个问题哈,这句话是什么意思,那个nperiod得出来的是个什么东西?
作者: GTR1113    时间: 2013-3-13 21:43
毕业设计 发表于 2013-3-6 10:32
nPeriod = (short)getReg(PWM_PWMCM);

楼主,请教一个问题哈,这句话是什么意思,那个nperiod得出来的是 ...

获取PWM_PWMCM寄存器的值

作者: a269799355    时间: 2013-3-15 12:29
GTR1113 发表于 2013-3-13 21:43
获取PWM_PWMCM寄存器的值

请问下LZ。。。  K60 没这个寄存器及函数怎么办....  这个值是不是一个定值..纠结死我了~~~   fLeftVoltage 这个值怎么我的变化是-14-14

作者: GTR1113    时间: 2013-3-20 17:53
a269799355 发表于 2013-3-15 12:29
请问下LZ。。。  K60 没这个寄存器及函数怎么办....  这个值是不是一个定值..纠结死我了~~~   fLeftVolta ...

PWM_PWMCM 这个值应该是可以自己设定的。K60没有这个,不是一款芯片当然不同了,弄清原理。  fLeftVoltage 应该能随着P,I,D的调剂变化的。

作者: 抓住指間の落寞.    时间: 2013-3-30 12:34
请问lz  short nPeriod;
这句话是什么意思?nPeriod 是一个变量吗,还是一个常数?
作者: 抓住指間の落寞.    时间: 2013-3-30 12:36
SetMotorVoltage();这个函数是有什么作用的? 表示对如何把角度转化为占空比这一步骤不清楚
作者: GTR1113    时间: 2013-3-30 21:14
抓住指間の落寞. 发表于 2013-3-30 12:36
SetMotorVoltage();这个函数是有什么作用的? 表示对如何把角度转化为占空比这一步骤不清楚


SetMotorVoltage(); 这个函数就是用来给电机占空比的。          怎么把角度转化成占空比上边有说明,不明白就再好好想想。

作者: 三水亦是哥    时间: 2013-3-31 15:55
倘若将U设定在[-1000, 1000]之间,那么PWM的周期寄存器和占空比寄存器的值应为多少?
作者: 三水亦是哥    时间: 2013-3-31 15:56
三水亦是哥 发表于 2013-3-31 15:55
倘若将U设定在[-1000, 1000]之间,那么PWM的周期寄存器和占空比寄存器的值应为多少?

这个问题我也困扰多时了,看了你上面的回答,还是没有彻底理解,麻烦能详细解释一下

作者: GTR1113    时间: 2013-3-31 20:59
三水亦是哥 发表于 2013-3-31 15:55
倘若将U设定在[-1000, 1000]之间,那么PWM的周期寄存器和占空比寄存器的值应为多少?

PWM周期寄存器的值设定为1000,把SpeedVoltage强制转换成整型给占空比寄存器。

SpeedVoltage=Speed_P + Speed_I + Speed_D。
直立车的话,单独调试直立的量是AngleControl=k1*angle+k2*angle_speed,就把这个量AngleControl给占空比寄存器。k1,k2就是个放大倍数,可以把AngleControl放大或缩小到-1000到1000之间。 就这个道理





欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2