一、基本功能描述:

1、基本循迹功能。对于直道、S弯道和钝角弯道,小车可沿黑线轨迹自动进行调整使黑线在小车正中间。如若出现小车全脱离黑线,小车进行逆时针旋转直至再次检测到黑线进行循迹。

2、特殊赛道循迹功能。对于直角、锐角赛道,小车进行较大幅度转向不偏离轨道。对于十字路口赛道,即小车检测模块全压在黑线,小车直行跨越黑线。

3、防碰撞功能:在碰撞障碍时可以识别障碍的存在并进行避障。(本次课程未实现)

二、硬件结构:

2.1:小车整体分为5大模块:

(1)控制模块:搭载单片机MSP432的Launch Pad主板

(2)驱动模块:电池组、N20直流电机

(3)循迹模块:红外LED传感器

(4)防撞模块:防撞开关

(5)运动模块:底盘和车轮等

模块作用:

(1)控制模块即使用单片机编程,实现代码控制小车按一定路线行进

(2)驱动模块即是提供能源动力的部分

(3)循迹模块是使用红外传感器,通过反射的不同来识别路面,以获得轨道信息

(4)防撞模块是通过防撞开关进行传感,以使小车识别障碍,进而实现避障功能

(5)运动模块是小车主体部分,是进行运动的主体

2.2:这里主要介绍本次课程重点的3个模块

(1)控制模块:MSP432P401R Launch Pad包含48MHz ARM CortexM4F内核80μA/MHz工作功耗和660nA RTC操作,14位1Msps差动SAR ADC和AES256加速器。

处理器特性:低功耗、高性能的MSP432P401R MCU

带浮点单元和DSP加速功能的48MHz 32位ARM CortexM4F

功耗:80μA/MHz工作功耗和660nA RTC待机操作功耗

模拟:24通道14位1Msps差动SAR ADC两个比较器

数字:高级加密标准(AES256)加速器、CRC、DMA、32位硬件乘法器

存储器:256KB闪存、64KB RAM

计时器:4个16位、2个32位

通信:多达4个I2C、8个SPI、4个UART

40引脚BoosterPack连接器,支持20引脚BoosterPack采用EnergyTrace+技术的板载XDS-110ET仿真器 2个按钮和2个LCD,便于用户交互反向通道UART通过USB连接到PC

MSP432处理器可以使用CCS、IAR和Keil μVision IDE来开发。

整块电路板的框图如下:

以电路板上虚线为分界,上半部分是XDS-110ET仿真器,S101开关来选择板载XDS-110ET仿真器还是用外部仿真器

MSP432P401R与XDS-110ET的连接可以断开,MSP432P401R与XDS-110ET除仿真信号外没有其他通讯连接,仿真信号包括XDS-110ET串行调试信号、应用UART信号和3.3V、5V电源

(2)驱动模块:两节3.7V可充电锂电池

N20直流减速电机:

产品型号: GM12-N20VA

主要用途:标签打印机、标签剥离机、条码打印机、机器人、电子门锁、打印机、电子监控器、美容仪器、展示架、柜台、自动售货机等

电压:3V 4.5V 6V 12V

转速:3rpm--1000rpm

力矩: 最大 7kg.cm

外形尺寸:12*10*25mm

出轴外径: 3mm, (出轴长短可根据客户的要求设计)

输出轴可以加工成M3螺纹, M4螺纹

12*10mm微型精密减速器.

减速比:1/3、1/5、1/10、1/30、1/50、1/63、1/100、1/150、1/210、1/250、1/298、1/370、1/380、1/1000

(3)循迹模块:红外传感器原理:利用8路红外传感器感知地面颜色信息,控制机器人沿白线行进。不同的材料表面对红外线的反射能力不同,红外接收器电压变化也就不同,如下图:

可以看出,白色表面比黑色表面下降更快,由此我们记录高电平时间,通过这个时间的长短即可以判断地面是黑色或白色。
控制:对于这种车型,小车的控制当然是差速控制。8路开关,可以把差速分为4个等级,不同等级差速大小不一样,这几个参数影响小车循迹的稳定性,要根据实际情况调整。电机配有编码器,使用定时器输入捕获功能进行正交解码即可得知电机转速信息,这样就能实现电机闭环控制,让小车运行效果更好。

三、控制算法及软件实现

主要内容:

3.1 软件平台及安装

CCS,Keil uVision5,pack驱动包

3.2 软件系统总体结构及各模块的功能定义

(1)Keil uVision5用于寻迹小车的代码学习和书写,并将程序下入32单片机对小车进行驱动。

(2)Keil.STM32F4xx_DFP.1.0.8.pack为小车配置编程环境

(3)电机使用例程,对单片机对电机的驱动方式方法有了初步的了解,并实现电机的各种功能。

(4)循迹旧版例程,通过红外传感器对黑线识别来控制小车行走,其中涉及二进制,十六进制,单片机IO口等

3.3 关键算法和软件实现

if((0xFF==flag)||(0xFE==flag)||(0x7F==flag))//十字路口代码{//            if(0==TrackingControlCnt)
//            {
//                TrackingControlCnt=1;
//                return ;
//            }
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);
//            while(!Turn(TurnForward,120,200));while(!Turn(TurnForward,90,500));
//            TrackingControlCnt=0;
LEDPreError=0;
LEDLastError=0;
TrackingControlFlag=0;
L_Wheel_Speed=L_Wheel_Init_Speed;
R_Wheel_Speed=R_Wheel_Init_Speed;
L_Wheel_Positive();
R_Wheel_Positive();
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,
L_Wheel_Init_Speed);
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,
R_Wheel_Init_Speed);
return ;}
else if((0xB8==flag)||(0x98==flag)||(0x9C==flag)||(0xB0==flag))//左锐角代码{
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);while(!Turn(TurnForward,100,600));while(!Turn(TurnLeft,80,900));
TrackingControlCnt=0;
LEDPreError=0;
LEDLastError=0;
TrackingControlFlag=0;
L_Wheel_Speed=L_Wheel_Init_Speed;
R_Wheel_Speed=R_Wheel_Init_Speed;
L_Wheel_Positive();
R_Wheel_Positive();
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,
L_Wheel_Init_Speed);
Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,
R_Wheel_Init_Speed);
return ;}

这里给出2个较为关键的识别代码

3.4功能模块的具体实现

//前进后退转弯代码#include "MOTOR.h"//在MSP432参考指南找到对应章节有关TimerA的介绍
//定时器A向上计数模式配置结构体Timer_A_UpModeConfig upConfig =
{TIMER_A_CLOCKSOURCE_SMCLK,              // SMCLK Clock SourceTIMER_A_CLOCKSOURCE_DIVIDER_48,         // SMCLK/48 = 1MHz1000,                                   // 5000 tick periodTIMER_A_TAIE_INTERRUPT_DISABLE,         // Disable Timer interruptTIMER_A_CCIE_CCR0_INTERRUPT_ENABLE ,    // Enable CCR0 interruptTIMER_A_DO_CLEAR                        // Clear value
};//SMCLK是系统子时钟,MCLK是系统主时钟
//定时标志
volatile uint8_t TimingFlag=0;
//溢出次数LoopCnt,余数TimingVal 溢出次数=定时时间/0xFFFF 余数=定时时间%0xFFFF
volatile uint32_t LoopCnt=0,TimingVal=0;//电机初始化
void MotorInit(void)
{Timer_A_PWMConfig pwm1Config ={TIMER_A_CLOCKSOURCE_SMCLK,//时钟源选择SMCKTIMER_A_CLOCKSOURCE_DIVIDER_1,//1分频2000,//周期为2000个SMCK时钟周期L_CAPTURECOMPARE_REGISTER,//选择左轮电机PWMTIMER_A_OUTPUTMODE_RESET_SET,0//初始占空比为0};Timer_A_PWMConfig pwm2Config ={TIMER_A_CLOCKSOURCE_SMCLK,//时钟源选择SMCKTIMER_A_CLOCKSOURCE_DIVIDER_1,//1分频2000,//周期为2000个SMCK时钟周期R_CAPTURECOMPARE_REGISTER,//选择右轮电机PWMTIMER_A_OUTPUTMODE_RESET_SET,0//初始占空比为0};//GPIO复用配置MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(MotorPWMPort,L_PWM_Pin|R_PWM_Pin,GPIO_PRIMARY_MODULE_FUNCTION);//设置引脚L_PWM_Pin和R_PWM_Pin为复用功能MAP_GPIO_setAsOutputPin(MotorDirectionPort,L_Direction_Pin|R_Direction_Pin);//设置引脚L_Direction_Pin和R_Direction_Pin为普通输出//PWM配置MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwm1Config);//产生PWM到左轮电机MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwm2Config);//产生PWM到右轮电机//转向定时配置器MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);//配置定时器向上计数模式MAP_Interrupt_enableInterrupt(INT_TA1_0);//打开定时器中断
}//原地转向函数
//direction:方向,可选参数TurnLeft,TurnRight,TurnForward,TurnBackward
//angle:角度 范围:任意度数(前进和后退时此参数为运动时间)
//speed:转向速度,范围:0~2000
uint8_t Turn(uint8_t direction,float angle,uint32_t speed)
{uint32_t time;if(0==TimingFlag){time=angle*TimingPerAngle;if(time<=0xFFFF){LoopCnt=0;TimingVal=time;}else{LoopCnt=time/0xFFFF;TimingVal=time%0xFFFF;}upConfig.timerPeriod=TimingVal;MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);//转弯代码--开始转弯switch(direction){case 1:Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,speed);Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,speed);L_Wheel_Positive();R_Wheel_Negative();break;//右转case 2:Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,speed);Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,speed);L_Wheel_Negative();R_Wheel_Positive();break;//左转case 3:Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,speed);Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,speed);L_Wheel_Negative();R_Wheel_Negative();break;//后退case 4:Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,speed+65);//(若左右轮转速不同可增加一个常数调节)Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,speed);L_Wheel_Positive();R_Wheel_Positive();break;//前进default:break;}MAP_Timer_A_startCounter(TIMER_A1_BASE,TIMER_A_CONTINUOUS_MODE);TimingFlag=1;}else if(2==TimingFlag){TimingFlag=0;return 1;}return 0;
}void TA1_0_IRQHandler(void)
{MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_0);if(0==LoopCnt){Timer_A_stopTimer(TIMER_A1_BASE);//转弯代码--停止转弯Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,0);Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,0);MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);TimingFlag=2;}else{LoopCnt--;upConfig.timerPeriod=0xFFFF;MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);MAP_Timer_A_startCounter(TIMER_A1_BASE,TIMER_A_CONTINUOUS_MODE);}
}
//红外传感模块代码#include "ReflectSensor.h"//void ReflectSensorInit(void)
//{
//}uint8_t ReadReflectSensor(void)
{uint8_t val=0;//对管端口设置为输出方式MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin0);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin1);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin2);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin3);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin4);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin5);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin6);MAP_GPIO_setAsOutputPin(ReflectSensorPort,ReflectSensor_Pin7);//对管LED设置为输出方式MAP_GPIO_setAsOutputPin(ReflectSensorLED_Port,ReflectSensorLED_Pin);//对管端口输出为高电平MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin0);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin1);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin2);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin3);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin4);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin5);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin6);MAP_GPIO_setOutputHighOnPin(ReflectSensorPort,ReflectSensor_Pin7);//打开LED,对电容充电MAP_GPIO_setOutputHighOnPin(ReflectSensorLED_Port,ReflectSensorLED_Pin);//延迟10usDelayUs(10);//设置对管端口为输入方式MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin0);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin1);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin2);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin3);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin4);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin5);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin6);MAP_GPIO_setAsInputPin(ReflectSensorPort,ReflectSensor_Pin7);//延时1.7ms(建议在1~2之间,可用来调节对轨道识别灵敏度)DelayUs(1700);//读对管引脚val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin0)<<7);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin1)<<6);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin2)<<5);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin3)<<4);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin4)<<3);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin5)<<2);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin6)<<1);val|=(MAP_GPIO_getInputPinValue(ReflectSensorPort,ReflectSensor_Pin7)<<0);//关闭管LEDMAP_GPIO_setOutputLowOnPin(ReflectSensorLED_Port,ReflectSensorLED_Pin);//返回测量值return val;
}
//避障模块代码#include "CrashSensor.h"
#include "Motor.h"
#include "Delay.h"volatile uint8_t DetectionVal=0;
uint8_t AvoidFlag=0;
extern uint8_t TimingFlag;const uint8_t SensorAngleTab[]={Sensor1Angle,Sensor2Angle,Sensor3Angle,\Sensor4Angle,Sensor5Angle,Sensor6Angle};void CrashSensorInit(void)
{MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P6,GPIO_PIN0|GPIO_PIN1|\GPIO_PIN2|GPIO_PIN3|\GPIO_PIN4|GPIO_PIN5);MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P6,GPIO_PIN0|GPIO_PIN1|\GPIO_PIN2|GPIO_PIN3|\GPIO_PIN4|GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);MAP_Interrupt_setPriority(INT_PORT6,0xE8);MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, GPIO_PIN0|GPIO_PIN1|\GPIO_PIN2|GPIO_PIN3|\GPIO_PIN4|GPIO_PIN5);MAP_GPIO_enableInterrupt(GPIO_PORT_P6,GPIO_PIN0|GPIO_PIN1|\GPIO_PIN2|GPIO_PIN3|\GPIO_PIN4|GPIO_PIN5);MAP_Interrupt_enableInterrupt(INT_PORT6);}void PORT6_IRQHandler(void)
{uint32_t status,cnt,i;status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P6);MAP_GPIO_clearInterruptFlag(GPIO_PORT_P6, status);if(status & GPIO_PIN0){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN0))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x01;}if(status & GPIO_PIN1){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN1))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x02;}if(status & GPIO_PIN2){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN2))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x04;}if(status & GPIO_PIN3){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN3))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x08;}if(status & GPIO_PIN4){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN4))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x10;}if(status & GPIO_PIN5){cnt=0;for(i=0;i<SampleCnt;i++){if(GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN5))cnt++;}if(cnt>SampleThreshold)return ;DetectionVal|=0x20;}
}void CrashAvoid(void)
{uint8_t i;uint32_t sum=0,cnt=0;//停止状态if(0==AvoidFlag){AvoidFlag=1;}//直线行驶状态else if(1==AvoidFlag){L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,500);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,500);AvoidFlag=2;}//障碍检测状态else if(2==AvoidFlag){if(DetectionVal!=0){DelayUs(1000);//停止前进Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);for(i=0;i<SensorCnt;i++){if((DetectionVal>>i)&0x01){sum+=SensorAngleTab[i];cnt++;}}sum=sum/cnt;//后退while(!Turn(3,50,1000));if(sum>90){sum=180-sum;//退后几步再右拐//补充退后代码Turn(1,sum,2000);}else if(sum<90){//退后几步再左拐//补充退后代码Turn(2,sum,2000);}else{//退后几步再左拐//补充退后代码Turn(2,180,2000);}AvoidFlag=3;}}//避障完成else if(3==AvoidFlag){if(2==TimingFlag){TimingFlag=0;AvoidFlag=0;DetectionVal=0;}}
}
//红外循迹模块代码#include "Track.h"float L_Wheel_Speed=L_Wheel_Init_Speed,R_Wheel_Speed=R_Wheel_Init_Speed;
float LEDError=0,LEDLastError=0,LEDPreError=0,PIDVal=0,ErrorSum=0;
float Kp=150,Ki=0.01,Kd=30;
uint16_t TrackingControlFlag=0,TrackingControlCnt=0;void TrackLine(void)
{uint8_t flag=0;float temp;flag=ReadReflectSensor();  if((0x18==flag)||(0x08==flag)||(0x10==flag)){LEDError=0;}else if((0xFF==flag)||(0xFE==flag)||(0x7F==flag)){if(TrackingControlFlag<DirectionInterval)return ;
//            if(0==TrackingControlCnt)
//            {
//                TrackingControlCnt=1;
//                return ;
//            }Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);
//            while(!Turn(TurnForward,120,200));while(!Turn(1,120,1000));while(!Turn(TurnForward,90,500));
//            TrackingControlCnt=0;LEDPreError=0;LEDLastError=0;TrackingControlFlag=0;L_Wheel_Speed=L_Wheel_Init_Speed;R_Wheel_Speed=R_Wheel_Init_Speed;L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,L_Wheel_Init_Speed);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,R_Wheel_Init_Speed);return ;}else if((0xF8==flag)||(0xFC==flag)){if(TrackingControlFlag<DirectionInterval)return ;Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);while(!Turn(TurnForward,120,500));while(!Turn(TurnLeft,130,1000));while(!Turn(TurnForward,100,500));
//            TrackingControlCnt=0;LEDPreError=0;LEDLastError=0;TrackingControlFlag=0;L_Wheel_Speed=L_Wheel_Init_Speed;R_Wheel_Speed=R_Wheel_Init_Speed;L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,L_Wheel_Init_Speed);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,R_Wheel_Init_Speed);return ;}else if((0x1F==flag)||(0x3F==flag)){if(TrackingControlFlag<DirectionInterval)return ;Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);while(!Turn(TurnForward,120,500));while(!Turn(TurnRight,130,1000));while(!Turn(TurnForward,100,500));
//            TrackingControlCnt=0;LEDPreError=0;LEDLastError=0;TrackingControlFlag=0;L_Wheel_Speed=L_Wheel_Init_Speed;R_Wheel_Speed=R_Wheel_Init_Speed;L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,L_Wheel_Init_Speed);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,R_Wheel_Init_Speed);return ;}
//        else if((0x31==flag)||(0x33==flag)||(0x19==flag)||(0x39==flag)||(0x1D==flag))
//        {
//            if(TrackingControlFlag<DirectionInterval)
//                return ;
//            if(0==TrackingControlCnt)
//            {
//                TrackingControlCnt=1;
//                return ;
//            }
//            Timer_A_setCompareValue(TIMER_A0_BASE,
//                                    TIMER_A_CAPTURECOMPARE_REGISTER_3,
//                                    0);
//            Timer_A_setCompareValue(TIMER_A0_BASE,
//                                    TIMER_A_CAPTURECOMPARE_REGISTER_1,
//                                    0);
//            while(!Turn(TurnForward,200,500));
//            while(!Turn(TurnRight,210,1500));
//            while(!Turn(TurnForward,260,500));
//            TrackingControlCnt=0;
//            LEDPreError=0;
//            LEDLastError=0;
//            TrackingControlFlag=0;
//            L_Wheel_Speed=L_Wheel_Init_Speed;
//            R_Wheel_Speed=R_Wheel_Init_Speed;
//            L_Wheel_Positive();
//            R_Wheel_Positive();
//            Timer_A_setCompareValue(TIMER_A0_BASE,
//                                    TIMER_A_CAPTURECOMPARE_REGISTER_1,
//                                    L_Wheel_Init_Speed);
//            Timer_A_setCompareValue(TIMER_A0_BASE,
//                                    TIMER_A_CAPTURECOMPARE_REGISTER_3,
//                                    R_Wheel_Init_Speed);
//            return ;
//        }else if((0x1A==flag)||(0x1C==flag)||(0xB8==flag)||(0x98==flag)||(0x9C==flag)||(0xB0==flag)){Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,0);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,0);while(!Turn(TurnForward,100,200));while(!Turn(TurnLeft,68,1500));while(!Turn(TurnForward,200,600));TrackingControlCnt=0;LEDPreError=0;LEDLastError=0;TrackingControlFlag=0;L_Wheel_Speed=L_Wheel_Init_Speed;R_Wheel_Speed=R_Wheel_Init_Speed;L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1,L_Wheel_Init_Speed);Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_3,R_Wheel_Init_Speed);return ;}else if(0x80&flag)LEDError=3;else if(0x40&flag)LEDError=2;else if((0x20&flag))LEDError=1;else if(0x01&flag)LEDError=-3;else if(0x02&flag)LEDError=-2;else if((0x04&flag))LEDError=-1;(若要改变小车调整幅度,将不同情况LEDError差值减小)else{if((LEDError>0)&&(0==flag))LEDError=6;else if((LEDError<0)&&(0==flag))LEDError=-6;//ÍÑÀëºÚ½º´ø} //PID调整量计算
//        PIDVal=Kp*(LEDError-LEDLastError)+Kd*(LEDError-2*LEDLastError+LEDPreError);
//  PIDVal=Kp*(LEDError-LEDLastError)+Ki*LEDError;PIDVal=Kp*(LEDError-LEDLastError);
//        PIDVal=Kp*(LEDError-LEDLastError)+Ki*LEDError+Kd*(LEDError-2*LEDLastError+LEDPreError);LEDPreError=LEDLastError;LEDLastError=LEDError;//速度调整//速度限幅temp=R_Wheel_Speed;temp+=PIDVal; if(temp<PIDLowThreshold)R_Wheel_Speed=PIDLowThreshold;else if(temp>PIDHighThreshold)R_Wheel_Speed=PIDHighThreshold;elseR_Wheel_Speed=temp;temp=L_Wheel_Speed;temp-=PIDVal;if(temp<PIDLowThreshold)L_Wheel_Speed=PIDLowThreshold;else if(temp>PIDHighThreshold)L_Wheel_Speed=PIDHighThreshold;elseL_Wheel_Speed=temp;USARTSendStr("flag:",5);USARTSendNum(flag);USARTSendStr(",",1);USARTSendStr("L_Speed:",8);USARTSendNum(L_Wheel_Speed);USARTSendStr(",",1);USARTSendStr("R_Speed:",8);USARTSendNum(R_Wheel_Speed);USARTSendStr(",   ",4);L_Wheel_Positive();R_Wheel_Positive();Timer_A_setCompareValue(TIMER_A0_BASE,L_CAPTURECOMPARE_REGISTER,L_Wheel_Speed);Timer_A_setCompareValue(TIMER_A0_BASE,R_CAPTURECOMPARE_REGISTER,R_Wheel_Speed);
}

四、测试调试

项目一:小车电机驱动装置是否正常,能否进行前进、倒退和左右转弯。

1方法:我们小组将小车组装完成后,导入相应的代码,并多次调整电机速度观察是否出现相应运动。

2调试结果:当我们将左右电机的运转速度调成一致,小车前进时向右偏。左右转时并不能转动设定的角度。调整后能顺利直行,左右转弯。

3结果分析与结论:我们小组认为两个电机转动时速有些许差异,导致直行与转弯不顺。于是,我们将小车右轮速度调高,多次调整后,小车能准确进行直行运动,转弯也没有问题。

项目二:小车是否具有基本循迹功能,即黑线进行直行,钝角转弯等。

1方法:我们小组首先将循迹功能导入小车,通过人为按键去扫描小车压在黑线上的数据,在此基础上对程序进行提高。同时驱动小车,观察小车能否按预期进行运动,且保持稳定。

2测试仪器设备、环境:小车,XCOM软件,附有黑线的直道、S型弯道和钝角弯道。

3调试结果:当我们把代码导入小车就马上将小车压在黑线上,并打开XCOM软件进行数据采集,采集结果与预期相对应,小车扫描模块没有问题。于是,我们将小车分别压在S弯道和钝角弯道上,根据代码,小车能顺利行走,但是有些许的摇摆,不能很准确地行走。经过完善后能完成基本循迹功能。

4结果分析与结论:小车扫描模块没有任何问题,小车行走时有些许不稳定,我们判断可能是代码中的对小车偏离轨道的分析调整有些过头,于是我们适当地增加调整了小车对于偏离的调整数据,经过多次的测试,小车终于能够稳定地在黑线上行走。

项目三:小车是否具有特殊赛道循迹功能,即直角、锐角和十字路口。

1方法:我们用小车和XCOM软件多次在直角、锐角和十字路口上进行数据扫描,并根据结果对使小车进行相应动作,同时需要多次调整转动角度及电机速度。

2测试仪器设备、环境:小车,XCOM软件,附有黑线的直角、锐角和十字路口。

3调试结果:小车对于直角赛道的判断是较为容易的,只需一边的扫描器压在黑线,另一边压在地板上,仅有几次小车无法顺利判断。而锐角赛道和直角赛道就困难许多。对于锐角赛道,判定条件较多,且扫描速率对小车能否顺利通过有极大的影响,同时小车的转动角度也是一个难点。测试结果不是很理想,我们花费了许多时间去进行调试。而十字路口,起初我们的代码能很顺利的进行判断,并做出相应行动。但是在多次测试后,小车有挺大几率会判断成锐角转弯。

4结果分析与结论:对于直角赛道,我们小组认为是小车对于直角赛道的判断条件少了,通过小车多次扫描,我们认为不能小车一半压在一边一半压在另一边就可,在小车行走过程中,小车些许的晃动会使小车稍微偏离赛道,此时一边就只有3或5个扫描点,于是,我们增加了小车判断条件,更改后,小车能很顺利地通过直角赛道。对于锐角赛道,在多次的测试及数据分析后,我们总结了多个判断条件,更改代码后小车能顺利判断锐角弯道,在此基础上我们对转弯角度进行多次调试,使小车能够很好的转过锐角赛道。对于十字路口,我们采取小车遇十字路口直行方案。导入代码后,起初几次的判断结果都很好,能够顺利通过,但是多次测试后,对于十字路口的判别经常发生错误,很容易误判为锐角,通过串口记录小车行驶数据分析,由于传感器采样速率较快,在到达黑线边界时,这个值其实是模糊的,类似于锐角的值。所以,当检测到锐角时,让车前进一段时间再采样,越过黑线边界,多次调试后,我们找到了较为精确的前进时间数值使小车能顺利通过。

项目四:小车是否能稳定地重复在轨道上跑圈。

1方法:我们将初步成型的代码导入小车中,让小车不加干预的在赛道上跑圈。根据结果对小车具体参数进行更改。

2测试仪器设备、环境:小车,XCOM软件,附有黑线的普通、特殊赛道。

3调试结果:小车第一圈刚开始能够顺利地通过十字路口,在直角赛道有一些偏移,最后锐角也能顺利通过。但是第二圈时,小车通过第一个十字路口后,在第二个十字路口判断成了锐角进行了左转。在后面多次的测试中,小车还出现了无法判断直角赛道的情况,直接直行,锐角也有相应的状况发生,小车很难无失误多次跑圈。

4结果分析与结论:起初我们对于小车为什么出现这种情况真的是很头疼,不知道怎么去更改。但是在小组成员多天的测试后,我们认为轨道旁同学的影子,小车扫描的延迟,直行的稳定性,还有判定条件都是很粗糙的会对小车产生很大的影响。需要进一步去完善。在小车测试时,我们会让旁边的同学稍稍让开点,特别是在锐角这个地方。关于小车扫描的时间,我们发现时间长短会对小车判断锐角和十字路口产生不同的影响,所以,我们进行了多次的测试,终于找到了一个较为合适的时间延迟。使小车能顺利通过锐角,对于十字路口,能采集的确定数据进行直行。同时,对于特殊赛道,我们也完善了判定条件,使在弯道能做出正确的动作。更改代码后,小车能够破除一圈魔咒,进行多次跑圈,为了更完善,我们在接下来的几天再次进行了更多次的数据分析,使小车能够更加稳定。为了能在顺利跑圈的同时增加速度,我们也是不断去磨合了这个速度,使之达到更好的状态。最终小车能在较高速下跑完六七圈的成绩。

ti移动机器人设计报告相关推荐

  1. 2020年TI杯大学生电子设计大赛 无线运动传感器节点 作品开源( PCB、设备/服务器工程、文档、测试视频、设计报告)

    2021.5.1更新: 需要焊接晶振,程序默认使用的是外部晶振 2021.4.22更新: 正值毕业设计季,近期有不少毕设题目是本作品的学长学姐私信询问,由于博主备考,无法及时回复. 本作品还有不少待优 ...

  2. 移动机器人设计与实践-基础概念汇总

    如下全文在关键词提示词等脚本交互下,由文图版本生成式人工智能在1分钟内创作完成. AI自动生成文章评分已经远超大部分博文评分值. 人类社会经历过农业时代(最强代表汉唐)-工业时代(最强代表日不落帝国) ...

  3. 基于MSP432控制的红外循迹爬坡小车设计报告

    基于MSP432控制的红外循迹爬坡小车设计报告 竞赛选题:坡道行驶电动小车(C题) 摘要 本小车基于TI的MSP432平台,设计了可以沿指定路线在坡道上循迹行驶的四轮小车.小车采用L298N驱动芯片控 ...

  4. 简易数字式电阻、电容和电感测量仪设计报告

    写在前面:这是这次参加电子设计大赛我写的设计报告,但是我本人现在对硬件不是很熟悉,所以很对原理叙述不是很到位啊,不过整个作品用到知识点和原理都基本说清楚了. 简易数字式电阻.电容和电感测量仪设计报告 ...

  5. 扬州大学大一计算机课,扬州大学计算机硬件课程设计报告

    扬州大学计算机硬件课程设计报告 (11页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 计算机硬件技术基础课程设计课程名称:计算机硬件技术基础 ...

  6. 装载机工作机构的设计,手机充电器的模具设计,牛头刨床执行机构及部件设计,轮式移动机器人设计,智能车刀刃磨机机械结构设计,螺纹轴车削加工及数控车削机床仿真的研究,关节型机械手设计……

    装载机工作机构的设计(cad+pro+说明书) 履带拖拉机变速器改进设计 Ⅳ 手机充电器的模具设计(论文+DWG图纸) 牛头刨床执行机构及部件设计(说明书+CAD图纸+三维图+仿真录像) 机械手设计( ...

  7. c语言时钟加秒表报告,51单片机秒表计时器课程设计报告(含C语言程序)...docx

    - - PAGE # - - - PAGE # - XXXXX)学院 51单片机系统设计 课程设计报告 目:秒表系统设计 目: 专业.班级: 学生姓名: 学 号: 指导教师: [摘要] 本设计是一个秒 ...

  8. 红外遥感设计报告论文+电路原理图

    红外遥感设计报告论文+电路原理图 一.设计目标 设计一对红外遥控器和接收器,实现无线控制.遥控器自带按键,通过按键操作,能控制接收器输出信号(可用发光二极管发光或熄灭来指示). 论文+原理图+电路图下 ...

  9. java课设推荐,《Java程序设计》课程设计报告推荐.docx

    <Java程序设计>课程设计报告推荐 <Java程序设计>课程设计报告2015-2016学年 第一学期设计题目整数进制转换学生姓名邹晓刚学 号0专业班级信管1303指导教师 姜 ...

最新文章

  1. 英特尔宣布全新自动驾驶平台整合处理器和视觉芯片
  2. php中判断常量,变量,函数是否存在的方法示例
  3. 16 导出pcb各网络的布线长度_PCB原理图常见错误分析
  4. java中的内存分配原则
  5. 红米android4.4.2,新版红米Note配置升级详解:系统其实是基于Android 4.4.2
  6. 解释java程序所使用的命令是,Java程序的执行原理以及解释说明
  7. Halcon PDF文档(hdevelop_users_guide)学习总结之一
  8. android 转场动画 4.4,Android高级UI开发(二十七)Material Design之转场动画(一)
  9. AI企航58自动发帖软件图片视频教程
  10. 【多任务学习】多任务学习中的任务选择机制(Task Selection Policies for Multitask Learning)
  11. mac下Charles https抓包乱码,手机不能上网解决
  12. 微信内网页分享,分享者能看到分享的图片(描述),但被分享者无法看到
  13. java调用高德地图api_JAVA调用高德地图API实践
  14. Vue 开源项目库汇总
  15. 中心性算法的简单总结
  16. 【前端】CSS3、Canvas、SVG等5种方式实现水波纹波浪动画特效
  17. 华为OWS平台和HEC服务浅见
  18. Pytorch模型训练和模型验证
  19. 中国第一代程序员列传
  20. webcam包的使用介绍

热门文章

  1. 上海亚商投顾:沪指震荡反弹涨1.2% 中国移动创历史新高
  2. 怎么将电脑上的mp4文件转换成mp3格式
  3. 字节跳动教育业务怎么样_【字节跳动教育行政工资待遇怎么样】-看准网
  4. 《如何让你爱的人爱上你》-读书笔记
  5. 如何将Mac备份到外置硬盘?
  6. 在excel日期比对大小_如何在Excel中防止分组日期
  7. android 锁屏软件的软件的开机自启动
  8. 有一种银行叫生命银行
  9. 12.28黄金原油价格投资策略、黄金白银最新价格布局及指导
  10. oracle加了rownum后就很慢,rownum orderby非常慢