智能车电磁组完整程序
- 格式:doc
- 大小:101.50 KB
- 文档页数:18
电磁组智能车原理智能车技术是近年来科技领域的热门话题之一,其中电磁组智能车更是备受关注。
本文将详细介绍电磁组智能车的原理,以及其在实践中的应用。
一、电磁组智能车的工作原理电磁组智能车是一种基于电磁感应技术的智能交通工具。
它主要依靠车身上的电磁感应器,通过感知周围电磁场的变化来判断出前方障碍物的位置和距离。
其工作原理如下:1. 电磁感应器电磁感应器通常由多个磁场传感器组成,布置在车身的前端。
这些传感器可以感知到周围环境中的电磁场变化,并将这些变化转化为电信号。
2. 信号处理电磁感应器采集到的电信号将通过信号处理模块进行处理。
该模块会对信号进行放大、滤波和分析,从而提取出有用的信息。
3. 障碍物检测通过信号处理后,可以获得前方障碍物的位置和距离信息。
智能车的控制系统会根据这些信息判断前方是否存在障碍物,从而做出相应的行驶决策。
4. 行驶决策根据障碍物的位置和距离信息,智能车的控制系统将做出行驶决策。
当前方没有障碍物时,智能车可以保持匀速直行;当有障碍物出现时,智能车会自动减速或变换方向以避让。
二、电磁组智能车的应用电磁组智能车在交通领域具有广泛的应用前景,以下是一些典型的应用场景:1. 智能巡航电磁组智能车可以通过感知前方障碍物的位置和距离,实现智能巡航功能。
它能够根据道路情况自动控制车速,避免与其他车辆发生碰撞。
2. 自动泊车电磁组智能车的电磁感应器还能够感知到停车位周围的电磁场变化。
通过对这些变化进行分析,智能车可以准确地判断出停车位的位置和大小,从而实现自动泊车功能。
3. 避障导航电磁组智能车在进行导航时,可以通过电磁感应器感知到道路上的障碍物。
根据障碍物的位置和距离信息,智能车可以选择合适的行驶路径,避免与障碍物发生碰撞。
4. 特殊环境下的应用电磁组智能车的电磁感应器对于特殊环境下的感知也具有一定的优势。
例如,在较为黑暗的地下停车场中,智能车可以借助电磁感应器的辅助实现车辆的准确定位和导航。
智能循迹小车电磁组C语言源代码(stc12c5a芯片)#include#include#define FOSC 18432000L#define BAUD 9600#define ADC_POWER 0x80 //ADC power control bit 电源控制位#define ADC_FALG 0x10 //ADC complete flag 标志位#define ADC_START 0x08 //ADC start control bit 启动控制位#define ADC_SPEEDLL 0x00 //420 clocks#define ADC_SPEEDL 0x20 //280 clocks#define ADC_SPEEDH 0x40 //140 clocks#define ADC_SPEEDHH 0x60 //70 clockstypedef unsigned char BYTE;typedef unsigned int WORD;float bj1,bj2;int cg1,cg2,go;go=0x05; //电机驱动设为0101BYTE ch=0;void InitADC();void Delay(WORD n);void kongzhi();void PWM();void GetADCResult(BYTE ch);void main(){P0=0X00; //P0口的LED灯全亮InitADC(); //初始化ADIE=0xa0;PWM(); //调用PWM函数while(1){GetADCResult(ch); //读取AD值并赋值给变量kongzhi(); //调用控制函数}}void GetADCResult(BYTE ch) //读取AD的函数{ADC_CONTR &=!ADC_FALG;for(ch=0;ch<2;ch++){switch(ch){case 0: ADC_CONTR=0xe9; //定义P1.1为AD转换 1110 1001 _nop_();_nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FALG));ADC_CONTR&=~ADC_FALG; //清除falg位cg1=ADC_RES; //把传到P1.1口的AD值(二进制)赋值给cg1 break;case 1: ADC_CONTR=0xea; //定义P1.2口为AD转换1110 1010_nop_();_nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FALG));ADC_CONTR&=~ADC_FALG;cg2=ADC_RES; //把传到P1.2口的AD值(二进制)赋值给cg2 break;default: break;}}if(++ch>=2) ch=0;}void InitADC() //初始化AD函数{P1ASF=0XE7; // 1110 0111 //定义为AD转换的IO口P1M0=0xE7 ; // P1.7-P1.0:1110 0111P1M1=0xE7 ; // P1.7-P1.0:1110 0111ADC_RES=0;ADC_CONTR=0xe9;Delay(2);}void Delay(WORD n) //延时函数{WORD x;while(n--){x=5000;while(x--);}}void kongzhi(){bj1=((cg2*5/256)-(cg1*5/256)); //两个传感器所检测到的电压的差值bj2=((cg1*5/256)-(cg2*5/256));if((bj1<1)&&(bj2<1)) //全速{CCAP0H=0x08; //左轮CCAP1H=0x00; //右轮P3=go;}else if(bj1>4/3) //强左拐{CCAP0H=0x40; //左轮CCAP1H=0x00; //右轮P3=go;}else if(bj1>1&&bj1<4/3) //微左拐{CCAP0H=0x22; //左轮CCAP1H=0x00; //右轮P3=go;}else if(bj2>1&&bj2<4/3) //微右拐{CCAP0H=0x00; //左轮CCAP1H=0x18; //右轮P3=go;}else if(bj2>4/3) //强右拐{CCAP0H=0x00; //左轮CCAP1H=0x35; //右轮P3=go;}}void PWM(){CCON=0;CL=0;CH=0;CMOD=0X02;CCAP0H=CCAP0L=0X80;CCAPM0=0X42; //允许比较器功能、PWM脉宽输出CCAP1H=CCAP1L=0X80;PCA_PWM0=0x00; //组成9位P1.3PCA_PWM1=0x00; //组成9位P1.4CCAPM1=0X42;CR=1; //启动PCA计数器阵列}。
摘要本文以智能汽车为模型,基于电磁传感器,采用MC9S12XS128微控制器,构建自主寻迹控制系统.系统的硬件设计采用模块化的设计方法.主要包括:微控制器模块、电源模块、光电传感器模块、速度检测模块、舵机驱动模块,电机驱动模块。
系统的软件设计采用结构化程序设计方法。
从结构上看,软件程序主要包括以下几个部分:主体循环程序,增量式PID速度控制程序,中断服务程序,舵机控制算法程序,速度控制算法程序以及一些其他控制程序。
软件设计重点研究PID控制算法、PWM控制、模糊控制、闭环控制在该系统中的应用。
PID及PWM控制主要运用于电机的控制,模糊控制运用于道路信息的采集中,闭环控制系统是针对整个系统而构建的。
关键词:MC9S12XS128,电磁传感器,H桥,PID控制一、总体结构设计本模型车采用电感来判别跑道上的电磁引导线,通过MC9S12XS128单片机来控制模型车各个模块的工作。
路径识别系统电路由14个电感组成。
通过传感器的不同方位设计,来判断车的行进角度,速度加减,赛道预测等等。
路径识别模块会将当前采集到的一组信号值传递给微控制器。
转速测量模块采用光电编码器,安装在车尾部,用来测量模型车行驶过程中的瞬时速度。
测量出的瞬时速度将输入到单片机中,以帮助分析确定模型车下一步的速度、转角等。
为了能够及时设置调整一些重要的控制参数,如速度档位,需增加一个8路的拨码开关.总体设计分为控制系统设计、硬件设计、软件设计三大部分.1、控制系统设计智能车系统的控制结构是以微处理器为核心,车速控制器、直流电机和测速传感器构成一个闭环,该闭环的输入为路径判别后经模糊控制处理后的速度给定,输出直接驱动后轮;而舵机控制器构成一个控制系统通道,其输入为模糊处理后的路径转角偏差,输出直接控制前轮转向;最后以车体位置情况作为道路识别反馈控制器的输入,其输出直接与道路中心线参数比较从而构成一个大的闭环控制系统.在控制策略的选择方面,遵循以下几点原则:(1)对于驱动电机,必须使用闭环控制。
第五届飞思卡尔智能车电磁组获奖程序MC9S12XS128单片机、用前置线圈检测磁感线、用无线蓝牙采集数据、干簧管检测起跑线磁铁。
#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */#include <stdio.h>/****************************************************************************** ******一·全局变量声明模块******************************************************************************* ******/typedef unsigned char INT8U;typedef unsigned int INT16U;typedef int INT32;typedef struct {INT8U d; //存放这一次AD转换的值}DATA;/****************************************************全局变量声明区*****************************************************/DA TA data[6]={0}; //全局变量数组,存放赛道AD转换最终结果INT8U a[6][8]={0}; //全局变量用来存放赛道AD转换中间结果INT8U cross0,cross1; //记录十字叉线#define LED PORTA_PA7#define LED_CS PORTA_PA0byte START ;INT16U dianji0;//用来存放上次电机转速PWM,来判断是否减速#define duojmax 9200 //向左转向最大值#define duojmid 8400 //打在中间#define duojmin 7600 //向右转向最小值#define duojcs 8000;#define dianjmax 1200#define dianjmin 10#define dianjmid 600static INT8U look=0,look1=0;int road_change[100]={0}; //判断赛道情况数组int roat_change0;int *r_change0; //指向数组最后一位int *r_change1; //指向数组倒数第二位int sum_front=0,sum_back=0; //分别存储数组前后两部分的和INT16U waittime=0;INT8U choise; //读拨码开关数值/******************************速度测量参数定时********************************/#define PIT0TIME 800 //定时0初值:设定为4MS 测一次速度,采一次AD值#define PIT1TIME 1390 //定时1初值:设定为7ms定时基值/*******************************脉冲记数变量*******************************/ static INT16U PulseCnt;//最终的脉冲数/******************************电机PID变量*********************************/float speed_return_m ;struct {int error0;int error1;int error2;int speed;int chage;float q0,q1,q2,Kp,Kd,Ki;}static SpeedPid;/********************************速度变量设定*******************************/ INT8U speedmax ; //直道加速INT8U speedmin ; //急转弯刹车INT8U speedmid ; //弯道内部限速INT8U speedaveg ; //INT8U breaktime ; //刹车时间////////////////////////////////////////////////////////////////////////////#define speederror_min 2 //允许的最小误差static int NowSpeed;static int speed_control; //存储pid输出值static int speed_return;/*******************************舵机PID参数******************************/struct{int error0;int error1;int error2;int chage;float Kp,Kd,Ki;}PositionPid;int change;static INT16U angle_left [52]={8550,8562,8574,8586,8598,8610,8622,8634,8646,8658,8670,8682,8694,8706,8718,8730,8 742,8754,8766,8778,8790,8802,8814,8826,8838,8850,8862,8874,8886,8898,8910,8922,8934,894 6,8958,8970,8982,8994,9006,9018,9030,9042,9054,9066,9078,9090,9102,9114,9126,9138,9150,9 150};static INT16U angle_right[52]={8250,8238,8226,8214,8202,8190,8178,8166,8154,8142,8130,8118,8106,8094,8 082,8070,8058,8046,8034,8022,8010,7998,7986,7974,7962,7950,7938,7926,7914,7902,7890,787 8,7866,7854,7842,7830,7818,7806,7794,7782,7770,7758,7746,7734,7722,7710,7698,7686,7674,7 662,7650,7650};static INT16U *angle_l=angle_left ,*angle_r=angle_right;static INT16U angle_control=duojmid; //舵机PWM最终控制量static INT16U angle_control0=duojmid;static INT16U angle_control1=duojmid;static INT16U break_pwm=0;INT16U angle_return;/****************************lcd液晶显示变量定义**************************/#define LCD_DATA PORTB#define LCD_RS PORTA_PA4 //PA6#define LCD_RW PORTA_PA5 //PA7#define LCD_E PORTA_PA6 //PA7INT8U start[]={"WELCOME TO LZJTU"};INT8U date[]={"2011-3-15 TUS"};INT8U time[]={"00:00:00"};INT16U Counter=0;INT8U Counter0=0,select=0,min=0;INT8U Counter1=0;INT8U LCD_choice;/**************************标志变量区*************************************/INT8U stop_flag=0;INT8U start_flag=0;INT8U backflag=0;INT8U AD_start ;INT8U zhijwan=0 ;INT8U shizi=0;/****************************************************************************** ******二·初始化函数模块******************************************************************************* ******//**************************************************************1. 芯片初始化--------MCUInit()**************************************************************/void MCUInit(void){//////////////////////////////////////////////////////////////////////////////////////////// ********总线周期计算方法******** //// fBUS=fPLL/2 //// fvoc=2*foscclk*(synr+1)/(refdv+1) //// PLL=2*16M*(219+1)/(69+1)=96Mhz /////////////////////////////////////////////////////////////////////////////////////////////////CLKSEL=0X00;PLLCTL_PLLON=1; //锁相环控制SYNR = 0X40|0X05;REFDV =0X80|0X01;POSTDIV=0X00;while( CRGFLG_LOCK != 1); //等待锁相环时钟稳定,稳定后系统总线频率为24MHz CLKSEL_PLLSEL = 0x01; //选定锁相环时钟PLLCTL=0xf1; //锁相环控制//时钟合成fpllclk=2*foscclk*(synr+1)/(refdv+1)//synr=2;refdv=1;外部时钟foscclk=16mb//fpllclk=48mb 总线时钟24mb// CRGFLG=0x40; //时钟复位控制// CRGINT=0x00 ; //时钟复位中断使能// CLKSEL =0xc0; //时钟选择//COPCTL =0x00;// ARMCOP =0x00; //看门狗复位// RTICTL =0x00; //实时中断}/**************************************************************2. AD转换初始化--------ADCInit()**************************************************************/void ADCInit(void){A TD0CTL1=0x00;A TD0CTL2=0x40; //0100,0000,自动清除使能控制位,忽略外部触发//转换结束允许中断,中断禁止A TD0CTL3=0xA4; //0100,0100,转换序列长度为4;FIFO模式,冻结模式下继续转换A TD0CTL4=0x05; //00001000,8位精度,PRS=5,ATDCLOCK=BusClock(24mb)/(5+1)*2,约为2MHz,采样周期位4倍AD周期A TD0DIEN=0x00; //输入使能禁止}/**************************************************************3. PWM初始化--------PWMInit()**************************************************************/void PWMInit(void) //PWM初始化{//总线频率24mb//1. 选择时钟:PWMPRCLK,PWMSCLA,PWMSCLB,PWMCLKPWME=0x00; //PWM通道关闭PWMPRCLK=0x01; //00010011时钟源A=BusClockA/2=48M/2=24MB;//低位clockA:01,45;高位clockB:23,67 时钟源B=48/1=48MBPWMSCLA =2; //ClockSA=ClockA/2/2=24MB/4=6MBPWMSCLB =2; //ClockSB=ClockB/2/2=12MBHzPWMCLK =0xFF; //通道均级联,均用SA,SB ,且都为6MB//2. 选择极性:PWMPOLPWMPOL =0xff; //电机正反转寄存器(PWMPOL)起始输出为高电平//3. 选择对齐方式:PWMCAEPWMCAE=0x00; //输出左对齐//4.PWMCTL PWM控制寄存器PWMCTL=0xF0; //01,23,45,67通道都级连,输出风别由1,3,5,7口控制//5. 使能PWM通道; PWME//6. 对占空比和周期编程//周期计算公式:输出周期=通道时钟周期*(PWMPERX+1)//占空比:=(PWMPERYX+1)/(PWMPERX+1)//开始时刻应使舵机打直,电机不转//1.通道45用来控制舵机PWMPWMPER45=60000-1; //PWM01=6MB/(60000)=100HzPWME_PWME5 =0; //舵机PWM通道开//2.通道23用来控制电机PWM1,通道01用来作为电机PWM2PWMPER23=1200-1;//电机正转PWM周期初始化。
#include "common.h"#include "include.h"/*!* @brief main函数* @since v5.0*/float kp=0; //PI 调节的比例常数float ek=0; //偏差e[k]float ukl=0; //u[k]float ukr=0;int i=0;int j=0;int adjust; //调节器输出调整量int AD1[100];int AD2[100];int ad=0;int count=0;int sum1=0;int flag1=0;int flag2=0;void main(){// float kp; //PI 调节的比例常数// float ek; //偏差e[k]// float ukl; //u[k]// float ukr;// int i=0;// int j=0;// int adjust; //调节器输出调整量// int AD1[100];// int AD2[100];// int ad;// int count;// int sum;adc_init (ADC0_SE0);adc_init (ADC0_SE3);tpm_pwm_init(TPM0, TPM_CH3,50,750);tpm_pwm_init(TPM2, TPM_CH0,20000, 0);tpm_pwm_init(TPM2, TPM_CH1,20000, 2300);kp=5000;while(1){for(i=0;i<100;i++){AD1[i]=adc_once(ADC0_SE0, ADC_8bit);AD2[i]=adc_once(ADC0_SE3, ADC_8bit);}for(i=0;i<99;i++){for(j=0;j<98;j++){if(AD1[j]>AD1[j+1]){ad = AD1[j];AD1[j] = AD1[j+1];AD1[j+1] = ad;}}}for(count=10;count<90;count++){sum1 += AD1[count];}ukl =(sum1/80);sum1=0;for(i=0;i<99;i++){for(j=0;j<98;j++){if(AD2[j]>AD2[j+1]){ad = AD2[j];AD2[j] = AD2[j+1];AD2[j+1] = ad;}}}for(count=10;count<90;count++){sum1 += AD2[count];}ukr = (sum1/80);sum1=0;if(ukl<100&&ukr<100&&ukl>ukr&&flag1==0&&flag2==0){flag1=1;}else if(ukl<100&&ukr<100&&ukl<ukr&&flag1==0&&flag2==0){flag2=1;}else{if(ukl>115||ukr>115){flag1=0;flag2=0;}}if(flag1==1&&flag2==0){tpm_pwm_duty(TPM0, TPM_CH3, 850);}else if(flag1==0&&flag2==1){tpm_pwm_duty(TPM0, TPM_CH3, 630);}else{ek=(ukl-ukr)/(ukl*ukr);adjust=(int)(750+kp*ek);if(adjust>870){adjust=870;}if(adjust<630){adjust=630;}tpm_pwm_duty(TPM0, TPM_CH3, adjust);}}// Ki=KpT/Ti=0.8,微分系数Kd=KpTd/T=0.8,Td=0.0002,根据实验调得的结果确定这些参数}。
第七届“飞思卡尔”杯全国大学生智能汽车竞赛技术报告基于电磁传感器的两轮自平衡智能车路径识别控制系统学校:北京联合大学队伍名称:北京联合大学电磁二队参赛队员:李俊、刘佳鑫、郑川指导教师:潘峰、曲金泽关于技术报告和研究论文使用授权的说明本人完全了解第七届全国大学生“飞思卡尔”杯智能汽车竞赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委会和飞思卡尔半导体公司可以在相关主页上收录并公开参赛作品的设计方案、技术报告以及参赛模型车的视频、图像资料,并将相关内容编纂收录在组委会出版论文集中。
参赛队员签名:带队教师签名:日期:目录第一章引言 (2)1.1概述 (2)1.2技术报告结构 (3)第二章设计方案概述说明 (3)2.1设计思路及方案的总体说明 (3)2.2系统各模块实现简介 (4)第三章机械及硬件电路设计 (5)3.1机械设计 (5)3.1.1 电磁传感器的安装 (5)3.1.2 PCB主板的固定 (6)3.1.3 测速电路模块的安装 (7)3.1.4 差速的调节 (7)3.1.5 加速度计与陀螺仪的安装 (7)3.1.6 液晶与按键的安装 (8)3.2硬件电路设计 (9)3.2.1 电磁传感器的设计 (9)3.2.2 PCB主板的设计 (13)3.2.3 电源管理模块 (14)3.2.4 电机驱动 (14)3.2.5 陀螺仪电路 (15)第四章软件设计 (16)4.2主要算法及实现 (18)4.2.1 算法框图与控制函数关系 (18)4.2.2 主要控制函数说明 (21)4.3速度PID控制算法及其改进形式 (28)第五章开发调试过程及主要参数 (30)5.1开发工具 (30)5.2制作调试过程说明 (30)5.3智能车主要技术参数 (32)5.4存在问题及改进方法 (33)参考文献 (35)参考程序: (36)第一章引言1.1 概述在本届智能模型车竞赛中,根据组委会要求的具体要求,本队采用了标准的汽车模型、直流电机和可充放电电池制作出了一个能够自主识别电流为20KHz,50—150mA导线线路的智能车,能够在比赛跑道上自主识别道路方向,能够稳定行驶、保持较高的速度。
智能车电磁组完整程序一、引言智能车电磁组是智能车的重要组成部份,通过电磁感应技术实现对周围环境的感知和反应。
本文将详细介绍智能车电磁组的完整程序,包括硬件设备和软件算法。
二、硬件设备智能车电磁组所需的硬件设备主要包括以下几个部份:1. 电磁传感器:采用高精度电磁传感器,能够准确感知周围环境的电磁信号。
2. 控制器:使用嵌入式控制器,如Arduino或者Raspberry Pi,作为智能车的主控制单元,用于接收电磁传感器的数据并进行处理。
3. 机电驱动器:用于控制智能车的机电,根据电磁传感器的数据调整车辆的速度和方向。
4. 电源模块:提供电力供应,确保智能车电磁组正常运行。
三、软件算法智能车电磁组的软件算法主要包括以下几个方面:1. 数据采集:通过电磁传感器采集周围环境的电磁信号数据,包括强度和方向等信息。
2. 数据处理:对采集到的电磁信号数据进行处理,包括滤波、噪声消除等,以提高数据的准确性和稳定性。
3. 环境感知:根据处理后的电磁信号数据,判断周围环境的情况,如是否存在障碍物、障碍物的位置和距离等。
4. 决策与控制:根据环境感知结果,智能车电磁组会做出相应的决策和控制,调整车辆的速度和方向,以避免碰撞或者与目标物保持一定距离。
5. 数据存储与分析:将采集到的电磁信号数据进行存储和分析,以便后续的优化和改进。
四、程序流程智能车电磁组的程序流程如下:1. 初始化:对硬件设备进行初始化,包括电磁传感器、控制器、机电驱动器等。
2. 数据采集:通过电磁传感器采集周围环境的电磁信号数据。
3. 数据处理:对采集到的电磁信号数据进行处理,包括滤波、噪声消除等。
4. 环境感知:根据处理后的电磁信号数据,判断周围环境的情况。
5. 决策与控制:根据环境感知结果,智能车电磁组会做出相应的决策和控制,调整车辆的速度和方向。
6. 数据存储与分析:将采集到的电磁信号数据进行存储和分析。
7. 循环执行:以上步骤会循环执行,以实时感知和响应周围环境的变化。
#include <hidef.h> /* common defines and macros */#include "derivative.h" /* derivative-specific definitions */int left1=0;int left2=0;int right1=0;int right2=0;int AR_LEFT=0;//left2-right2int AR_RIGHT=0;int CR=0;//左边相加减右边相加int preCR=0;int ppreCR=0;int mkp=0;int mki=0;int mkd=0;int ideal_speed=0; //设定速度int speed=0;int s_ideal0[6]={75,80,42,42,42,42}; //普通道、长直道、普通到弯、长直道到弯、弯内、偏离黑线int s_ideal1[6]={70,75,42,42,42,42};int s_ideal2[6]={62,70,42,40,41,40};int s_ideal3[6]={54,66,42,40,41,40};int table_mkp0[6]={30,30,30,30,30,30}; //ni 16.31 ,shun 15.16int table_mkp1[6]={25,25,25,25,25,25};int table_mkp2[6]={5,4,4,20,20,20};int table_mkp3[6]={4,4,4,10,8,9}; //稳定速度int table_mki0[6]={0,0,20,20,20,20};int table_mki1[6]={0,0,20,20,20,20};int table_mki2[6]={0,0,0,10,10,20};int table_mki3[6]={0,0,0,0,0,0};int table_mkd0[6]={0,0,0,0,0,0};int table_mkd1[6]={0,0,0,0,0,0};int table_mkd2[6]={0};int table_mkd3[6]={0,0,0,0,0,0};int s_table[6];int b_mkp[6]=0;int b_mki[6]=0;int b_mkd[6]=0;int table_rkp0[7]={5,3,2,550,550,550,8};//普通道中间、长直道低速、长直道高速、普到弯、直到弯、弯、普通道两边int table_rkp1[7]={7,5,4,450,450,400,9};int table_rkp2[7]={6,3,2,150,150,150,9};int table_rkp3[7]={5,3,2,150,150,150,9};int table_rkd0[7]={0,0,0,400,400,400,100};int table_rkd1[7]={0,0,0,500,500,500,100};int table_rkd2[7]={0,0,0,200,300,400,100};int table_rkd3[7]={0,0,0,200,300,400,100};int b_rkp[7]=0;int b_rkd[7]=0;int rkp=0;int rkd=0;int f=0;// pwmDTY要加的值int pref=0;int Pulse_count=0; //脉冲数int ganhuang=0;unsigned int ting=0;int i=0;int Flag_Chute=0; //道路标志int GeneralCtn=0;int CurveCtn=0;int ChuteCtn=0;int WANCtn=0;int Flag_gaosu=0;unsigned char Flag_Pwm;//知道转弯道标志int flag=0;/***********************//PLL超频到40MHZ****************/void PLL_Init(void) {CLKSEL=0X00;PLLCTL_PLLON=1;REFDV=0X80|0X01;SYNR=0X40|0X04;POSTDIV=0X00;asm nop;asm nop;while(!(CRGFLG_LOCK==1));CLKSEL_PLLSEL=1;}//延时函数cnt*1ms;void delay(unsigned int cnt) {unsigned int loop_i,loop_j;for(loop_i=0;loop_i<cnt;loop_i++) {loop_j=0x1300;while(loop_j--);}}/*******************************///////////////\\计数程序//\\\\\\\\\\\\\\\*********************************/void PACBInit() //PT7 获得脉冲值{PACTL=0X40; //PT7 PIN,PACN32 16BIT,Rising edge,NOT INTERRUPTTCTL3=0x40; //c-输入捕捉7 上升沿有效,TIE_C7I=0; //通道7 禁止中断TIOS_IOS7=0; //每一位对应通道的: 0 输入捕捉,1 输出比较PACNT = 0;}void RTI_init(void) //RTI 产生10ms 的中断定时{asm sei; //关闭中断RTICTL=0xC7; //中断周期设置10ms 中断一次(或者让RTICTL=0x59<为10.24ms 定时>)CRGINT_RTIE=1; //实时中断有效,一旦RTIF=1 则发出中断请求asm cli; //开放中断}//舵机初始化void PWM_rudder_init(void) {PWME_PWME3=0;PWME_PWME2=0;PWMPRCLK_PCKB=2;//CLOCKB=BUS/4=10MHz PWMSCLB=2;//CLOCCSB=10/(2*2)=2.5MHzPWMCTL_CON23=1;//组合PWM23PWMCLK_PCLK3=1;//PWM3使用SBPWMPER23=50000;//写PWM23的周期寄存器,周期是20ms PWMPOL_PPOL3=1;//极性为正PWMCAE_CAE3=0;//左对齐PWME_PWME3=1;//使能PWM23}//电机初始化void PWM_init_motor(void){ //电机初始化PWME_PWME0=0;PWME_PWME1=0;PWMPRCLK_PCKA=2; //Clock A=40M/4=10MPWMPOL_PPOL1=1;//通道1 正极性输出PWMCLK_PCLK1=0;//通道1 选择A 时钟PWMCAE_CAE1=0;//左对齐PWMCTL_CON01=1;PWMPER01=1000;//输出频率=10M/1000=10KhzPWMDTY01=0;//通道1 占空比为100/250PWME_PWME1=1;//通道1 使能PWME_PWME4=0;PWME_PWME5=0;PWMPRCLK_PCKA=1; //Clock A=40M/2=20MPWMPOL_PPOL5=1;//通道5 正极性输出PWMCLK_PCLK5=1;//通道5 选择SA 时钟PWMSCLA=1; //ClockSB=20M/(2*1)=10M PWMCAE_CAE5=0;//左对齐PWMCTL_CON45=1;PWMPER45=1000;//输出频率=10M/1000=10KhzPWMDTY45=0;//初始通占空比0PWME_PWME5=1;//通道5 使能}void AD_Init(void){A TD0CTL1=0x20; //选择AD通道为外部触发,10位精度,采样前不放电A TD0CTL2=0x40; //标志位自动清零,禁止外部触发, 禁止中断A TD0CTL3=0xA0; //右对齐无符号,每次转换4个序列, No FIFO, Freeze模式下继续转A TD0CTL4=0x09; //采样时间为4个AD时钟周期,PRS=9,A TDClock=40/(2*(9+1))2MHz A TD0CTL5=0x30; //特殊通道禁止,连续转换4个通道,多通道转换,起始通道为0转换A TD0DIEN=0x00; //禁止数字输入}/************************/////////检测起跑线\\\\\\\\\\\*****************/void Checkstart(){asm sei;TIOS_IOS0=0; //输入捕捉TSCR1=0X80;TSCR2=0X07;TCTL4=0X01;//上升沿捕捉TIE=0X01; //允许硬件中断asm cli;}//拨码开关void boman(){if(PORTA_PA0==1) {b_rkp[0]=table_rkp0[0];b_rkp[1]=table_rkp0[1];b_rkp[2]=table_rkp0[2];b_rkp[3]=table_rkp0[3];b_rkp[4]=table_rkp0[4];b_rkp[5]=table_rkp0[5];b_rkp[6]=table_rkp0[6];b_rkd[0]=table_rkd0[0];b_rkd[1]=table_rkd0[1];b_rkd[2]=table_rkd0[2];b_rkd[4]=table_rkd0[4]; b_rkd[5]=table_rkd0[5]; b_rkd[6]=table_rkd0[6];b_mkp[0]=table_mkp0[0]; b_mkp[1]=table_mkp0[1]; b_mkp[2]=table_mkp0[2]; b_mkp[3]=table_mkp0[3]; b_mkp[4]=table_mkp0[4]; b_mkp[5]=table_mkp0[5];b_mki[0]=table_mki0[0]; b_mki[1]=table_mki0[1]; b_mki[2]=table_mki0[2]; b_mki[3]=table_mki0[3]; b_mki[4]=table_mki0[4]; b_mki[5]=table_mki0[5];b_mkd[0]=table_mkd0[0]; b_mkd[1]=table_mkd0[1]; b_mkd[2]=table_mkd0[2]; b_mkd[3]=table_mkd0[3]; b_mkd[4]=table_mkd0[4]; b_mkd[5]=table_mkd0[5];s_table[0]=s_ideal0[0];s_table[1]=s_ideal0[1];s_table[2]=s_ideal0[2];s_table[3]=s_ideal0[3];s_table[4]=s_ideal0[4];s_table[5]=s_ideal0[5];}if(PORTA_PA1==1) {b_rkp[0]=table_rkp1[0]; b_rkp[1]=table_rkp1[1]; b_rkp[2]=table_rkp1[2]; b_rkp[3]=table_rkp1[3]; b_rkp[4]=table_rkp1[4]; b_rkp[5]=table_rkp1[5]; b_rkp[6]=table_rkp1[6];b_rkd[1]=table_rkd1[1]; b_rkd[2]=table_rkd1[2]; b_rkd[3]=table_rkd1[3]; b_rkd[4]=table_rkd1[4]; b_rkd[5]=table_rkd1[5]; b_rkd[6]=table_rkd1[6];b_mkp[0]=table_mkp1[0]; b_mkp[1]=table_mkp1[1]; b_mkp[2]=table_mkp1[2]; b_mkp[3]=table_mkp1[3]; b_mkp[4]=table_mkp1[4]; b_mkp[5]=table_mkp1[5];b_mki[0]=table_mki1[0]; b_mki[1]=table_mki1[1]; b_mki[2]=table_mki1[2]; b_mki[3]=table_mki1[3]; b_mki[4]=table_mki1[4]; b_mki[5]=table_mki1[5];b_mkd[0]=table_mkd1[0]; b_mkd[1]=table_mkd1[1]; b_mkd[2]=table_mkd1[2]; b_mkd[3]=table_mkd1[3]; b_mkd[4]=table_mkd1[4]; b_mkd[5]=table_mkd1[5];s_table[0]=s_ideal1[0];s_table[1]=s_ideal1[1];s_table[2]=s_ideal1[2];s_table[3]=s_ideal1[3];s_table[4]=s_ideal1[4];s_table[5]=s_ideal1[5];}if(PORTA_PA2==1) {b_rkp[0]=table_rkp2[0]; b_rkp[1]=table_rkp2[1]; b_rkp[2]=table_rkp2[2]; b_rkp[3]=table_rkp2[3]; b_rkp[4]=table_rkp2[4]; b_rkp[5]=table_rkp2[5]; b_rkp[6]=table_rkp2[6];b_rkd[0]=table_rkd2[0]; b_rkd[1]=table_rkd2[1]; b_rkd[2]=table_rkd2[2]; b_rkd[3]=table_rkd2[3]; b_rkd[4]=table_rkd2[4]; b_rkd[5]=table_rkd2[5]; b_rkd[6]=table_rkd2[6];b_mkp[0]=table_mkp2[0]; b_mkp[1]=table_mkp2[1]; b_mkp[2]=table_mkp2[2]; b_mkp[3]=table_mkp2[3]; b_mkp[4]=table_mkp2[4]; b_mkp[5]=table_mkp2[5];b_mki[0]=table_mki2[0]; b_mki[1]=table_mki2[1]; b_mki[2]=table_mki2[2]; b_mki[3]=table_mki2[3]; b_mki[4]=table_mki2[4]; b_mki[5]=table_mki2[5];b_mkd[0]=table_mkd2[0]; b_mkd[1]=table_mkd2[1]; b_mkd[2]=table_mkd2[2]; b_mkd[3]=table_mkd2[3]; b_mkd[4]=table_mkd2[4]; b_mkd[5]=table_mkd2[5];s_table[0]=s_ideal2[0];s_table[1]=s_ideal2[1];s_table[2]=s_ideal2[2];s_table[3]=s_ideal2[3];s_table[4]=s_ideal2[4];s_table[5]=s_ideal2[5];}if(PORTA_PA3==1) {b_rkp[0]=table_rkp3[0]; b_rkp[1]=table_rkp3[1]; b_rkp[2]=table_rkp3[2]; b_rkp[3]=table_rkp3[3];b_rkp[4]=table_rkp3[4];b_rkp[5]=table_rkp3[5];b_rkp[6]=table_rkp3[6];b_rkd[0]=table_rkd3[0];b_rkd[1]=table_rkd3[1];b_rkd[2]=table_rkd3[2];b_rkd[3]=table_rkd3[3];b_rkd[4]=table_rkd3[4];b_rkd[5]=table_rkd3[5];b_rkd[6]=table_rkd3[6];b_mkp[0]=table_mkp3[0];b_mkp[1]=table_mkp3[1];b_mkp[2]=table_mkp3[2];b_mkp[3]=table_mkp3[3];b_mkp[4]=table_mkp3[4];b_mkp[5]=table_mkp3[5];b_mki[0]=table_mki3[0];b_mki[1]=table_mki3[1];b_mki[2]=table_mki3[2];b_mki[3]=table_mki3[3];b_mki[4]=table_mki3[4];b_mki[5]=table_mki3[5];b_mkd[0]=table_mkd3[0];b_mkd[1]=table_mkd3[1];b_mkd[2]=table_mkd3[2];b_mkd[3]=table_mkd3[3];b_mkd[4]=table_mkd3[4];b_mkd[5]=table_mkd3[5];s_table[0]=s_ideal3[0];s_table[1]=s_ideal3[1];s_table[2]=s_ideal3[2];s_table[3]=s_ideal3[3];s_table[4]=s_ideal3[4];s_table[5]=s_ideal3[5];}}/**************************////////赛道特征识别///////****************************/void Roadjudge(void){if(Flag_Chute==0) //普通弯道情况0{ GeneralCtn=0;CurveCtn=0;if(CR>=-23&&CR<=40) //此时对应一个车轮的内侧压线@@@@@@@@@@@@@@@@@@@@@@@@@@@@{ChuteCtn++;W ANCtn=0;}if(CR<-23||CR>40) { // @@@@@@@@@@@@@@@@@@@@@@@@@@if(CR<-85||CR>90){ //对应车轮的外侧压线@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ChuteCtn=0;W ANCtn++;}else {ChuteCtn=0;WANCtn=0;}}if(ChuteCtn>10000) // 300{Flag_Chute=1;}if(W ANCtn<-10000){Flag_Chute=2;}}if(Flag_Chute==1) //长直道情况 1{ChuteCtn=0;GeneralCtn=0;W ANCtn=0;if(CR>40)CurveCtn++; // 60 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@if(CR<-23)CurveCtn--; // -60 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@if(CurveCtn>1||CurveCtn<-1){if(Flag_gaosu==1) //高速时转入大弯道情况{Flag_Chute=2;}if(Flag_gaosu==0)Flag_Chute=0; //低速时转入普通弯道情况}}if(Flag_Chute==2) //大弯道情况 2{ChuteCtn=0;CurveCtn=0;W ANCtn=0; // @@@@@@@@@@@@@@@@@@@@@@@if(CR>-23&&CR<35)GeneralCtn++;else GeneralCtn=0;if(GeneralCtn>1300)Flag_Chute=0;//if(GeneralCtn>130)Flag_Ct=1;//else Flag_Ct=0;//if(k_abs(Turn_C-Turn<54)// {// Flag_Zhj=1;// }// else// {// Flag_Zhj=0;// }// if(Flag_Pwm==1&&Flag_Ct==1)Flag_Chute=1;}}/******************************\\\\\\\\\\\\\\\\\\\\//舵机控制\\\\\\\\\\\\\\\\\*********************************/void rudder_ctrl(void){if(Flag_Chute==0) //普通道{Flag_Pwm=0;if(CR<40&&CR>-23){rkp=b_rkp[0];rkd=b_rkd[0];}else{rkp=b_rkp[6];rkd=b_rkp[6];}}else if(Flag_Chute==1) //长直道{Flag_Pwm=1;if(Flag_gaosu==0) //disu{rkp=b_rkp[1]; //5rkd=b_rkd[1];}else //gaosu{rkp=b_rkp[2]; //4rkd=b_rkd[2];}}else if(Flag_Chute==2) //大弯道{if(Flag_Pwm==0) //普通道到大弯道{rkp=b_rkp[3];rkd=b_rkd[3];}else if(Flag_Pwm==1) //直道到大弯道{rkp=b_rkp[4];rkd=b_rkd[4];}else{rkp=b_rkp[5];rkd=b_rkd[5];}}f=3800+rkp*CR+rkd*(CR-2*preCR+ppreCR); //舵机的PID算式ppreCR=preCR;//计算之后向前推进赋值为下次计算做准备preCR=CR;}/***********************************\\\\\\\\\\\\电机控制\\\\\\\\\\\\\\\\\\************************************/void motor_ctrl1(void){if(Flag_Chute==0) //普通道{Flag_Pwm=0;mkp=b_mkp[0];mki=b_mki[0];mkd=b_mkd[0];ideal_speed=s_table[0];}else if(Flag_Chute==1) //长直道{Flag_Pwm=1;// Flag_PIDRev=0;mkp=b_mkp[1];mki=b_mki[1];mkd=b_mkd[1];ideal_speed=s_table[1];}else if(Flag_Chute==2) //大弯道{if(Flag_Pwm==0) //普通道进大弯道{mkp=b_mkp[2];mki=b_mki[2];mkd=b_mkd[2];ideal_speed=s_table[2];}else if(Flag_Pwm==1) //直道进大弯道{mkp=b_mkp[3];mki=b_mki[3];mkd=b_mkd[3];ideal_speed=s_table[3];}else{mkp=b_mkp[4];mki=b_mki[4];mkd=b_mkd[4];ideal_speed=s_table[4];}Flag_Pwm=2;}}//电机控制void motor_ctrl2(void){int error,m_perror,m_ierror,m_derror;int pre_error=0;int ppre_error=0;error=ideal_speed-Pulse_count;m_perror = error - pre_error;m_ierror=error;m_derror=error-2*pre_error+ppre_error;ppre_error=pre_error;pre_error=error;speed+=mkp*m_perror + mki*m_ierror + mkd*m_derror; //速度PID控制算式if(speed>=9000) speed=9000;if(speed<=-4000) speed=-4000;if(speed>=0){PWMDTY45=0;PWMDTY01=(int)speed/10;}else{PWMDTY45=(int)(-speed)/10;PWMDTY01=0;}}//主函数//void main(void) {DisableInterrupts;PWMDTY23=3800;PLL_Init();DDRA=0X00;//输入boman();PACBInit();RTI_init();PWM_rudder_init();PWM_init_motor();AD_Init();DDRB=0XFF;//输出PORTB=0X03;//1号与2号灯亮delay(5000); //4000 3s左右PORTB=0xFC;//3号与4号灯亮Checkstart();EnableInterrupts;/* put your own code here */for(;;) {while(!ATD0STA T2_CCF0); // 等待转换结束while(ATDOSTA T2_CCF0==1)left1=ATD0DR0;//读取结果寄存器left1的值while(!ATD0STAT2_CCF2); // 等待转换结束while(ATDOSTAT2_CCF1==1) left2=ATD0DR2;//读取结果寄存器的值while(!ATD0STAT2_CCF1); // 等待转换结束while(ATDOSTAT2_CCF2==1) right1=ATD0DR1;//读取结果寄存器的值while(!ATD0STAT2_CCF3); // 等待转换结束while(ATDOSTAT2_CCF3==1)right2=ATD0DR3;//读取结果寄存器的值AR_LEFT=left1+left2;AR_RIGHT=right1+right2;CR=(AR_RIGHT-AR_LEFT)/10;if(Pulse_count>65)Flag_gaosu=1;else Flag_gaosu=0;if(AR_RIGHT<110||AR_LEFT<95)//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ left93 {if(pref>3800) //if(AR_RIGHT<110)f=4500; //f=3100;if(pref<3800) //if(AR_LEFT<95)f=3100; //f=4500;mkp=b_mkp[5];mki=b_mki[5];mkd=b_mkd[5];ideal_speed=s_table[5];}else{Roadjudge(); //先对道路进行判断rudder_ctrl(); //调整舵机motor_ctrl1(); //调整电机的pid参数}if(f>4500)f=4500;if(f<3100)f=3100;PWMDTY23=f;pref=PWMDTY23;motor_ctrl2();}} /* loop forever */#pragma CODE_SEG __NEAR_SEG NON_BANKEDinterrupt 7 void Int_TimerOverFlow(void){Pulse_count= PACNT; //脉冲计数赋值PACNT = 0X0000;CRGFLG_RTIF=1;if(ting<1100)ting++;else ting=1100;}interrupt VectorNumber_Vtimch0 void stop(void){DisableInterrupts;TFLG1_C0F=1; //清除中断标志位//PORTB=0X03;//1号与2号灯亮// delay(20);// PORTB=0xFC;//3号与4号灯亮// ganhuang++;//if(ganhuang%4==0){// ganhuang=0;//PORTB=0xFC;//3号与4号灯亮//ganhuang=0;//TIE=TIE&0X0FE;flag=1;if(ting==1100){flag=2;PORTB=0xF6;for(i=0;i<3000;i++){while(!ATD0STA T2_CCF0); // 等待转换结束while(ATDOSTA T2_CCF0==1)left1=ATD0DR0;//读取结果寄存器left1的值while(!ATD0STAT2_CCF2); // 等待转换结束while(ATDOSTAT2_CCF1==1) left2=ATD0DR2;//读取结果寄存器的值while(!ATD0STAT2_CCF1); // 等待转换结束while(ATDOSTAT2_CCF2==1) right1=ATD0DR1;//读取结果寄存器的值while(!ATD0STAT2_CCF3); // 等待转换结束while(ATDOSTAT2_CCF3==1) right2=ATD0DR3;//读取结果寄存器的值AR_LEFT=left1+left2;AR_RIGHT=right1+right2;CR=(AR_RIGHT-AR_LEFT)/10;rkp=9;rkd=0;f=3800+rkp*CR+rkd*(CR-preCR);preCR=CR;if(f>4500)f=4500;if(f<3100)f=3100;PWMDTY23=f;pref=PWMDTY23;//mkp=20;//mki=0;//mkd=0;//ideal_speed=0;//motor_ctrl2();PWMDTY01=0;PWMDTY45=0;delay(2);}}EnableInterrupts;}// asm cli;#pragma CODE_SEG DEFAULT//结论3800中间;3100(-700)左打死,4500(700)右打死//7.11当右边两个相加小于40时往左打死,此时左车轮大概偏黑线2cm,当左边两个相加小于100时右打死//此时右轮偏2cm。