完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
第1章 绪论
1.1、 灭火小车控制系统的设计背景和意义 1.2、 国内国际研究现状 1.3、 灭火小车控制系统 的目标 本设计开发的智能灭火小车控制系统应用范围十分广泛, 设计的灭火小车能够实现自动循迹、检测火源、吹风灭火、报警等功能,救灾人员可以利用手机APP通过蓝牙无线模块对小车进行远程精确控制,让小车能制精确地到达火灾发生点;把各个功能设计为多个独立的模块,便于更改和维护。 本设计具有 很好的开发前景,将会 受到广大安全防护人员的欢迎。 第2章 灭火小车控制系统介绍 2.1 灭火小车功能概述 经过文献查阅和实际情况调研,了解到目前的消防系统的研究与设计一般采用的方案大都为: 通过人为报警,再由消防人员开着消防车去起火现场进行灭火。那样消防人员会随时面临着危险。通过自己的想法。采用的方案为:通过火焰传感器、检测到起火地点的温度的因素与其标准区间值不符,小车自动根据设定好的路线去灭火或者通过手机控制小车的方向进行灭火,极大地降低了火灾对消防员人身安全的威胁。 该控制系统的最大特点: 结构简单 体积小、功率低 信号无干扰,传输准确度高 成本低廉 安全 系统各个功能模块简介: 四路循迹模块:主要用来让小车按照设定好的路线前进。 电源模块:主要用来分别区分给单片机与电机、风扇电机驱动模块供电。 五路火焰传感器模块:主要用来对火焰传感器给单片机传值的功能。 电机驱动模块:主要用来驱动两个减速直流电机,实现小车的前进、左转、右转、停车等功能。 风扇驱动模块:主要是用来控制风扇是否吹风,来实现小车灭火 功能。 蓝牙模块:通过手机软件来控制灭火小车的状态。 图 2-1 灭火小车整体模块图 2.2、工作原理 在灭火小车的设计中,工作原理:首先小车通过四路循迹模块,根据我们设定好的路线前进,然后小车的五路火焰传感器检测前方是否有火焰信号,如果检测不到火焰信号,则小车往前行走;当在小车在行走的过程中检测到火焰信号时,五路火焰传感器将信号发送到芯片,然后单片机控制小车停止,同时控制电路驱动风扇旋转,将火吹灭。 2.3、主要设计内容 用STM32F103单片机作为控制核心,加上四路循迹模块,五路火焰传感器模块,电机驱动小车四轮行走以及风扇转动,电源模块以及OLED显示模块,设计一个灭火小车。设计包括以下内容: ( 1 ) 自动沿预设轨道行驶,小车在行驶过程中,能够自动检测预先设好的轨道,实现直道、弯道和弧形轨道的前进。 ( 2 )当小车到达火源地后,自动停车同时启动灭火风扇进行灭火,消除火源后随着路线返回起点。 ( 3 )能通过手机的软件,通过蓝牙模块,切换为手动和自动循迹模式,手动模式时能控制小车到达想要的地点。 2.4、本章小结 本章结合目前的灭火小车对当前的小车进行了系统的概述,小车具备的功能以及系统控制的工作原理,通过阅读本章内容可对该系统有一个总体的了解。 第3章 系统硬件设计 3.1、硬件设计框图 本控制系统硬件设计框图 3-1 如下所示: 图 3-1硬件设计框图 在灭火小车控制系统的设计中,以STM32单片机为控制核心,用了一片 L298N电机驱动板模块用于驱动两个变速电机。 12V 电源单独给电机供电,首先STM32单片机根据火焰检测电路是否有火焰信号,来判断小车是否继续循迹前进。如果没有该火焰信号,则一直按照循迹巡线进行。手机APP控制单片机根据程序设计的要求做出相应的判断送给电机驱动模块,让小车来实现前进、左转、右转、停车等基本功能。到达火灾地点时,单片机通过晶闸管导通风扇控制电路,驱动风扇灭火。 3.2 、硬件设计及主控芯片介绍 在灭火小车控制系统的设计中,共用了一片STM32F103ZET6 单片机作为本控制系统的主控芯片,硬件设计模块共分为:4路循迹模块、电机驱动模块、电源模块、五路火焰检测模块、风扇模块。 3.2.1、STM32F103ZET6主控芯片介绍 STM32F103ZET6 简介 stm32是一个低功耗,高性能32位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器。主要性能有:与MCS-51单片机产品兼容、全静态操作:0Hz~33Hz、 三级加密程序存储器、32个可编程I/O口线、三个16位定时器/计数器、八个中断源、全双工UART串行通道、掉电后中断可唤醒、看门狗定时器、双数据指针、掉电标识符、易编程。 STM32它拥有的资源包括:48KB SRAM、256KB FLASH、2 个基本定时器、4 个通用定时器、2个高级定时器、2个DMA 控制器(共 12 个通道)、3 个SPI、2个IIC、5个串口、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口及51 个通用IO口,该芯片性价比极高。 各个引脚说明如下 PB6 接电机驱动的IN1; PB7接电机驱动IN2; PB8接电机驱动IN3; PB9接电机驱动IN4; PA2接蓝牙模块的RXT; PA3接蓝牙模块的TXD; PA6接电机驱动ENA,作为右电机调速; PA7接电机驱动ENB,作为左电机调速; 图3-2.1 STM32F103引脚图 3.2.2、4路循迹模块系统方案设计 采用脉冲调制反射红外发射接收器作为循迹传感器,调制信号带有交流分量,可减少外界的大量干扰。信号采集部分就相当于智能循迹小车的眼睛,有它完成黑线识别并产生高、低平信号传送到控制单元,然后单片机生成指令来控制驱动模块来控制两个直流电机的工作状态,来完成自动循迹。工作电流为10mA-50mA,输出为TTL电平。 3.2.3、驱动电机系统方案设计 方案 1 :采用专用芯片 L298N 作为电机驱动芯片。 L298N 是一个具有高电压大电流的全桥驱动芯片,它相应频率高,一片 L298N 可以分别控制两个直流 电机,而且还带有控制使能端。用该芯片作为电机驱动,操作方便,稳定性好,性能优良。 L298N 是 SGS 公司的产品,内部包含 4 通道逻辑驱动电路。是一种二相和四相电机的专用驱动器,即内含二个 H 桥的高电压大电流双全桥式驱动器,接收标准 TTL 逻辑电平信号,可驱动 46V 、 2A 以下的电机。其引脚排列如图 3-7 中 U4 所示, 1 脚和 15 脚可单独引出连接电流采样电阻器,形成电流传感信号。 L298 可驱动 2 个电机, OUT1 、 OUT2 和 OUT3 、 OUT4 之间分别接 2 个电动机。 5 、 7 、 10 、 12 脚接输入控制电平,控制电机的正反转, ENA , ENB 接控制使能端,控制电机的停转。也利用单片机产生 PWM 信号接到 ENA , ENB 端子,对电机的转速进行调节。 1 L298N 的逻辑功能: 表 3-2 SHARP GP2D12 实物图 2 外形及封装: 图 3-2.3 L298N 实物图 方案 2 :对于直流电机用分立元件构成驱动电路。由分立元件构成电机驱动电路,结构简单,价格低廉,在实际应用中应用广泛。但是这种电路工作性能不够稳定。 因此我们选用了方案 1 。 驱动电路的设计如图 3-2.3(2) 所示: 图 3-2.3 驱动电机模块原理图 3.2.4 、电源系统方案设计 由于本系统需要电池供电,我考虑了如下集中方案为系统供电。 方案 1 : 采用 8 节 1.5V 干电池供电,电压达到 12V ,给支流电机供电,然后将 12V 电压再次降压、稳压后给单片机系统和其他芯片供电。并且电池的价格比较低。 方案 2 :采用 3 节 4.2V 可充电式锂电池串联共 12.6V 给直流电机供电,经过 7812 的电压变换后给支流电机供电,然后将 12V 电压再次降压、稳压后给单片机系统和其他芯片供电。锂电池的电量比较足,并且可以充电,重复利用,因此,这种方案比较可行。但锂电池的价格过于昂贵,使用锂电池会大大超出我的预算,因此,我放弃了这种方案。 方案 3 :采用 12V 蓄电池为直流电机供电,将 12V 电压降压、稳压后给单片机系统和其他芯片供电。蓄电池具有较强的电流驱动能力以及稳定的电压输出性能。但蓄电池的体积过于庞大,在小型电动车上使用极为不方便, 综上考虑,我选择了方案 1 。 采用稳压芯片给各个芯片提供稳定的工作电压,其芯片的具体参数如下: 稳压芯片 LM7805CV 、 LM7812CV 1 . LM7805CV 的技术指标如下表 : 表 3-3 稳压芯片 7805 参数 2 。 电源模块电路原理图 由于单片机及所有的传感器系统供电采用的是 5V 的电源,而车体要良好的运行电机的供电电压应该达到 12V ,所以在电源的处理上采用了稳压芯片 7805CV 和 7812CV 。 图 3-2.4 电源部分电路图 通过对比三个方案,发现第三个方案要比前两个更加的可靠稳定,这一点对灭火机器人的性能的发挥很重要。所以,选择第三种方案。 3.2.5 、五路火焰检测系统设计 方案 1 :火焰传感器是模拟传感器。它利用红外敏感型元件 AC4067 对红外信号强度的检测并将其转换为机器人可以识别的信号,从而来检测火焰信号。如下图为火焰传感器电路。 图 3-2.5 火焰传感电路 火焰传感器可以用来探测波长在 700nm ~ 1000nm 范围内的红外线的短波近红外线(SW-NIR),通过电信号(电压信号)进行输出。探测角度为 60º ;,其中红外线波长在 880nm 附近时,其灵敏度达到最大。红外火焰探头将外界红外光的强弱变化转化为电流的变化,通过 A/D 转换器反映为 0 ~ 255 范围内数值的变化。外界红外光越强,数值越小;红外光越弱,数值越大。在机器人设计中,红外火焰探头起着非常重要的作用,它可以用作机器人的眼睛来寻找火源或其他物体。利用它可以制作灭火小车、足球机器人等。 3.2.6 、 车体方案设计 方案 1 :购买玩具电动车。购买的玩具电动车具有组装完整的车架车轮、电机及其驱动电路。但是一般的说来,玩具电动车具有如下缺点:首先,这种玩具电动车由于装配紧凑,使得各种所需传感器的安装十分不方便。其次,这种电动车一般都是前轮转向后轮驱动,不能适应该题目的方格地图,不能方便迅速的实现原地保持坐标转 90 度甚至 180 度的弯角。再次,玩具电动车的电机多为玩具直流电机,力矩小,空载转速快,负载性能差,不易调速。而且这种电动车一般都价格不菲。因此我们放弃了此方案。 方案 2 :自己制作电动车。经过反复考虑论证,我制定了左右两轮分别驱动,前万向轮转向的方案。即左右轮分别用两个转速和力矩基本完全相同的直流减速电机进行驱动,车体前部装一个万向轮。这样,当两个直流减速电机转向相反同时转速相同时就可以实现电动车的原地旋转,由此可以轻松的实现小车坐标不变的 90 度和 180 度的转弯。 在安装时我保证两个驱动电机同轴。当小车前进时,左右两驱动轮与前万向轮形成了三点结构。这种结构使得小车在前进时比较平稳,可以避免出现后轮过低而使左右两驱动轮驱动力不够的情况。为了防止小车重心的偏移,前万向轮起支撑作用。 对于车架材料的选择,我们经过比较选择了有机玻璃。用有机玻璃做的车架比塑料车架更加牢固,比铁制小车更轻便,美观。 综上考虑,我们选择了方案 2 。 3.2.7 、风扇模块设计 灭火风扇的驱动电路如图 3-2.7所示。其中 Port 接到单片机的 P0.5 、 P0.6 接口上。单片机输出 Port 控制信号用以驱动灭火电机动作。由于选用的是增强型 MOS 管,所以,当 Port 信号为高时, MOS 管在 V GS 下开始工作, MOS 导通,风扇开始动作,进行灭火;当 Port 信号为低时,由于增强型 MOS 管特点, V GS =0 时, i D =0 。此时, MOS 截止,风扇不动作。 图 3-2.7 风扇控制电路 3.2.8、蓝牙模块设计 使用HC-05蓝牙模块就接受APP的蓝牙数据。挂载在STM32板UART中。HC-05 蓝牙串口通信模块,是基于 Bluetooth Specification V2.0 带 EDR 蓝牙协议的 数传模块。无线工作频段为 2.4GHz ISM,调制方式是 GFSK。模块最大发射功率为 4dBm, 接收灵敏度-85dBm,板载 PCB 天线,可以实现 10 米距离通信。 模块采用邮票孔封装方式,模块大小 27mm×13mm×2mm,方便客户嵌入应用系统之 内,自带 LED 灯,可直观判断蓝牙的连接状态。 模块采用 CSR 的 BC417 芯片,支持 AT 指令,用户可根据需要更改角色(主、从模式) 以及串口波特率、设备名称等参数,使用灵活。实物图如下: 图3-2.7(2)工作原理图 图3-2.7(3)蓝牙模块与手机通讯 3.3 本章小结 本章通过框图的形式介绍了各个系统模块的设计,4路循迹模块、驱动电机模块、电源模块、五路火焰检测模块、风扇控制、蓝牙模块等几部分的设计思路作了详细分析,通过阅读本章内容可对本智能灭火小车控制系统的硬件设计全面了解。 第4章 系统软件 设计 对于一个完整控制系统来说,除了要有一个完整的硬件控制以外,还应该有一个能充分发挥硬件功能的软件系统来支持它,本章将详细介绍4路循迹巡线模块、电机驱动、五路火焰检测模块、风扇驱动的软件实现方法。 4.1 软件设计思路 根据总体设计的思想及本系统实现的功能,在软件设计中完成以下功能。 图 4-1 系统软件图 4路循迹巡线模块主程序: 电机驱动模块主程序:主要用来控制两个直流减速电机,实现前进、后退、前左转、前右转、后左转、后右转、停车等功能。 火焰检测模块主程序:主要通过火焰传感器探测是否有火源。 风扇模块程序:主要用来控制一个报警器和风扇,实现报警、吹风等功能。 通过各种功能模块得到我们需要的东西,并且通过Keil 软件公司提供的Keil5软件利用代码来具体实现我们需要的功能。 4.2、各功能模块软件程序设计 在各个硬件功能模块的基础上,针对其预定实现的相应功能对各个功能模块进行软件程序设计。 4.2.1、Main主程序代码 利用main主程序代码检测火焰传感器信号 .#include “delay.h” #include “sys.h” #include “usart.h” #include “timer.h” #include “moter.h” #include “oled.h” #include “linewalking.h” #include “fire.h” //电机 1 PWM(EN)使用GPIOA.6 --- PA.6 //电机 2 PWM(EN)使用GPIOA.7 --- PA.7 //电机的初始化 //分别PB11 PB12 PB13 PB14 //蓝牙模块 PA.9 ---》 RXD // PA.10 ---》 TXD // int Flag = 0; int main(void) { delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(9600); //串口初始化为9600 LED_Init(); //LED端口初始化 TIM3_PWM_Init(899,719); //72分频。PWM频率=72000000/(900*720) Moter_GPIO_Init();//电机的GPIO初始化 LineWalking_GPIO_Init();// 巡线传感器GPIO初始化接口 Fire_GPIO_Init(); KEY_Init(); while(1) { if(KEY0 == 0) { delay_ms(20); while(KEY0 == 0); Flag++; if(Flag == 3) Flag = 0; } if(Flag == 2) { if(fire1||fire3||fire4||fire5) { delay_ms(10); if(fire1||fire3||fire4||fire5) { moter_stop(); GPIO_SetBits(GPIOD,GPIO_Pin_2); LED1 = 0; } } else { GPIO_ResetBits(GPIOD,GPIO_Pin_2); app_LineWalking(); LED1 = 1; } } } } 4.2.2、Pwm代码 通过程序代码实现车速的调整功能 void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟 //GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2-》PB5 //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOA.6 GPIOA.7 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6; //TIM_CH1 TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO //初始化TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 //初始化TIM3 Channel2 PWM模式 //------------------注意!!!----------------------// //在模式PWM1中有效电平于无效电平 such as (TIM_OCPolarity_Low)有效 则为低电平 否则无效电平为高电平 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性低 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 //初始化TIM3 Channel1 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性低 TIM_OC1Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC1 TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3 } 4.2.3、电机驱动代码 通过电机驱动程序代码实现小车的前进,后退,右转左转功能 void Moter_GPIO_Init(void) { //电机的GPIO 初始化 GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化 GPIO_SetBits(GPIOB,GPIO_Pin_4); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_5); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_8); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_9); // 输出高 }//前进 void moter_run(u16 pwm1,u16 pwm2) { IN1 = 1; IN2 = 0; IN3 = 1; IN4 = 0; TIM_SetCompare1(TIM3,pwm1); // 电机1占空比 TIM_SetCompare2(TIM3,pwm2); // 电机2占空 }//暂停 void moter_stop(void) { IN1 = 0; IN2 = 0; IN3 = 0; IN4 = 0; TIM_SetCompare1(TIM3,0); // 电机1占空比 TIM_SetCompare2(TIM3,0); // 电机2占空比 } //后退 void moter_back(u16 pwm1, u16 pwm2) { IN1 = 0; IN2 = 1; IN3 = 0; IN4 = 1; TIM_SetCompare1(TIM3,pwm1); // 电机1占空比 TIM_SetCompare2(TIM3,pwm2); // 电机2占空比 } // Function moter_left //@author yuan //left void moter_left(u16 pwm1, u16 pwm2) { IN1 = 0; IN2 = 0; IN3 = 1; IN4 = 0; TIM_SetCompare1(TIM3,pwm1); // 电机1占空比 TIM_SetCompare2(TIM3,pwm2); // 电机2占空比 }//Right void moter_right(u16 pwm1,u16 pwm2) { IN1 = 1; IN2 = 0; IN3 = 0; IN4 = 0; TIM_SetCompare1(TIM3,pwm1); // 电机1占空比 TIM_SetCompare2(TIM3,pwm2); // 电机2占空比 } 4.2.4、蓝牙串口代码 利用蓝牙串口代码实现数据的传输以及通信功能 void uart_init(u32 bound){ //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 USART_Cmd(USART1, ENABLE); //使能串口1 } void USART1_IRQHandler(void) //串口1中断服务程序 { u8 Res; #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1); //读取接收到的数据 if(Res == 69) //E moter_stop(); if(Res == 65) //A { moter_run(300,300); LED = !LED; } if(Res == 66) //B moter_left(300,0); if(Res == 67) //C moter_right(0,300); if(Res == 68) //D moter_back(300,300); // OLED_Clear(); //清屏函数,清完屏, // OLED_ShowString(10,12,“ok”); if((USART_RX_STA&0x8000)==0)//接收未完成 { // OLED_ShowString(10,10,“ok”); if(USART_RX_STA&0x4000)//接收到了0x0d { // OLED_ShowString(10,10,“ok”); if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA》(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } } } } #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntExit(); #endif } 4.2.5、循迹代码 利用循迹代码实现小车路线的检测功能以及对于小车的正确路径行驶功能。 #include “linewalking.h” #include “moter.h” #include “delay.h” void LineWalking_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PC端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15|GPIO_Pin_12; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化 GPIO_SetBits(GPIOB,GPIO_Pin_13); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_14); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_15); // 输出高 GPIO_SetBits(GPIOB,GPIO_Pin_12); // 输出高 } //从车身后面往前看: 左侧到右边巡线传感器顺序为 L1 L2 |黑线| R1 R2 对应原理图 IN2 IN1 |黑线| IN3 IN4 void bsp_GetLineWalking(int *p_iL1, int *p_iL2, int *p_iR1, int *p_iR2) { *p_iL1 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); //L1 *p_iL2 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14); //L2 *p_iR1 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15); //R1 *p_iR2 = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12); //R2 } void app_LineWalking(void) { int LineL1 = 1, LineL2 = 1, LineR1 = 1, LineR2 = 1; bsp_GetLineWalking(&LineL1, &LineL2, &LineR1, &LineR2); //获取黑线检测状态 if( (LineL1 == LOW || LineL2 == LOW) && LineR2 == LOW) //左大弯 { moter_SpinLeft(300, 300); delay_ms(80); } else if ( LineL1 == LOW && (LineR1 == LOW || LineR2 == LOW)) //右大弯 { moter_SpinRight(300, 300); delay_ms(80); } else if( LineL1 == LOW ) //左最外侧检测 { moter_SpinLeft(300, 300); delay_ms(10); } else if ( LineR2 == LOW) //右最外侧检测 { moter_SpinRight(300, 300); delay_ms(10); } else if (LineL2 == LOW && LineR1 == HIGH) //中间黑线上的传感器微调车左转 { moter_left(0,300); } else if (LineL2 == HIGH && LineR1 == LOW) //中间黑线上的传感器微调车右转 { moter_right(300,0); } else if(LineL2 == LOW && LineR1 == LOW) // 都是黑色, 加速前进 { moter_run(300,300); } } 4.2.6、风扇灭火代码 利用风扇灭火代码实现小车的灭火功能 #include “stm32f10x.h” // Device header #include “fire.h” void Fire_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE); //使能PC端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_9); GPIO_SetBits(GPIOA,GPIO_Pin_10); // 输出高 GPIO_SetBits(GPIOA,GPIO_Pin_11); // 输出高 GPIO_SetBits(GPIOA,GPIO_Pin_12); // 输出高 GPIO_SetBits(GPIOA,GPIO_Pin_13); // 输出高 GPIO_ResetBits(GPIOD,GPIO_Pin_2); } 4.2.7、Android端代码 利用Android端代码实现对于小车的手机控制功能 La《Button android:layout_width=“100dp” android:layout_height=“wrap_content” android:id=“@+id/forword” android:layout_gravity=“center_horizontal” android:text=“前进” android:textSize=“20dp” android:layout_margin=“20dp” android:background=“@drawable/button” /》 《LinearLayout android:layout_width=“wrap_content” android:layout_height=“wrap_content” android:orientation=“horizontal” android:layout_gravity=“center” 》 《Button android:id=“@+id/left_btn” android:layout_width=“100dp” android:layout_height=“wrap_content” android:text=“左转” android:textSize=“20dp” android:background=“@drawable/button” /》 《Button android:id=“@+id/stop_btn” android:layout_width=“100dp” android:layout_height=“wrap_content” android:text=“停止” android:textSize=“20dp” android:layout_marginLeft=“20dp” android:background=“@drawable/button” /》 《Button android:id=“@+id/right_btn” android:layout_width=“100dp” android:layout_height=“wrap_content” android:text=“右转” android:textSize=“20dp” android:layout_marginLeft=“20dp” android:background=“@drawable/button” /》 《/LinearLayout》 《Button android:id=“@+id/back” android:layout_width=“100dp” android:layout_height=“wrap_content” android:layout_gravity=“center” android:text=“后退” android:textSize=“20dp” android:background=“@drawable/button” android:layout_margin=“20dp” /》 4.2.8、Java代码 class ButtonListener implements View.OnTouchListener { public boolean onTouch(View v, MotionEvent event) { switch (v.getId()){ case R.id.forword: if(event.getAction() == MotionEvent.ACTION_UP){//放开事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } if(event.getAction() == MotionEvent.ACTION_DOWN){//按下事件 message[0]= (byte) 0x41;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } break; case R.id.back: if(event.getAction() == MotionEvent.ACTION_UP){//放开事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } if(event.getAction() == MotionEvent.ACTION_DOWN){//按下事件 message[0]= (byte) 0x44;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } break; case R.id.stop_btn: if(event.getAction() == MotionEvent.ACTION_UP){//放开事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } if(event.getAction() == MotionEvent.ACTION_DOWN){//按下事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } break; case R.id.left_btn: if(event.getAction() == MotionEvent.ACTION_UP){//放开事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } if(event.getAction() == MotionEvent.ACTION_DOWN){//按下事件 message[0]= (byte) 0x42;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } break; case R.id.right_btn: if(event.getAction() == MotionEvent.ACTION_UP){//放开事件 message[0]= (byte) 0x45;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } if(event.getAction() == MotionEvent.ACTION_DOWN){//按下事件 message[0]= (byte) 0x43;//设置要发送的数值 bluesend(message);//发送数值 Log.d(“cy08”,“”+message[0]); } break; default: break; } return false; } } 4.3、本章小结 本章用流程图的方法说明了智能寻迹灭火小车控制系统的软件设计,并对系统中主要程序的设计作了详细说明,通过阅读本章内容可以全面了解本控制系统的软件设计。 第5章 仿真调试 5.1、硬件调试 本次实验硬件的 调试主要运用到的是keil5的C语言代码编写,串口调试助手在小车上的代码调试,首先,在正式代码编写之前,需要先了解到几个步骤; 在调试程序之前,需要先确认各个模块的正确运行,所以需要我们先简单编写keil5程序,完成对于模块的简单使用,防止模块本身的问题造成的实验影响, 调试程序时,首先用全速运行的方法进行总体调试,以便快速发现程序中存在问题的部分。然后设置断点调试。主要针对有问题的程序调试,更快地确定出现问题的位置。最后,利用单步调试方法,分析程序中出现的问题,解决问题,使程序正常运行。 在多次调试不成功的基础上,考虑思路是否正确,如果确定思路无误,考虑两个问题:一是程序中是否有笔误的地方;二是运行软件是否正常。 5.2、软件调试 本次APP使用的开发软件是Android studio,我们在蓝牙的连接上采用的是通过Mac地址自动连接已配对的蓝牙设备,按下按键时,会向蓝牙设备发送“ABCD”字符的十六进制数。 调试过程中,需要注意stm32接收的字符是ASCII码,所以在接收时需要用ASCII码来进行识别,否则无法识别到APP发送的数据。 手机按键在按下前进后退等时,会发送相应指令的数据,而松开时会立刻发送停止的指令,这样可以实现在按键松开时可以立刻停车。 5.3、本章小结 本章将硬件调试与软件调试分开叙述,并对调试过程中出现的问题作了详细的分析。 通过对硬件调试的基础上,根据其功能和特性,完成了软件的调试,整个程序能够实现预定的功能。在综合调试中尤其要注意各子程序之间的调用、返回。 可对智能寻迹灭火小车控制系统的整个调试过程有较全面的了解 第6章 结论 本次电子系统综合设计按照“循迹自动灭火小车”需要实现的功能通过以 stm32为主要核心板,用各种模块完成我们此次任务,通过各种模块的功能实现我们也得到了许多的设计结论, ( 1 )、控制小车循迹行动; 当循迹小车时,需要我们掌握好对于路线识别的准确判断,因此我们通过设定路线进行循迹,并且对于小车的循迹功能,我们还可以额外尝试增加一个避障功能,防止当小车循迹出错的时候出现小车的安全问题,及时的保护好我们的小车。 (2 )、控制风扇灭火。 当启动小车前进时一样,也有很大的瞬时的电流。所以需要延时程序来调整。 (3 )、火焰传感器识别。 当我们使用小车时,火焰传感识别的功能非常重要,因此我们必须得保证好火焰传感器的灵敏程度,需要我们在远距离就能够发现火焰的扩散,并及时停车灭火。所以购买火焰传感器的钱一定不能省,保护小车安全 通过硬件调试及软件的编程,达到了此次设计要求,实现了基本功能以及其一些扩展功能。该系统不仅能够对风扇的灵活控制,进行路线的自动巡航,并且还可以实现小车的具体运动控制,对小车进行调整。即包含手动,也包含自动蓝牙控制功能,完成实验设计需要的要求。通过本次实际,我们对于各芯片的工作原理有了更深入的认识,能够理论联系实际,同时也建立起了很强的思考能力和合作动手的能力,是一次非常好的学习与锻炼能力的机会! |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 03:05 , Processed in 0.752212 second(s), Total 48, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号