搜档网
当前位置:搜档网 > 遥控智能小车(课程设计)

遥控智能小车(课程设计)

《嵌入式系统原理》

课程设计说明书

题目:遥控智能小车

院(系):计算机与电子系

专业班级:电子科学与技术0902班

学生姓名:黄占威

学号:20091185045

指导教师:黄向宇

20 11 年 12 月 30 日至20 12 年 1 月 13 日

华中科技大学武昌分校制

嵌入式系统原理课程设计任务书

遥控智能小车(课程设计)

遥控智能小车(课程设计)

遥控智能小车(课程设计)

目录

1. 总体思想 (1)

2. 电机驱动 (2)

2.1 简介 (2)

2.2 具体实现 (2)

2.3 功能函数设计 (2)

3.遥控系统 (7)

3.1 遥控器简介 (7)

3.2 接收探头与解码 (7)

3.3 红外控制 (8)

4. 超声波 (12)

4.1 简介 (12)

4.2 超声波测距具体实现 (12)

4.3 超声波程序设计 (12)

5. 红外寻迹 (14)

5.1 反射式红外传感器 (14)

5.2 具体实现方法 (14)

5.3 寻迹程序设计 (15)

6. 总结 (17)

1.总体思想

遥控智能小车(课程设计)

图 1.1 设计全局图

本次课程设计,我们小组采用stm32作为主控芯片,L298N模块作为电机驱动芯片。在小车车头放置三个反射式红外传感器,由于红外光易于被黑线吸收,利用这个原理,来检测黑线,当检测到黑线时,发射出去的红外光被吸收,红外传感器接受不到反射信号,通过输出信号反馈给STM32,产生中断,作出相应的调整,详细介绍见下文第12页。

车头部分采用一个US-100超声波模块,用于检测前方障碍物,我们小组设置的安全距离为25cm,当小车与前方障碍之间的距离小于25cm时,小车蜂鸣器报警,stm32控制电机,作出相应的调整。关于超声波工作详情,请见下文第11页。

小车尾部安装一枚HS0038红外接收探头,配合一块遥控器,实现遥控小车的功能。

我们小组选用的遥控器编码为NEC协议。红外遥控功能详情,请见下文第7页。

我们在小车的车身上放置一块3.2寸TFT液晶显示器。用于显示时间,车速。车速通过霍尔元件测得。

2.电机驱动

2.1简介

电机运转需要大电流,而stm32驱动能力达不到电机正常运转的要求,故我们小组采用L298N模块驱动电机,L298N拥有4个输入端口,由stm32直接输入,4个输出端,可以驱动两个直流电机。s tm32输出端口的电平变换,可以控制电机的方向。PWM脉宽调制信号,可以控制电机的转速。实现加速减速的功能。

2.2 具体实现

通过stm32的PA0,PA1,根据TIM2产生的不同占空比的PWM波,控制电机的速度,以及正反转。PA3,PA4控制小车前轮,前轮采用舵机控制,在转向方面,不能大幅度转弯,所以,在小车转弯上,我们采用转一段时间,然后倒退一段距离,然后再转,如此反复几次。通过这种方式实现小车的900C转弯。

2.3 功能函数设计

1.void Front()

{

GPIOD->BRR = 0X03;

GPIOA_Conf(); //配置A端口

GPIOA->BRR = 0x0f;

GPIOA->BSRR = 0X01;

}

调用这个函数,实现小车全速向前形式。PD端口的D0,D1位,是控制小车后面两个尾灯。当小车前进时,尾灯关闭。

2.void Back()

{

GPIOD->BSRR = 0x03;

GPIOA_Conf();

GPIOA->BRR = 0x0f;

GPIOA->BSRR = 0X02;

}

调用这个函数,实现小车全速后退。同时开启车身后面的尾灯。

3 . void LeftSlideFront()

{

GPIOD->BSRR = 0X01;

GPIOD->BRR = 0X02;

GPIOA->BRR = 0X04;

GPIOA->BSRR = 0X08;

Time_Configuration(350,0,500,7199);

}

调用此函数,实现小车前进,左转弯。同时开启尾部左边的尾灯,关闭右边的尾灯。Time_Configuration(350,0,500,7199)为占空比调制函数。通过输入不同的值,改变电机的转速。

4.void Time_Configuration(uint16_t CCR1_Val,uint16_t CCR2_Val,uint16_t periodValue,uint16_t PrescalerValue)

{

/*开启TM2定时器时钟*/

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/*TIM2定时器复用管脚PA0,PA1,PA2,PA3*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/*配置定时器时基*/

TIM_TimeBaseStructure.TIM_Period = periodValue;

TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/*配置定时器各通道情况*/

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = CCR1_Val;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC1Init(TIM2, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

TIM_OC2Init(TIM2, &TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_ARRPreloadConfig(TIM2, ENABLE);

TIM_Cmd(TIM2, ENABLE);

}

PWM脉宽调制波形输出,是stm32定时器功能的一大亮点,以往8位单片机输出PWM 波形,均为模拟,或者借助外围芯片,而stm32内部定时器,实现了精确的PWM波形直接输出。上面功能函数,为TIM2定时器的配置情况。我在使用时,开启了TIM2定时器的通道1和通道2。分别为PA0,PA1,这两个端口控制小车的后轮电机。由于前轮为舵机。所以,没有采用PWM波形。而是直接给高低电平调整小车的方向。stm32定时器采用预分频处理,即将系统时钟分频后给定时器,这个预分频值,由传入的参数PrescalerValue决定。系统时钟为72MHz,设分频后的频率为F,则:

F = 72MHz/(PrescalerValue+1)

定时器的计数周期为传入参数periodValue的值决定。PWM占空比值由传入参数

CCR1_Val和CCR2_Val决定,分别控制PA0,PA1的占空比值。

占空比 = CCR1_Val/periodValue。

4.void LeftSlideBehind()

{

GPIOD->BSRR = 0X01;

GPIOD->BRR = 0X02;

GPIOA->BRR = 0X04;

GPIOA->BSRR = 0X08;

Time_Configuration(0,350,500,7199);

}

调用此函数,控制小车后退并左转弯。同时开启左边尾灯,关闭右边尾灯。

5.void RightSlideFront()

{

GPIOD->BSRR = 0X02;

GPIOD->BRR = 0X01;

GPIOA->BRR = 0X08;

GPIOA->BSRR = 0x04;

Time_Configuration(350,0,500,7199);

}

调用此函数,控制小车前进并右转弯。同时关闭左边尾灯,开启右边尾灯。

6.void RightSlideBehind() //后退,右转弯

{

GPIOD->BSRR = 0X02;

GPIOD->BRR = 0X01;

GPIOA->BRR = 0X08;

GPIOA->BSRR = 0X04;

Time_Configuration(0,350,500,7199);

}

调用此函数,控制小车后退并右转弯。同时关闭左边尾灯,开启右边尾灯。

7.void Upshift()

{

uint16_t i;

GPIOD->BRR = 0x03;

for(i = 100;i <= 180;i = i + 10)

{

Delay(200);

Time_Configuration(i,0,500,7199);

}

while(i <= 500)

{

i = i + 50;

Time_Configuration(i,0,500,7199);

Delay(100);

}

}

调用此函数,实现小车的加速,我们小组将加速过程分为2级,第一级为慢加速,让速度慢慢起来,第二级加速为快加速,当速度达到一定值后,占空比增大的幅度加强。

8.void SlowDown()

{

uint16_t i = 400;

GPIOD->BSRR = 0X03;

while(i > 200)

{

Time_Configuration(i,0,500,7199);

i = i-50;

Delay(70);

}

for(;i > 170; i = i - 5)

{

Time_Configuration(i,0,500,7199);

Delay(80);

}

}

调用此函数,实现小车的减速,减速过程,我们也分为两级。第一级为快速减速,第二级为慢速减速。使小车平稳减速。

9.void Brake()

{

GPIOD->BSRR = 0x03;

GPIOA_Conf();

GPIOA->BSRR = 0x0f;

}

调用该函数,小车将停止。同时后面尾灯开启。

3.遥控系统

3.1 遥控器简介

我们小组使用的遥控器发射编码为NEC协议,NEC编码协议中,遥控器每发送一个8位数据,可以分为5个部分:

遥控智能小车(课程设计)

图 3.1 NEC协议编码规则

当按下遥控器上的任意一个键时,遥控器将发送一个38KHz的载波信号,根据NEC编码协议,如果发送数据位为1,则向外发送38KHz的载波信号,持续发送0.56ms.然后停止发送1.685ms后继续发送下一位。如果发送数据位为0,则红外遥控向外发送38KHz的载波信号,持续发送0.56ms,然后停止发送0.565ms后继续发送下一位。

3.2 接收探头与解码

接受红外信号部分,我们采用HS0038接收探头,HS0038共三个引脚,分别为,OUT、VCC、GND。通电后,当没有收到红外信号时,OUT端口默认为高电平。接受端口信号与红外遥控发送信号电平相反。

在解码方面,接收探头接受到38KHz的载波后,输出端OUT电平拉低。由于NEC发射编码中,采用的是38KHz载波表示高,无发射表示低。所以在接受探头部分的电平高低,与发射部分刚好相反。解码部分,数据1,0的电平宽度为别是:

遥控智能小车(课程设计)

图 3.2 NEC协议1、0电平宽度

由于每个数据位开始低电平均为0.56ms,所以,我们使用TIM3定时器,准确捕获到每位数据高电平持续时间。通过捕获到的值,来确认1和0.

通过软件解码时,首先接受到引导码,9ms的低电平和4.5ms的高电平,然后是地址码和地址反码,最后是数据码和数据反码。在程序设计上,我们定义个unsigned char 型数组,分别记录下地址码、地址反码、数据码、数据反码。取出数组下标为2和3的

值,将下标为3的数组数据取反,判断是否相等,如果不相等,表示解码数据有误;如果相等,表示解码正确。

3.3 红外控制

将stm32的外部中断3端口与红外探头的输出端相连,捕捉红外遥控发射来的信号。外部中断端口程序配置如下:

1.void EXTI3_Configration()

{

/***************配置PC3端口,作为外部中断触发端口***********/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOC, &GPIO_InitStructure);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);

/****************外部中断线配置,设置为上升沿触发****************/

EXTI_InitStructure.EXTI_Line = EXTI_Line3;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);

/********************中断向量表配置*****************/

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

配置好外部中断后,当stm32上电后,便会实时监控PC3端口,当接受到红外信号后,便产生一个中断信号,调用中断处理函数,处理该事件,下面为中断处理函数,主要是解码红外信号:

2.void EXTI3_IRQHandler(void)

{

int i,j,Counter = 0;

char IR[4] = {0};

char ch1=0,ch2=0;

if(EXTI_GetITStatus(EXTI_Line3) != RESET)

{

TIM3->CNT = 0;

TIM_Cmd(TIM3,ENABLE);

while(TIM_GetCounter(TIM3) < 7000);

TIM_Cmd(TIM3,DISABLE);

TIM3->CNT = 0;

if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == 0)

{

while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));

TIM3->CNT = 0;

TIM_Cmd(TIM3,ENABLE);

while(TIM_GetCounter(TIM3) < 3500);

TIM_Cmd(TIM3,DISABLE);

if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == 1)

{

while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));

for(i = 0; i< 4; i++)

{

for(j = 0; j < 8; j++)

{

while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));

TIM3->CNT = 0;

TIM_Cmd(TIM3,ENABLE);

while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));

Counter = TIM_GetCounter(TIM3);

TIM_Cmd(TIM3,DISABLE);

ch1 = ch1>>1;

if(Counter > 840)

{

ch1 = ch1|0x80;

}

else

{

ch1 = ch1|0;

}

Counter = 0;

}

IR[i] = ch1;

}

ch1 = IR[2];

ch2 = IR[3];

ch2 = ~ch2;

if(ch1 == ch2)

{

switch(ch1)

{

case 0x07:LeftSlideFront();break;

case 0x09:RightSlideFront();break;

case 0x40:Front();break;

case 0x19:Back();break;

case 0x16:LeftSlideBehind();break;

case 0x0d:RightSlideBehind();break;

case 0x0c:Upshift();break;

case 0x5e:SlowDown();break;

case 0x15:Brake();break;

default :Brake();break;

}

}

}

}

Delay(500);

EXTI_ClearITPendingBit(EXTI_Line3);

}

}

这个函数为中断处理函数,在中断处理函数中,我们又用到了一个TIM3定时器,该定时器主要是解码红外信号,根据上文所述的0,1编码规则,用TIM3定时器,所捕获到的值,来判断信号0,1,实现软件解码红外信号。下面为TIM3定时器的配置:

3.void TIM3_Configuration()

{

TIM_DeInit(TIM3);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

TIM_TimeBaseStructure.TIM_Period = 50000;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

TIM_PrescalerConfig(TIM3,71,TIM_PSCReloadMode_Immediate);

TIM_ARRPreloadConfig(TIM3,DISABLE);

TIM_Cmd(TIM3,DISABLE);

}

设置预分频值为71,经过分频后,计数器的频率为1MHz。周期为50000.计数方式为向上计数。虽然stm32普通定时器的时钟为36MHz,如果将TIM_ClockDivision的值设置为0,则采用预分频时,时钟值应选72MHz进行分频。

4.超声波

4.1 简介

通过超声波发射装置发出超声波,根据接收器接到超声波时的时间差就可以知道距离了。超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。(超声波在空气中的传播速度为340m/s,根据计数器记录的时间t,就可以计算出发射点距障碍物的距离(s),即:s=340t/2)

4.2 超声波测距具体实现

我们在小车的前端放置一个超声波模块,采用查询法,每隔1s,发射一个10us以上的脉冲信号,超声波模块便自动发送8个40Khz的信号。当模块接收到返回信号时,输出端会输出一个高电平,这个高电平的持续时间,就是超声波模块到达障碍物,声速的来回时间。如果测得前方障碍物距离小于设置距离,则小车后退,并发出报警蜂鸣声。

4.3 超声波程序设计

1. float Distance()

{

float distance;

int time;

TIM3->CNT = 0; //非常重要,不清零,没结果

GPIOB->BSRR = 0X01;

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);//等待接收到反回信号GPIOB->BRR = 0X01;

TIM_Cmd(TIM3,ENABLE); //开启定时器,记下电平持续时间

while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 1);

TIM_Cmd(TIM3,DISABLE);

time = TIM_GetCounter(TIM3);

distance = (float)time*0.017; //cm数量级

return distance;

}

程序中的TIM3定时器,在上文3.3.3已经详细的描述。我们将stm32的PB0作为发送10us以上高电平的端口,将PB1作为接受超声波模块馈送的时间信号电平端口。该高电平的时间,为超声波来回障碍物的时间。该函数返回值,即为小车到障碍物的距离。

2. void KeepDistance() //超声波测距,距离控制函数

{

GPIOB->BRR = 0x100;

if(Distance() < 25.0)

{

GPIOB->BSRR = 0x100;

RightSlideBehind();

Delay(200);

GPIOB->BRR = 0x100;

Delay(700);

GPIOA->BSRR = 0x0c;

Time_Configuration(70,0,100,71);

}

}

调用这个函数,当小车查询到前方距离小于25cm时,便进行一些列的调整,如蜂鸣器想起,小车向右后转。

5.红外寻迹

5.1 反射式红外传感器

遥控智能小车(课程设计)

图5.1 反射式红外传感器

如图5.1所示,当红外发射管发射信号,经地面反射到接收管时,接收管部位电阻值很小;当红外传感器与地面距离拉大,接收管接收不到反射信号时,接收管部位电阻值很大。采用一个电压比较器LM393,LM393为两端输入,一端输出,比较两个输入信号的大小。我们将红外传感器接收管在接收到信号和没有接收到信号时,电阻两端的电压与一个固定的值相比,接收到信号时,LM393输出低电平;没有接受到信号时,LM393输出高电平。通过高低电平,判断红外管发出的信号是否被黑线吸收。

5.2 具体实现方法

小车上的黑线检测设备,采用的中断触发方式是,下降沿。由于电机在转动过程中,不可避免的会发生突然变向,减速等。这样会干扰电源电压,由于我我们组采用的stm32为3.3V供电,该电压有6个电池串联,经过稳压芯片稳压后,输出3.3V给stm32,当点击由于突然变向,加速减速才生大电流,对电池电压产生较大的冲击,稳压芯片输出截止。黑线检测的模块与stm32并联,当稳压芯片输出的3.3V电压突然截止时,寻迹模块输出电压为0.如果采用下降沿触发,这时,由于电压的不稳定而导致了一个有害的触发中断。

通过修改硬件电路,采用上升沿触发,当红外对管检测到黑线时,输出信号为0,当小车没有检测到黑线时,输出信号为1。当稳压芯片突然截止时,输出也0,这样可以有效的解决电机对寻迹模块的干扰。

我们小组采用3个寻迹模块,stm32采用3个外部触发端口分别与3个寻迹模块相

相关文档
  • 智能小车课程设计

  • 遥控智能小车的设计

  • 智能小车课程设计报告

  • 智能汽车课程设计

  • 汽车设计课程设计

  • 小车课程设计