自動循跡功能現實
一,硬件描述
1、循跡模塊五路黑線檢測,黑線反饋低電平
2、小車行駛速度通過PWM控制,現實無極調速。因爲開發板以及小車自重太重佔空比太低的時候下車無法驅動
3、小車馬達減速裝置不夠,小車無法現實太高速度移動。
4、小車方向打太大的時候無法移動。
5、舵機通過週期爲20ms不同佔空比的方波控制轉向
二、循跡思路
傳感器各種情況舵機處理方式:
因爲車身過大以及不能進行大拐彎,所以轉不過去的時候先反向倒車4.5秒
三,源代碼
1、主程序加了一段外部中斷,通過開發板按鍵來進行模式切換
static u8 mode = 0; //操作模式,0:紅外遙控,1:自動循跡,2,app藍牙控制
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
delay_init();
KEY_Init(); // 按鍵端口初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能複用功能時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//GPIOE.3 中斷線以及中斷初始化配置 下降沿觸發 //KEY1
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式 中斷
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能
EXTI_InitStructure.EXTI_Line=EXTI_Line3; //中短線 KEY1按鍵PE3口對應3線
EXTI_Init(&EXTI_InitStructure); //根據EXTI_InitStruct中指定的參數初始化外設EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //使能按鍵KEY1所在的外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //搶佔優先級2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子優先級1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器
}
//外部中斷3服務程序
void EXTI3_IRQHandler(void)
{
delay_ms(10);//消抖
if(KEY1==0) //按鍵KEY1 KEY1用來切換控制模式
{
// LCD_Clear(WHITE); //清空顯示屏
LED1=!LED1;
mode++;
if(mode==3)mode=0;
}
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中斷標誌位
}
u8 GetMode(void){
return mode;
}
2、循跡程序
LCD_Clear(WHITE); //LCD清屏
pwm_sudu = 8000;
led0pwmval = Z_qian;
TIM_SetCompare4(TIM3,pwm_sudu);
while(mode1 == 1){ //模式2,自動循跡模式
PGout(13) = 1;
PGout(14) = 0;
Show_Str(30,30,200,16,"循跡小車循跡調試界面",16,0);
POINT_COLOR=RED;
Show_Str(30,70,200,16,"傳感器反饋值(1-5):",16,0);
Show_Str(30,110,200,16,"當前舵機pwm值:",16,0);
Show_Str(30,130,200,16,"當前速度pwm值:",16,0);
POINT_COLOR=BLUE;
if((LEDKEY5 == 0) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1)){
led0pwmval = 1080;
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu-1500);
flagkeyled = 5;
while((LEDKEY3 == 1) && !((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1))){
LCD_ShowNum(30+8*2,90,LEDKEY1,1,16);
LCD_ShowNum(30+8*5,90,LEDKEY2,1,16);
LCD_ShowNum(30+8*8,90,LEDKEY3,1,16);
LCD_ShowNum(30+8*11,90,LEDKEY4,1,16);
LCD_ShowNum(30+8*14,90,LEDKEY5,1,16);
}
}
else if((LEDKEY5 == 1) && (LEDKEY4 == 0) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1)){
led0pwmval = 1100;
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu);
flagkeyled = 4;
}
else if((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 0) && (LEDKEY2 == 1) && (LEDKEY1 == 1)){
led0pwmval = Z_qian;
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu);
flagkeyled = 3;
}
else if((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 0) && (LEDKEY1 == 1)){
led0pwmval = 1300;
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu);
flagkeyled = 2;
}
else if((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 0)){
led0pwmval = 1320;
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu-1500);
flagkeyled = 1;
while((LEDKEY3 == 1)&& !((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1))){
LCD_ShowNum(30+8*2,90,LEDKEY1,1,16);
LCD_ShowNum(30+8*5,90,LEDKEY2,1,16);
LCD_ShowNum(30+8*8,90,LEDKEY3,1,16);
LCD_ShowNum(30+8*11,90,LEDKEY4,1,16);
LCD_ShowNum(30+8*14,90,LEDKEY5,1,16);
}
}else if((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1)){
switch(flagkeyled){
case 5: { //車身較長,如果彎道弧度過大即使打死方向也轉不過彎道
if(flagkeyled != 0){ //黑線出了所有檢測點,打反方向盤倒車4.5秒
flagkeyled = 0;
PGout(13) = 0;
PGout(14) = 0;
delay_ms(100);
led0pwmval = 1250;
TIM_SetCompare4(TIM3,pwm_sudu-2000);
TIM_SetCompare2(TIM3,led0pwmval);
PGout(13) = 0;
PGout(14) = 1;
delay_ms(4500);
led0pwmval = 1050;
TIM_SetCompare2(TIM3,led0pwmval);
PGout(13) = 1;
PGout(14) = 0;
delay_ms(2500);
while((LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1) && !((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1))){
LCD_ShowNum(30+8*2,90,LEDKEY1,1,16);
LCD_ShowNum(30+8*5,90,LEDKEY2,1,16);
LCD_ShowNum(30+8*8,90,LEDKEY3,1,16);
LCD_ShowNum(30+8*11,90,LEDKEY4,1,16);
LCD_ShowNum(30+8*14,90,LEDKEY5,1,16);
} //每次倒車之後,等待中間檢測到黑線再開始運行檢測程序
}
}break;
case 1: {
if(flagkeyled != 0){ //黑線出了所有檢測點,打反方向盤倒車4.5秒
flagkeyled = 0;
PGout(13) = 0;
PGout(14) = 0;
delay_ms(100);
led0pwmval = 1150;
TIM_SetCompare4(TIM3,pwm_sudu-2000);
TIM_SetCompare2(TIM3,led0pwmval);
PGout(13) = 0;
PGout(14) = 1;
delay_ms(4500);
led0pwmval = 1350;
TIM_SetCompare2(TIM3,led0pwmval);
PGout(13) = 1;
PGout(14) = 0;
delay_ms(2500);
while((LEDKEY3 == 1) && (LEDKEY4 == 1) && (LEDKEY5 == 1) && !((LEDKEY5 == 1) && (LEDKEY4 == 1) && (LEDKEY3 == 1) && (LEDKEY2 == 1) && (LEDKEY1 == 1))){
LCD_ShowNum(30+8*2,90,LEDKEY1,1,16);
LCD_ShowNum(30+8*5,90,LEDKEY2,1,16);
LCD_ShowNum(30+8*8,90,LEDKEY3,1,16);
LCD_ShowNum(30+8*11,90,LEDKEY4,1,16);
LCD_ShowNum(30+8*14,90,LEDKEY5,1,16);
}//每次倒車之後,等待中間檢測到黑線再開始運行檢測程序
}
}break;
}
}
LCD_ShowNum(30+8*2,90,LEDKEY1,1,16);
LCD_ShowNum(30+8*5,90,LEDKEY2,1,16);
LCD_ShowNum(30+8*8,90,LEDKEY3,1,16);
LCD_ShowNum(30+8*11,90,LEDKEY4,1,16);
LCD_ShowNum(30+8*14,90,LEDKEY5,1,16);
LCD_ShowNum(30+8*16,110,led0pwmval,4,16);
LCD_ShowNum(30+8*16,130,pwm_sudu,4,16);
mode1 = GetMode();
}