做英飞凌比赛的全纪录(持续更新哦~)
larix.Wiki文档
在看代码之前,有极大的必要仔细阅读larix.Wiki那份文档,才能明白整个框架,明白每个工程到底要实现哪些目标。
所以,还是先总结下整个文档讲了什么
1)简介这块飞控板,以及要实现的目标。
2)数学模型。
3)控制器的设计和原理,数字控制器 在 Infineon XMC-4500 微型控制器中的文件 AttitudeController.c & AttitudeController.h.中实现。
4)硬件的组成。
*5)(这是我着重要说的,因为和我的任务密切相关,第5部分的阅读方便俯瞰整个代码)LARIX主板主要用于收集遥控器的信号以及实时的内部测量值,然后将数据传给数据处理器,再转换成所需要的PWM值,发送给电调,电调控制电机转动。
整个软件由下面的这些section构成,而每一个section都有其对应的function
· Controller The attitude controller for the quadcopter is implemented on the microcontroller by the files AttitudeController.c and AttitudeController.h
o AngleController(...)角度控制器函数 定义r,y,a,b,u,x
o AngleRateController(...)角速度控制函数,按比例控制油门运动的变化(通过角速度解算姿态)
o CreatePulseWidth(...)脉宽没懂==
· RC-receiver 16个字节的命令不同位置的字节分别表达不同的信息,throttle,elevator,rudder...
o mergeBytes(...) 极其晕,但我的理解是这几个函数的是为了实现将遥控器所发射的数字信号转化成模拟信号。
o map(...)
· Sensor MPU-9150 通过I2C协议 连接MPU9150传感器和微型控制器,*The I2C communication is implemented in the files I2Cdev.c and I2Cdev.h.
o I2Cdev_writeBytes(…) 写入
o I2Cdev_readBytes(…) 读取
· BLDC controller implementation 通过PWMSP001这个应用程序来实现电调控制
· Daisy Chain 菊花链
*关于主函数的理解(记住这几个变量!!):1)两个数组pwmpercent和pwmwidth包含当前的脉宽值(电机)用百分比和毫秒的形式表示。数组xpitch,xroll存储控制器之前的计算值。数组的长度和控制器给的数字转换函数(digita transfer function)所给的命令相等
2)float变量uroll,upitch,uyawdot包含当前控制器输出值
3)控制参数P,D,N在仿真系统里定义了
4)浮点数组aroll,apitch,broll,bpitch包含的是控制转换函数的多项式系数,而当前飞机的角度被存储在YPR这个三维数组里
5)在初始化以后,控制参数就会被定义,RC计时器就开始运行
7)初始化后的微处理器- 9150产生外部频率为50 Hz的中断,由函数ERUEventHandler()来计算。用来检查传感器的数值是否处理的太慢。如果处理太慢,传感器的缓冲区(fifo)就会报告溢出。
再来解释一波USBVC001DAVE-App USBVC00是一个作为用户界面通过终端接口和PC相连接,传输当前值的终端程序。 通过给微型控制器发送特定的数字,每一个数字代表不同的数据(由那个table图给出)主函数中给出的USBVC001-sending,即是为了得到这个特定的数值以传给微型控制器。
我目前遇到的问题:1,这三个工程分别表示什么,第一个和第三个为何如此相似?
2,脉宽是啥
-------------------------------------------------by-crystal==-7.21------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
先回答下脉宽
Pulse width脉宽,脉冲宽度:脉冲宽度就是高电平持续的时间,高电平:在逻辑电平中保证逻辑门的输入为高电平时所允许的最小输入高电平,当输入电平高于输入高电压(Vih) 时,则认为输入电平为高电平。以我目前的理解是通过(percent占空比)和(ms应该是频率)来表示脉宽
以下的内容是我对main.c文件的一些理解
void Controller_CompareMatch_Int_Handler( void ){
GetAngles(YPR); //通过计算得到当前的角度(z,Y,x三个方向)
GetRCData(&powerD, &yawD_dot, &pitchD, &rollD); //通过计算得到遥控器发出的的数据值
//YPR[0]=0;
// yaw control
AngleRateController(&yawD_dot, &YPR[0], &P_yaw, &u_yaw_dot); //计算得到当前角速度,俯仰的姿态是通过角速度来解算的
//pitch control
AngleController(&pitchD, &YPR[1], CONTROL_ORDER, a_pitch, b_pitch, x_pitch, &u_pitch); //算出偏航角
//roll control
AngleController(&rollD, &YPR[2], CONTROL_ORDER, a_roll, b_roll, x_roll, &u_roll); //算出横滚角
//generate actuator values// 以上的计算都是为了得到执行器的值
CreatePulseWidth(&u_roll, &u_pitch, &u_yaw_dot, &powerD, PWM_percent); //计算出脉宽占空比,再将四个PWM值以菊花链的形式发给四个电调
SendDaisyData(SET_REF_CURRENT,
PWM_percent[0]/100.0*1279,
PWM_percent[1]/100.0*1279,
PWM_percent[3]/100.0*1279,
PWM_percent[2]/100.0*1279);
/*SendDaisyData(SET_REF_CURRENT, // powerD是怎么得来的?
powerD/100.0*1279,
powerD/100.0*1279,
powerD/100.0*1279,
powerD/100.0*1279);*/
counter_main++;
}
void Initialize ()
{
delay(1000);
// initialize device
MPU9150_Setup();
// initilize controller polynomials //初始化控制器的多项式系数,通过PID来调节实现
b_roll[0]=P_roll-I_roll*T-P_roll*N_roll*T+N_roll*I_roll*T*T+D_roll*N_roll;
b_roll[1]=I_roll*T-2*P_roll+P_roll*N_roll*T-2*D_roll*N_roll;
b_roll[2]=P_roll+D_roll*N_roll;
a_roll[0]=1-N_roll*T;
a_roll[1]=N_roll*T-2;
b_pitch[0]=P_pitch-I_pitch*T-P_pitch*N_pitch*T+N_pitch*I_pitch*T*T+D_pitch*N_pitch;
b_pitch[1]=I_pitch*T-2*P_pitch+P_pitch*N_pitch*T-2*D_pitch*N_pitch;
b_pitch[2]=P_pitch+D_pitch*N_pitch;
a_pitch[0]=1-N_pitch*T;
a_pitch[1]=N_pitch*T-2;
WatchRC_Init(); //Initialize RC watchdog //初始化RC时间监控器
delay(1000);
//InitDaisy(); //初始化菊花链
PWMSP001_Start(&PWMSP001_Handle0); //这个函数用来启动 Dave 的那些 apps (ERU001,002,I2C001,USBCV001D等等),即使内部已经完成配置也会被要求执行。
}
int main已经在上面解释过了
这一段是我今天没有搞懂的
if (sendMag)
{sendMag = FALSE ;
USBVC001_SendString(( const char *)c);
}
// Call continuous to handle class specific control request //连续调用来处理特定的控制结果? 如和连续调用?
USB_USBTask();
}
return 0;
}
void Mag_Calibration_Int_Handler()
{
GetMagData (sensorData);
sprintf (c, "%f,%f,%f\r\n" , sensorData[0], sensorData[1], sensorData[2]);
sendMag = TRUE ;
}
------------------------------------------------------------------------by-crystal---2016-7-23------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------