——基于arduino的个人交通安全装置
个人交通安全装置的设计与开发
——一款基于arduino的个人交通安全装置
关键词:个人交通工具、安全装置、事故求救、安全警报
功能:
1、在交通工具有被盗风险时提示所有者并发出警报。2、优化锁具,使偷盗极为困难甚至没有意义。3、能根据使用者指令反馈位置信息。4、在发生交通事故时发送位置信息并及时求救。5、在速度过快时通过警示灯提示使用者。
优点:
使用加速度传感器与测速,解读交通工具运动状态
有效辨别不同情境,作出不同反应,有效面对事故,偷盗等问题
使用指纹识别,简化开锁过程,提升安全性
改进车锁为内置龙头锁,有效防止暴力破锁,巧妙解决偷盗问题
能根据需要追踪位置,为确认情况与被盗寻回提供方便
应用范围:
用于摩托车,电瓶车等个人交通工具以增强其安全性并减少偷窃高价交通工具带来的损失。还可应用于对交通状况及事故风险的调查与使用者出行路线,次数,驾驶习惯等内容的统计。
1 引言
1.1研究背景与由来
在生活经历中,我意识到摩托车,电瓶车还有自行车都有许多安全隐患。在对各个方面进行了较为完善的调查之后,得到了以下结论。
a.个人交通工具的道路交通安全事故多发
来自市交巡警部门提供的数据也显示,在当前我市的交通事故中,超过60%与电动车有关。 ——摘自《衢州日报》
从江山市的初步统计结果看,去年一年,交警队接处警中涉及电动自行车的占了60%;发生事故伤亡人数约占总数的50%以上。 ——摘自《三江晚报》
民警李景波介绍,在北三环高架桥上处理的非机动车事故,每月都有10多起。因为车速较高,这些事故中,约60%的非机动车车主有骨折现象。 ——摘自《河南商报》
b.高价个人交通工具逐步普及
数据表示,报告预计2013年全球电动车销量将同比增长89%至225,000辆,但该数字只有此前部分车企预期值的三分之一。 ——摘自《中国行业研究网》
1-10月,上述十家企业累计销售970.51万辆,约占摩托车销售总量的55.58%,比上年同期提高1.23个百分点。 ——摘自《中商情报网》
c.盗窃事故频发,现有锁具遭质疑
从2014年4月交付至今不到一年时间里,都市嘉源小区已经连续丢失了30辆左右电瓶车,另有业主其他物品被盗。 ——摘自《现代金报》
目前市面上的一些进口液压钳最大刀口口径在22mm左右,压力超过16t。因此,一般U型防盗锁在其面前的确显得脆弱不堪,U型锁杆在几秒钟内被轻而易举地剪断,电动车因此频频被盗。 ——来源《浙江在线》
1.2研究目的
根据事故多发,伤亡率高的特点,能一定程度上减少事故概率并及时做出应对,使个人交通工具出行更加可靠,对驾驶员的安全有保障。
同时能有效解决盗窃事故的多发,降低偷窃概率,减少偷盗事件对所有者的损失。
增强拥有者的交通安全意识与防盗意识,从根本上消除安全隐患。
2 研究内容
2.1主要设计原理
主体运算由iteaduino mega2560单片机进行,通过指纹模块识别认证使用者并控制锁的开关,通过主体由霍尔传感器组成的速度计判断显示速度并进行提示,通过加速度传感器判断停放或行驶状态,由单片机进行判断后收集gps模块定位后的信息由gprs模块发出。供电由轮胎上的发电轴(类发电花鼓)进行。
2.2装置功能
测算行驶速度,将行驶速度及时显示并在速度大于安全限制时亮起警示灯。目的是使驾驶员对当前速度有明确意识,防止速度过快或刹车距离过大导致的事故。
安置在车把上的指纹模块检测使用者指纹并自动开锁。指纹的安全性远高于其他认证措施,省去开关锁锁消耗的时间和精力。
内置在交通工具主体结构内部的锁通过锁定车头使其无法转动来达到锁车的效果。内置锁有效防止强行破拆。
锁处于开启状态而车运动状态异常的情况下,判断为发生事故,将向使用者发送15秒询问信息。若无反馈则向外发出位置信息及求救信号。
锁处于关闭状态下检测到持续移动时,响起警报威吓小偷并向使用者手机手机发出提示信息。
2.3装置结构
外部结构:
从外部来看,装置主要分为几个不同的区域固定在交通工具上,具体结构如下:
a: 车把指纹锁与液晶显示屏部分
此部分由指纹模块的两个部分组成,前一部分起到扫描指纹并向芯片传输数据的作用,后一部分将数据整合并初步处理后由连接线传给单片机进行进一步运算。
液晶显示屏同样固定在车把上,负责显示指纹认证状态,在开启后转为显示运动速度,在其一侧有led小灯辅助。
b: 车中部主体部分
主体部分是整个装置的核心,主要的功能的发挥与实现都是由这一部分完成的。这一部分包括了arduino2560开发板,gprs模块,gps模块和三轴加速度传感器。
整个装置所有信息的运算,接收并发出指令都是经过arduino开发板的,而gprs模块作为通讯工具与手机相联系,承担了发出信息的工作。Gps模块的定位功能使得自行车能够被追踪,对于被窃与事故都有所帮助。
三轴加速度传感器的使用使单片机能够判断自行车的运动状态和倾角,对于不同事件与情景发生的判断来说是必不可少的。
C:车轮处发电与测速装置
车轮处包括了发电装置和测速装置的信号输入端,包括安装在车轴上的发电花鼓,与其相连的稳压模块。还有车轮侧面的霍尔传感器与车轮上的磁铁。
发电花鼓承担了把车轮旋转的部分功耗转化为电能供整个装置工作,由于车轮转速不恒定,电压有大有小,所以需要使用稳压模块来使其稳定在需要的电压,输出的电能将储存在移动电源内。
测速的部分由霍尔传感器完成,它将检测车轮上磁铁所发出的磁场,再由单片机进行运算转化为速度,运动速度将显示在车把的lcd屏幕上。它对于运动状态的判断起到了辅助作用。
装置外部结构图:
内部结构:
从内部来讲,整个装置主要包括:
Arduino mega2560开发板,Sim900 Gprs模块,TF16E Gps模块,mpu6050三轴加速度传感器,霍尔传感器,1602 lcd液晶显示屏,UART 指纹读取模块,5v稳压模块,简易舵机锁
本节将对主要模块的功能和工作原理进行详细介绍。
a:Arduino mega2560开发板
基本原理:
arduino是一款便捷灵活、方便上手的开源电子原型平台,一个基于开放原始码的软硬件平台,构建于开放原始码simple I/O介面版,并且具有使用类似Java,C语言的Processing/Wiring开发环境。能通过各种各样的传感器来感知环境,通过控制灯光、马达和其他的装置来反馈、影响环境。对Arduino的编程是通过arduinoIDE(Integrated Drive Electronics)利用 Arduino编程语言和Arduino开发环境来实现的。
Arduino Mega2560是采用USB接口的核心电路板,具有54路数字输入输出,适合需要大量IO接口的设计。处理器核心是ATmega2560, 同时具有54路数字输入/输出口(其中16路可作为PWM输出),16路模拟输入,4路UART接口,一个16MHz晶体振荡器,一个USB口,一个电源 插座,一个ICSP header和一个复位按钮。
工作原理:
所有代码的运算都是由mega2560开发板进行的,接收,处理并发送信息,使得各模块能协同工作。具体工作原理见各模块工作原理。
b: Sim900 全球鹰 Gprs模块
基本原理:
GPRS,即通用分组无线服务记述,其工作时,是通过路由管理来进行寻址和建立数据连接的,而GPRS的路由管理表现在移动终端发送数据的路由建立,移动终端接收数据的路由建立,以及移动终端处于漫游时数据路由的建立。
对于第一种情况,当移动终端产生了一个PDU(分组数据单元),这个PDU经过SNDC层(子网适配层)的分段压缩,称为SNDC数据单元。然后经过LLC层(逻辑链路控制)处理,通过空中接口送到GSM网络中移动终端所处的SGSN。SGSN把数据送到GGSN。GGSN把收到的消息转换为可在公用数据网中传送的格式,最终送给公用数据网的用户。
电磁波的发射则是通过线圈和电容器组成振荡电路达到一定频率。SIM900工作频率为GSM/GPRS 850/900/1800/1900MHz。
工作原理:
与mega2560协同工作时使用3.3v接口和5V供电TXD,RXD(发出,接收)分别与单片机上的RXD,TXD连接。
和大多gprs模块一样,它是通过AT指令进行控制的。AT指令有许多功能,本装置中仅使用了消息发送的功能。
"AT+CSCS=\"GSM\"\r\n"(选择全球移动通信功能,\r\n为换行,开启新行的语句)
"AT+CMGF=1\r\n"(设置为短消息模式)
"AT+CMGS=\"18817559321\"\r\n"(设置为短消息发送模式并设置发送号码)
"Your bike has fallen down!"(发送内容)
以此来在加速度传感器传送信号由单片机判断情景后发送所要的信息。
c:TF16E Gps模块
基本原理:
Gps,即全球定位系统,是使用一颗或多颗卫星,接收目标以固定间隔持续发送的信号,利用多普勒效应计算其位置的系统。
当GPS卫星正常工作时,会不断地用1和0二进制码元组成的伪随机码(简称伪码)发射导航电文。GPS系统使用的伪码一共有两种,分别是民用的C/A码和军用的P(Y)码。C/A码频率1.023MHz,重复周期一毫秒,码间距1微秒,相当于300m。
GPS定位的基本原理是根据高速运动的卫星瞬间位置作为已知的起算数据,采用空间距离后方交会的方法,确定待测点的位置。
工作原理:
Gps有许多种数据类型,TF16E Gps模块使用的是NMEA0183协议。
NMEA 0183输出
GGA:时间、位置、定位类型
GLL:经度、纬度、UTC时间
GSA:GPS接收机操作模式,定位使用的卫星,DOP值
GSV:可见GPS卫星信息、仰角、方位角、信噪比(SNR)
RMC:时间、日期、位置、速度
VTG:地面速度信息
MSS:信号强度等
本装置使用的是GGA定位数据类型并从中提取出经纬度信息。
if(GGA_flag == 1)(判断是否需要定位)
Latitude = getLatitude();
Longtitude = getLongtitude();(获取GGA定位信息中的经纬度)
degree = (GPS_Buffer[18]-'0')*10+(GPS_Buffer[19]-'0');
cent = (GPS_Buffer[20]-'0')*10+(GPS_Buffer[21]-'0');
second=(GPS_Buffer[23]-'0')*1000+(GPS_Buffer[24]-'0')*100+(GPS_Buffer[25]-'0')*10+(GPS_Buffer[26]-'0');(经纬度数据单位装换公式)
之后将获取的数据传给单片机用gprs模块发送给使用者
d:mpu6050三轴加速度传感器
基本原理:
目前的三轴加速度传感器大多采用压阻式、压电式和电容式工作原理,产生的加速度正比于电阻、电压和电容的变化,通过相应的放大和滤波电路进行采集。这个和普通的加速度传感器是基于同样的一个原理,所以在一定的技术上三个单轴就可以变成一个三轴。
工作原理:
while(1){
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
Acceleration[0] = ax/16384.0;
Acceleration[1] = ay/16384.0;
Acceleration[2] = az/16384.0;
Rotation[3] = gx/131.0;
Rotation[3] = gy/131.0;
Rotation[3] = gz/131.0; (读取各项加速度数值)
if(abs(diffAcceleration[0])>MAX_diffAccel || abs(diffAcceleration[1])>MAX_diffAccel) {
if(count == TIMEOUT && GPS_flag==1) {
sendGPS();
GPS_flag=0;
}
count++;
}
if(abs(diffRotation[0]) > MAX_diffRota || abs(diffRotation[1]) > MAX_diffRota) sendAcceleration();
delay(500);} (判断加速度与运动状态并在必要时读取gps信息)
运动状态数据经单片机分析处理后获取位置信息并发送。
e:UART 指纹读取模块
基本原理:
本模块属于光学指纹模块,利用光的折摄和反射原理,光从底部射向三棱镜,并经棱镜射出,射出的光线在手指表面指纹凹凸不平的线纹上折射的角度及反射回去的光线明暗就会不一样。CMOS或者CCD的光学器件就会收集到不同明暗程度的图片信息,就完成指纹的采集。
而指纹的判断是将新采集到的指纹与事先录入的指纹以图片信息的形式比对相似度。
工作原理:
指纹模块的控制与反馈是通过1帧8字节的固定格式的语句。以不同16进制数字常量的值表示读取,写入,读取成功,读取失败,数据库已满等不同状态。
由于数据头第一字节和第七第八字节内容相同,所以对代码进行了封装。
命令 0xF5 CMD P1 P2 P3 0 CHK 0xF5
应答0xF5 CMD Q1 Q2 Q3 0 CHK 0xF5
CMD: 命令/应答类型
P1,P2,P3:命令参数
Q1,Q2,Q3:应答参数,
Q3 多用于返回操作的有效性信息,此时可有如下取值:
#define ACK_SUCCESS 0x00 //操作成功
#define ACK_FAIL 0x01 //操作失败
#define ACK_FULL 0x04 //指纹数据库已满
#define ACK_NOUSER 0x05 //无此用户
#define ACK_USER_EXIST 0x07 //用户已存在
#define ACK_TIMEOUT 0x08 //采集超时
CHK: 校验和,为第2 字节到第6 字节的异或值
以以上命令来录入指纹,并进行身份验证,身份验证结果将会发送给单片机并控制锁的开关等反馈。
3 总结与讨论
3.1 装置优点
装置的功能较齐全,能有效解决一些不便于困扰的问题。在特殊情况下提供很大帮助,尤其对于摩托车,装置能起到较好的保护作用,一定程度上解决了开关锁程序复杂,自行车安全系数较低易发生事故的问题。
应对方案相对较全面,对偷窃,认证,事故等不同情况都有所考虑,运行准确度较高。设计人性化,考虑使用者个人意愿并防止系统误判在发出警报前会向手机发出15秒询问。能很大程度上增加个人交通工具出行的安全性,同时有效防止盗窃事件。
3.2 过程中所得
在本项目的开发过程中,我不但学会了一些单片机编程的基础知识和齿轮传动,数据业务运作原理,还得到了许多项目完成的经验,如事先明确查询资料并理解原理的重要性,设计装置和程序时考虑完全有逻辑性和一些实用的演讲答辩技巧。我学会了如何解决出现的困难与如何正确有效地向他人寻求帮助,也磨练了意志,培养了坚持不懈,刻苦钻研问题的精神。这些收获是我在完成项目的过程中不可替代的。
3.3 遇到的问题
在进行研究与设计的过程中,我也遇到过相当多的问题与困难。在开始进行开发时,由于没有经验,曾经因单纯地将数字输出插入了模拟信号串口而导致代码无法使用,修改了许多次代码后才发现问题。制作第一把演示用锁时制作的是木制齿轮模型,由于没有充分理解齿距,齿偏角与模数关系导致最初制作的齿轮不能流畅地转动,通过重复的设计与探究才制作出了较为合适的锁。为了使用gprs模块,父母投入精力帮我买卡,第一次错买成了4g卡,因模块关系无法使用,第二次购买的是移动的3g卡,由于商家没有明确说明,在发现不能发短信时,经过调查,只有联通的3g卡才能支持,最终不得不借用父母未更换的2g卡。在进行代码的编写时,我因信息较为混乱,if语句的应对情况不完全,导致代码中有漏洞,后来经过长字符串的封装与逻辑的简化才达到理想效果。从中我理解到了不能急于求成,在进行任何研究之前事先进行完善调查的重要性。我也建议将要进行研究的人对知识储备和信息整理引起重视。
在我完成的过程中,父母全力支持我,提供资金,帮我办事。指导老师也耐心教导我如何使代码更加严谨而有条理,同时鼓励我自己解决问题,学会自力更生。
4 创新点
本装置的创新点在于:
使用加速度传感器与测速,解读交通工具运动状态
有效辨别不同情境,作出不同反应,有效面对事故,偷盗等问题
使用指纹识别,简化开锁过程,提升安全性
改进车锁为内置龙头锁,有效防止暴力破锁,巧妙解决偷盗问题
能根据需要追踪位置,为确认情况与被盗寻回提供方便
5 项目展望
本项目应用范围较广,对于摩托车,电瓶车,或其他交通工具都能起到一定作用。
在装置改进的方面,整体结构有一定体积,布置和排线可重新设计。可加入手环或手机的蓝牙通讯与认证,一方面增强了装置的可变性,可有多种认证选择,一方面省略了要录入指纹时相对繁琐的一些步骤。锁具虽然已经内置,但仍不排除有强行破除方法的可能性,可以重新设计结构使锁破坏后仍需要机械认证,如加入类似钥匙的结构,不影响自动化仅用于锁定开关锁的功能,使锁本身即使被单独破坏交通工具也无法使用。
6 参考文献
〔美〕Simon Monk 《arduino+与android互动制作》
〔美〕Massimo Banzi 《爱上arduino》
7 附录
装置代码
void loop(){
while(1){
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
Acceleration[0] = ax/16384.0;
Acceleration[1] = ay/16384.0;
Acceleration[2] = az/16384.0;
Rotation[3] = gx/131.0;
Rotation[3] = gy/131.0;
Rotation[3] = gz/131.0;
for(int i=0;i<3;i++){
diffAcceleration[i] = Acceleration[i] - preAcceleration[i];
preAcceleration[i] = Acceleration[i];
diffRotation[i] = Rotation[i] - preRotation[i];
preRotation[i] = Rotation[i]; }
Serial.print("diffAcceleration:");
for(int i=0;i<3;i++){
Serial.print(diffAcceleration[i]);
Serial.print(" ,"); }
Serial.println();
Serial.print("diffRotation:");
for(int i=0;i<3;i++){
Serial.print(diffRotation[i]);
Serial.print(" ,"); }
Serial.println();
//diffAccel = abs(diffAcceleration[0]) + abs(diffAcceleration[1]) + abs(diffAcceleration[2]) - MAX_diffAccel;
//diffRota = abs(diffRotation[0]) + abs(diffRotation[1]) + abs(diffRotation[2]) - MAX_diffRota;
if(abs(diffAcceleration[0])>MAX_diffAccel || abs(diffAcceleration[1])>MAX_diffAccel) {
if(count == TIMEOUT && GPS_flag==1) {
sendGPS();
GPS_flag=0; }
count++; }
if(abs(diffRotation[0]) > MAX_diffRota || abs(diffRotation[1]) > MAX_diffRota) sendAcceleration();
delay(500); } }
void serialEvent1(){
while(Serial1.available()){
rev_char=Serial1.read();
if(rev_char == '$' && rev_flag == 0){
rev_start = 1;
rev_stop = 0; }
if(rev_start == 1){
GPS_Buffer[rev_pos++] = rev_char;
if (rev_char == '\n'){
GPS_Buffer[rev_pos++] = '\0';
rev_start = 0;
rev_stop = 1;
rev_flag = 1;
rev_length= rev_pos;
rev_pos = 0;
} } }
if(rev_flag == 1){
GGA_flag = 1;
rev_flag = 0;
for(int j=0;j<6;j++) if(GPS_Buffer[j]!=GPS_GGA[j]) GGA_flag = 0;
if(GGA_flag == 1){
for(int i=0;i<=rev_length;i++) Serial.print(GPS_Buffer[i]);
Serial.println();
if(GPS_Buffer[43]!='0') {
Latitude = getLatitude();
Longtitude = getLongtitude();
GPS_flag=1;
Serial.print("Latitude:");
Serial.print(Latitude,8);
Serial.print(" Longtitude:");
Serial.println(Longtitude,8);
} } } }
double getLatitude(){
unsigned int degree,cent,second;
double value;
degree = (GPS_Buffer[18]-'0')*10+(GPS_Buffer[19]-'0');
cent = (GPS_Buffer[20]-'0')*10+(GPS_Buffer[21]-'0');
second = (GPS_Buffer[23]-'0')*1000+(GPS_Buffer[24]-'0')*100+(GPS_Buffer[25]-'0')*10+(GPS_Buffer[26]-'0');
value = (double)degree + (double)(cent/60.0) + (double)(second/600000.0);
return value; }
double getLongtitude(){
unsigned int degree,cent,second;
double value;
degree = (GPS_Buffer[30]-'0')*100+(GPS_Buffer[31]-'0')*10+(GPS_Buffer[32]-'0');
cent = (GPS_Buffer[33]-'0')*10+(GPS_Buffer[34]-'0');
second = (GPS_Buffer[36]-'0')*1000+(GPS_Buffer[37]-'0')*100+(GPS_Buffer[38]-'0')*10+(GPS_Buffer[39]-'0');
value = (double)degree + (double)(cent/60.0) + (double)(second/600000.0);
return value; }
void sendGPS(){
char value[10];
Serial2.write("AT+CSCS=\"GSM\"\r\n");
delay(1000);
Serial2.write("AT+CMGF=1\r\n");
delay(1000);
Serial2.write("AT+CMGS=\"18817559321\"\r\n");
delay(1000);
Serial2.write("Your bike has been stolen.Latitude:");
dtostrf(Latitude,2,5,value);
Serial2.write(value);
Serial2.write(" Longtitude:");
dtostrf(Longtitude,3,5,value);
Serial2.write(value);
Serial2.write(0x1a);
Serial2.flush();
for(int i=0;i<3;i++) delay(1000); }
byte sendAcceleration(){
Serial2.write("AT+CSCS=\"GSM\"\r\n");
delay(1000);
Serial2.write("AT+CMGF=1\r\n");
delay(1000);
Serial2.write("AT+CMGS=\"18817559321\"\r\n");
delay(1000);
Serial2.write("Your bike has fallen down!");
Serial2.write(0x1a);
Serial2.flush();
for(int i=0;i<3;i++) delay(1000);
return 1; }
//=========全局变量==========
byte gRsBuf[9]; //串行接收缓存
byte gTxBuf[9]; //串行发送缓存
char name[5][16]={"HuangSenhong","SuYutong","LiZiyi","ZhuShengjie","LingJie"};
byte gRsLength;
byte in_byte;
byte Verify_flag = 0;
byte value;
long count=0;
int flag = 0;
int time = 0;
int hallPin= 8;
int currentState=LOW;
int clockwise = 24;
const int tireCircumf=21; // inches
void setup(){
pinMode(clockwise,OUTPUT);
pinMode(hallPin,INPUT);
Serial2.begin(19200);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Please enter your");
lcd.setCursor(0, 1);
lcd.print("fingerprint"); }
void loop(){
if(flag==0){
value = VerifyUser();
if(Verify_flag){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Verify Successfully");
lcd.setCursor(0, 1);
lcd.print(name[value-1]);
flag = 1; }
else{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Fail to verify");
if(value == ACK_NO_USER){
lcd.setCursor(0, 1);
lcd.print("No such user");
delay(2000);
lcd.setCursor(0, 0);
lcd.print("Please enter your");
lcd.setCursor(0, 1);
lcd.print("fingerprint"); }
else{
lcd.setCursor(0, 1);
lcd.print("Time out"); } }
delay(1000); }
if(flag==1){
if (time ==0){
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("Success Unlocked");
digitalWrite(clockwise,HIGH);
delay(5500);
digitalWrite(clockwise,LOW);
time=1; }
if(time==1){
lcd.begin(16, 2);
lcd.print("RPM= 0");
lcd.setCursor(0, 1);
lcd.print("V= 0");
int RPM;
int V;
int priorState=LOW;
int StateChanges=LOW;
for (int i=0;i<5000;i++){
currentState=digitalRead(hallPin);
if (priorState!=currentState){
StateChanges++; }
priorState=currentState;
delay(1);}
RPM=(StateChanges/2);
V=(RPM*tireCircumf/4);
Serial.print("StateChanges=");
Serial.println(StateChanges);
Serial.print("RPM=");
Serial.println(RPM);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RPM= ");
lcd.setCursor(5, 0);
lcd.print(RPM);
lcd.setCursor(0, 1);
lcd.print("V= ");
lcd.setCursor(5, 1);
lcd.print(V); } } }
/******************串口发送子程序bit SendUART(U8 Scnt,U8 Rcnt,U8 Delay)******/
/*功能:向DSP发送数据********************************************************/
/*参数:Scnt发送字节数;Rcnt接收字节数; Delay延时等待数*********************/
/*返回值:TRUE 成功;FALSE 失败**********************************************/
byte TxAndRsCmd(byte Scnt, byte Rcnt, byte Delay)
{ byte i, j, CheckSum;
unsigned long RsTimeCnt;
Serial2.write(CMD_HEAD); //标志头
CheckSum = 0;
for (i = 0; i < Scnt; i++)
{ Serial2.write(gTxBuf[i]);
CheckSum ^= gTxBuf[i]; }
Serial2.write(CheckSum);
Serial2.write(CMD_TAIL);
Serial2.flush();
gRsLength = 0;
RsTimeCnt = Delay * 120000;
delay(200);
while (gRsLength < Rcnt && RsTimeCnt > 0){
if (Serial2.available()) in_byte = Serial2.read();
RsTimeCnt--;
gRsBuf[gRsLength++]=in_byte; }
if (gRsLength != Rcnt)return ACK_TIMEOUT;
if (gRsBuf[0] != CMD_HEAD) return ACK_FAIL;
if (gRsBuf[Rcnt - 1] != CMD_TAIL) return ACK_FAIL;
if (gRsBuf[1] != (gTxBuf[0])) return ACK_FAIL;
CheckSum = 0;
for (j = 1; j < gRsLength - 1; j++) CheckSum ^= gRsBuf[j];
if (CheckSum != 0) return ACK_FAIL;
return ACK_SUCCESS; }
/******************查询用户总数子程序******************/
/*功能:查询用户总数 **********************************/
/*参数 无 *********************************************/
/*返回值:用户总数 0xFF:失败***************************/
byte GetUserCount(void)
{ byte m;
gTxBuf[0] = CMD_USER_CNT;
gTxBuf[1] = 0;
gTxBuf[2] = 0;
gTxBuf[3] = 0;
gTxBuf[4] = 0;
m = TxAndRsCmd(5, 8, 10);
if (m == ACK_SUCCESS && gRsBuf[4] == ACK_SUCCESS)
{ return gRsBuf[3]; }
else
{ return 0xFF;} }
//删除所有指纹
byte ClearAllUser(void)
{ byte m;
gTxBuf[0] = CMD_DEL_ALL;
gTxBuf[1] = 0;
gTxBuf[2] = 0;
gTxBuf[3] = 0;
gTxBuf[4] = 0;
m = TxAndRsCmd(5, 8, 50);
if (m == ACK_SUCCESS && gRsBuf[4] == ACK_SUCCESS)
{ return ACK_SUCCESS;}
else
{ return ACK_FAIL; } }
byte IsMasterUser(byte UserID)
{ if ((UserID == 1) || (UserID == 2) || (UserID == 3)) return TRUE;
else return FALSE; }
//比对指纹
byte VerifyUser(void)
{ byte m=0,times=0 ;
gTxBuf[0] = CMD_MATCH;
gTxBuf[1] = 0;
gTxBuf[2] = 0;
gTxBuf[3] = 0;
gTxBuf[4] = 0;
while(1){ m = TxAndRsCmd(5, 8, 150);
if ((m == ACK_SUCCESS) && IsMasterUser(gRsBuf[4]))
{ Verify_flag = 1;
return gRsBuf[3]; }
else if(gRsBuf[4] == ACK_NO_USER)
{ Verify_flag = 0;
return ACK_NO_USER; }
else if(gRsBuf[4] == ACK_TIMEOUT)
{ times++;
delay(500);
if(times>TIMEOUT) {
Verify_flag = 0;
return ACK_GO_OUT; } }
delay(500);} }
    图1
    图2