1. 程式人生 > >嵌入式小專案練習-光電設計競賽-尋跡小車-03-尋跡演算法分析與原始碼

嵌入式小專案練習-光電設計競賽-尋跡小車-03-尋跡演算法分析與原始碼

這裡我用了三個光敏電阻的感測器來進行尋跡:這裡用X1,X2,X3(檢測到了為0)來表示:

演算法思路:

將三個感測器放置如圖:         |          |          |

1)直行:X1=1;X2=0;X3=1;

2)左轉:X1=0;X2=1;X3=1;

3)右轉:X1=1;X2=1;X3=0;

4)直角左轉:X1=0;X2=0;X3=1;

5)直角右轉:X1=1;X2=0;X3=0;

其他情況慢慢後退:這樣提高了小車的容錯性,如果一旦出現尋跡亂碼的情況(這裡指未出現的組合數如:X1=1 X2=0 X3=1)

演算法思路很簡單主要看小車尋跡的賽道,程式碼中的pwm的寬度是隨意設定的,具體什麼樣的彎道角度需要耐心除錯,反覆試驗。

main.c

#include <reg52.h>
#include <pwm.h>

#define u8 unsigned char
#define u16 unsigned int

//光學開關模組
sbit LS=P2^3;

//接尋跡模組
#define fin_1   P3^6	
#define fin_2	P3^7	 
#define fin_3   P3^5  

void main()
{
    P1=0X00;   //關電機	
    TMOD=0X01;
    TH0= 0XFc;		  //1ms定時
    TL0= 0X18;
    TR0= 1;
    ET0= 1;
	EA = 1;			   //開總中斷
    while(1)
    {
        if(LS==1)
        {    
            if(fin_1==1&&fin_2==0&&fin_3==1)
                run();
            else if(fin_1==1&&fin_2==1&&fin_3==0)
                right();
            else if(fin_1==0&&fin_2==1&&fin_3==1)
                left();
            else if(fin_1==1&&fin_2==0&&fin_3==0)
                right_90();
            else if(fin_1==1&&fin_2==0&&fin_3==0)
                left_90();
            else
                back();
        }
        else
        {
            P0=0X00;   //關電機
        }

    } 
}

pwm.h檔案:

#ifndef  _PWM_H
#define  _PWM_H
#include <reg52.h>

//定義小車驅動模組輸入IO口 
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^2;
sbit IN4=P1^3;

//pwm端使能位:
sbit Left_pwm=P1^6;	 //PWM訊號端
sbit Right_pwm=P1^7;	 //PWM訊號端

//小車驅動接線定義 	
void Left_moto_go();      //左電機向前走
void Left_moto_back();   	//左邊電機向後轉
//void Left_moto_Stop();      //左邊電機停轉                     
void Right_moto_go();    	//右邊電機向前走
void Right_moto_back();   	//右邊電機向後走
//void Right_moto_Stop();     //右邊電機停轉

//左電機調速  調節push_val_left的值改變電機轉速,佔空比
extern void pwm_out_left_moto(void);
extern void pwm_out_right_moto(void);

//調速模組
extern void run();
extern void left_90();
extern void right_90();
extern void left();
extern void right();
extern void back();

#endif

pwm.c檔案

#include <reg52.h>
#include <pwm.h>
unsigned char pwm_left=0;//變數定義
unsigned char push_left=0;// 左電機佔空比N/100
unsigned char pwm_right=0;	
unsigned char push_right=0;// 右電機佔空比N/100
unsigned  int  time=0;
void Left_moto_go()
{
    IN1=1;
    IN2=0;
    }  
void Left_moto_back()
{
    IN1=0;
    IN2=1;
} 	
/*
void Left_moto_Stop()   
{
    IN1=0;
    IN2=0;
}
*/                      
void Right_moto_go()     
{
    IN3=1;
    IN4=0;
}	
void Right_moto_back()   
{
    IN3=0;
    IN4=1;
}
/*	
void Right_moto_Stop()   
{
    IN3=0;
    IN4=0;
} 
*/ 
//左電機調速  調節push_val_left的值改變電機轉速,佔空比
void pwm_out_left_moto(void)
{  
    if(pwm_left <= push_left)
	       {
		        Left_pwm = 1; 
		   }
	else 
	       {
	         Left_pwm = 0;
		   }
	if(pwm_left>100)
	       pwm_left=0;
}
//右電機調速                                    
void pwm_out_right_moto(void)
{  
    
    if(pwm_right>100)
	       pwm_right=0;
    if(pwm_right<=push_right)
    {
	    Right_pwm = 1; 
    }
	else 
	{
         Right_pwm =0;
    } 
}
//前進
void run(void)
{
    push_right=80;
    push_left=80;
    Left_moto_go();
    Right_moto_go();
}

//左轉直角
void left_90(void)
{
    push_right=50;
    push_left=80;
    Left_moto_go();
    Right_moto_back();     
}

//右轉直角
void right_90(void)
{
    push_right=80;
    push_left=50;
    Right_moto_go();
    Left_moto_back();
}

//左轉微調
void left(void)
{
    push_right=80;
    push_left=60;
    Left_moto_go();
    Right_moto_go();
}


//右轉微調
void right(void)
{
    push_right=80;
    push_left=60;
    Right_moto_go();
    Left_moto_go();
}
//後退
void back(void)
{
    push_right=20;
    push_left=20;
    Left_moto_back();
    Right_moto_back();
}
// TIMER0中斷服務子函式產生PWM訊號
void timer0()  interrupt 1 using 2
{
     TH0=0XFc;	  //1Ms定時
	 TL0=0X18;
	 time++;
	 pwm_left++;
	 pwm_right++;
	 pwm_out_left_moto();
	 pwm_out_right_moto();
}