第七节 PID在智能小车中的应用
应大家要求,来个实例,最好是小车的PID应用。没问题,大家的要求只要是合理我都会答应。自动化有一门课叫运动控制原理,这是自动化的精髓。恰好,我是自动化出身,正宗科班。
/******************************************************************************************
** 函数名称: CarDriveInit
** 功能描述: 电机驱动初始化
** 入口参数: 无
** 出口参数: 无
*******************************************************************************************/
void CarDriveInit(void)
{
DCMotorA1OUT();
DCMotorA2OUT();
DCMotorA3OUT();
DCMotorA4OUT();
CarStop(); // 初始为停车
GPIO2BreakInit(GPIO2_BREAK_PIN);
T161Init();
PIDInit((PID*)&LDCMotorPID);
LDCMotorPID.MaxOut = GetPlayData(PAGE7);
LDCMotorPID.MinOut = 1;
LDCMotorPID.Kp = LDCMOTOR_KP;
LDCMotorPID.Ki = LDCMOTOR_KI;
LDCMotorPID.Kd = LDCMOTOR_KD;
PIDInit((PID*)&RDCMotorPID);
RDCMotorPID.MaxOut = GetPlayData(PAGE8);
RDCMotorPID.MinOut = 1;
RDCMotorPID.Kp = RDCMOTOR_KP;
RDCMotorPID.Ki = RDCMOTOR_KI;
RDCMotorPID.Kd = RDCMOTOR_KD;
}
/******************************************************************************************
** 函数名称: CarAngle
** 功能描述: 小车转固定的角度(定轮方式)
** 入口参数: angle--角度
dir--方向 (1--左转,2--右转)
fun--在等待过程中要处理的事件,回调形式完成
** 出口参数: 无
*******************************************************************************************/
void CarAngle(uint32 angle, uint8 dir, uint8 (*fun)(void))
{
uint32 AngleCount = 0; // 需要的角度对应的脉冲数
// AngleCount = 2*PI*LENGHT*angle*CIRCLE_COUNT/(360*CARTWHEEL_GIRTH);
// AngleCount = PI*LENGHT*angle*CIRCLE_COUNT/(180*CARTWHEEL_GIRTH);
AngleCount = 6.2 * angle - GetPlayData(PAGE9);
if (1 == dir){ // 左转 ,对右轮进行计数
CarLStop();
RDCMotorPulseCount = 0;
CarRDrive(295,1);
while (RDCMotorPulseCount < AngleCount){
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
} else if (2 == dir) { // 右转,对左轮进行计数
CarRStop();
LDCMotorPulseCount = 0;
CarLDrive(295,1);
while (LDCMotorPulseCount < AngleCount){
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
}
}
/******************************************************************************************
** 函数名称: CarBackAngle
** 功能描述: 小车转固定的角度(后退方式)
** 入口参数: angle--角度
dir--方向 (1--左转,2--右转)
fun--在等待过程中要处理的事件,回调形式完成
** 出口参数: 无
*******************************************************************************************/
void CarBackAngle(uint32 angle, uint8 dir, uint8 (*fun)(void))
{
uint32 AngleCount = 0; // 需要的角度对应的脉冲数
// AngleCount = 2*PI*LENGHT*angle*CIRCLE_COUNT/(360*CARTWHEEL_GIRTH);
// AngleCount = PI*LENGHT*angle*CIRCLE_COUNT/(180*CARTWHEEL_GIRTH);
AngleCount = 6.2 * angle - GetPlayData(PAGE11);
if (1 == dir){ // 左转 ,对右轮进行计数
CarRStop();
LDCMotorPulseCount = 0;
CarLDrive(295,2);
while (LDCMotorPulseCount < AngleCount){
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
} else if (2 == dir) { // 右转,对左轮进行计数
CarLStop();
RDCMotorPulseCount = 0;
CarRDrive(295,2);
while (RDCMotorPulseCount < AngleCount) {
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
}
}
/******************************************************************************************
** 函数名称: CarMidAngle
** 功能描述: 小车转固定的角度(中心轴方式)
** 入口参数: angle--角度
dir--方向 (1--左转,2--右转)
fun--在等待过程中要处理的事件,回调形式完成
** 出口参数: 无
*******************************************************************************************/
void CarMidAngle(uint32 angle, uint8 dir, uint8 (*fun)(void))
{
uint32 AngleCount = 0; // 需要的角度对应的脉冲数
// AngleCount = 2*PI*LENGHT*angle*CIRCLE_COUNT/(360*CARTWHEEL_GIRTH);
// AngleCount = PI*LENGHT*angle*CIRCLE_COUNT/(180*CARTWHEEL_GIRTH);
AngleCount = 3.1 * angle - GetPlayData(PAGE10);
if (1 == dir){ //
RDCMotorPulseCount = 0;
LDCMotorPulseCount = 0;
CarLDrive(295,2); // 左轮反转
CarRDrive(295,1); // 右轮正转
while ((RDCMotorPulseCount < AngleCount)&&(LDCMotorPulseCount < AngleCount)) { // 等待行走完毕
if (NULL != fun){
if (fun()) {
break;
}
}
}
CarStop();
} else if (2 == dir) { //
RDCMotorPulseCount = 0;
LDCMotorPulseCount = 0;
CarLDrive(295,1); // 左轮反转
CarRDrive(295,2); // 右轮正转
while ((RDCMotorPulseCount < AngleCount)&&(LDCMotorPulseCount < AngleCount)) { // 等待行走完毕
if (NULL != fun){
if (fun()) {
break;
}
}
}
CarStop();
}
}
/******************************************************************************************
** 函数名称: CarArcAngle
** 功能描述: 小车转固定的角度(弧线模式)
** 入口参数: angle--角度
dir--方向 (1--左转,2--右转)
fun--在等待过程中要处理的事件,回调形式完成
** 出口参数: 无
*******************************************************************************************/
void CarArcAngle(uint32 angle, uint8 dir, uint8 (*fun)(void))
{
uint32 LAngleCount = 0; // 需要的角度对应的脉冲数
uint32 RAngleCount = 0; // 需要的角度对应的脉冲数
if (1 == dir){ // 左转 ,对右轮进行计数
LAngleCount = PI*(GetPlayData(PAGE12))*angle*CIRCLE_COUNT/(180*(CARTWHEEL_GIRTH)) - GetPlayData(PAGE16);
RAngleCount = PI*(LENGHT+GetPlayData(PAGE12))*angle*CIRCLE_COUNT/(180*(CARTWHEEL_GIRTH)) - GetPlayData(PAGE14);
CarStop();
RDCMotorPulseCount = 0;
LDCMotorPulseCount = 0;
CarLDrive(GetPlayData(PAGE15),1); // 左轮慢
CarRDrive(GetPlayData(PAGE13),1); // 右轮快
while ((RDCMotorPulseCount < RAngleCount)||(LDCMotorPulseCount < LAngleCount)) {
if (RDCMotorPulseCount >= RAngleCount){
CarRStop();
}
if (LDCMotorPulseCount >= LAngleCount){
CarLStop();
}
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
} else if (2 == dir) { // 右转,对左轮进行计数
RAngleCount = PI*(GetPlayData(PAGE12))*angle*CIRCLE_COUNT/(180*(CARTWHEEL_GIRTH)) - GetPlayData(PAGE16);
LAngleCount = PI*(LENGHT+GetPlayData(PAGE12))*angle*CIRCLE_COUNT/(180*(CARTWHEEL_GIRTH))- GetPlayData(PAGE14);
CarStop();
RDCMotorPulseCount = 0;
LDCMotorPulseCount = 0;
CarLDrive(GetPlayData(PAGE13),1); // 左轮快
CarRDrive(GetPlayData(PAGE15),1); // 右轮慢
while ((RDCMotorPulseCount < RAngleCount)||(LDCMotorPulseCount < LAngleCount)) {
if (RDCMotorPulseCount >= RAngleCount){
CarRStop();
}
if (LDCMotorPulseCount >= LAngleCount){
CarLStop();
}
if (NULL != fun){
if (fun()) {
break;
}
}
}// 等待行走完毕
CarStop();
}
}
/******************************************************************************************
** 函数名称: CarLineLength
** 功能描述: 小车走指定的距离
** 入口参数: length--行走长度 单位(mm)
dir--方向 (1--前进,2--后退)
fun--在等待过程中要处理的事件,回调形式完成
** 出口参数: 无
*******************************************************************************************/
void CarLineLength (uint32 length, uint8 dir, uint8 (*fun)(void))
{
uint32 LineCount = 0; // 需要的距离对应的脉冲数
//AngleCount = length*CIRCLE_COUNT/(CARTWHEEL_GIRTH);
LineCount = 2.1 * length - GetPlayData(PAGE28);
LDCMotorPulseCount = 0;
RDCMotorPulseCount = 0;
CarRDrive(GetPlayData(PAGE18),dir);
CarLDrive(GetPlayData(PAGE17),dir);
// 等待行走完毕
while ((RDCMotorPulseCount < LineCount)||(LDCMotorPulseCount < LineCount)) {
if (RDCMotorPulseCount >= LineCount){
CarRStop();
}
if (LDCMotorPulseCount >= LineCount){
CarLStop();
}
if (NULL != fun){
if (fun()) {
break;
}
}
}
CarStop();
}