资源描述
基于GPS和Zigbee的高速路段区域智能应急预警系统
摘要:本系统设计出一个安全系数更好的基于GPS和Zigbee的高速路段区域智能应急预警系统。如今高速路段车祸频发,尤其是重特大的连环碰撞事故的发生,更是以我们宝贵的生命为代价。而我们还没有一套完善的预警系统可以帮助我们有效的减少连环追尾事故的发生。本系统正是从一个全新的技术和思维领域所设计的一套预警系统,利用GPS和物联网技术等,可有效的时时反映区域内各车的运行状态,帮助司机有效的了解路段和有效的预防追尾等事故。尤其是在雨雾冻等恶劣环境下做到有效的预警。
关键词:Zigbee;GPS;时时反映;有效预警
Abstract: This system is a safety coefficient of GPS and Zigbee better based on the high speed road area intelligence emergency alert system. Now the road traffic accident occur frequently, and especially the serial collision and great accidents, and we still don't have a perfect early warning system can help us reduce serial car tracing cauda accidents. This system is from a new technology and unique thought field of design a warning system, using GPS and physical networking technology, and so on, can be effective always reflect regional inside the car operation state, effective prevention car tracing cauda wait for an accident, Especially in the rain fog frozen and a harsh environment.
Key word: Zigbee; GPS; Always reflect; Effective warning
1. 系统简介
1.1系统方案
本系统的设计思路是:本系统通过构建终端--基站模式,为驾驶员提供多种安全保障,并以其经济性确立其可行性,终端、基站成本低廉,且前景广阔,具备可投资性,可拓展性、可维护性并为本系统后期长久发展提供保障,具备长久支持性。结合Zigbee模块的区域组网性,将高速路划分为多个区域,每一个区域内的网关类似于通信中的基站。当一辆车进入这个区域覆盖的范围内,该车的Zigbee模块就会通过组网的协议自动加入这个小区的网关,成为网关中的一个子节点。当组网完成后,该车的系统单片机就会解码GPS的数据并组包通过Zigbee模块发送给网关,网关接收到数据后进行解析,如果该车为新加入车,则会为该车建立一个临时的编号,类似于通信中的“漫游”,并将数据存储在该编号的结构体下;如果该车以前已经在网关中,这组数据为更新包,则继续使用临时编号,但更新该车的信息。之后通过网关的一系列数据处理,将离该车最近的一辆车的信息和两车车距回送给该车,该车接收到回送数据,通过处理显示到TFT屏幕中,并对数据进行适当的预警。如LED等的闪烁和蜂鸣器的鸣叫等。
1.2创新说明
1、物联网技术:随着物联网的迅速发展,物体使用的智能化、人性化发展的思想也得到极大地促进,我们也从这一思想得到启发,并结合高速行车实际,我们预计开发一套高速全程安全预警系统,为交通运输行业提供相应保障。本系统使用780MHZ频段,该频段十分“干净”。
2、基站--终端模式:本系统初步研究其实现性,极大程度的考虑可拓展性、可维护性和经济性,决定采用类似于现行3G网络的基站--终端模式。使用基站共享本区域车辆信息,为驾驶员提供本区域的视野,大幅提高驾驶员行车安全性。通过车载终端和基站交换本区域适用信息,基站实时维护本区域车辆信息,达到交互的实时性,并通过基站的结构体链表的实现,充分满足系统的拓展性及可维护性,满足系统后期需求更新。
3、拓展性:本系统通过构建终端--基站模式,为驾驶员提供多种安全保障,并以其经济性确立其可行性,终端、基站成本低廉,且前景广阔,具备可投资性,初步可为驾驶员提供:超车预警,追尾预警,堵车预警,事故智能报警,事故责任索赔追责等多项具有现实意义的相关服务。
4、 可维护性:本系统基站为独立模块,只包含电源模块、Zigbee模块、和单片机模块具有低功耗等特点,可使用太阳能供电。基站的生存性好。节点模块置于车内,使用车载电源,可通过面板设置节点相关参数。
5、群控性:本系统需求更高级群控管理系统,基于本系统的群控系统,通过有效的方式解决网关的联网性,可得到全高速路段的节点信息,实现群控。即可通过网关控制系统以“广播的形式”操作整个高速路段运行车辆。
6、可移植性:可移植到arm平台,通过qt编程,将节点信息与导航地图 整合,实现一个交互的可在地图上显示区域内所有节点位置和预警事故地点的预警系统。
1.3功能与指标
功能:本系统是从一个全新的技术和思维领域所设计的一套预警系统,利用GPS和物联网技术等,可有效的时时反映区域内各车的运行状态,帮助司机有效的了解路段和有效的预防追尾等事故;尤其是在雨雾冻等恶劣环境下做到有效的预警。
指标:按照2.5km的距离设立基站,后期可通过增大发射功率,或使用陶瓷等增益更大的天线,或利用模块的透传功能等方法进一步的增大基站设立的距离,在弯道和特殊地质等路段可适当紧密一点。各基站初始容量为256个。即区域网关可注册256辆车,这在正常情况的高速路段完全够用。为得到经纬度,航向,速度等信息,对于GPS数据只解析$GPRMC数据包,并打包车型,车牌等一些信息发送给网关。当车距相距小于200米时,LED闪烁5次,当车距小于50米时,蜂鸣器就会鸣叫5次。TFT屏幕显示的数据内容有:最近车距;最近车速;最近车型;最近车牌;区域内总车数等信息。
1.4实现原理
1.4.1 GPS模块-------REB-3571LP
GPS 上电后,每隔一定的时间就会返回的数据,格式为:$ 信息类型, x,x,x,x,x,x,x,x,x,x,x,x,x。结合系统数据的实际需要我们将解析GPRMC数据包。该数据包完整的数据如下:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
$GPRMC,080655.00,A,4546.40891,N,12639.65641,E,1.045,328.42,170809,,,A*60
注:<2> 定位状态, A= 有效定位, V= 无效定位
<3> 纬度 ddmm.mmmm( 度分 ) 格式
<4> 纬度半球 N( 北半球 ) 或 S( 南半球 )
<5> 经度 dddmm.mmmm( 度分 ) 格式
<6> 经度半球 E( 东经 ) 或 W( 西经 )
<7> 地面速率
<8> 地面航向 (000.0~359.9 度)
1.4.2 Zigbee模块------- HMD40201
HMD40201 网络协调器模块是瀚之显具有自主知识产权 VNET 网络平台的组成部分,收发机部分是基于 IEEE802.15.4 国际标准而构建,MCU 部分则是采用低功耗、高效率 的COTEX-M3 核 。HMD40201 使用的是 WPAN 中国频段 779MHZ~787MHZ (UHF 频带 Sub 1 G频段 ),在物理层采用先进的 DSSS 直序扩频技术,支持 BPSK 和 O-QPSK 两种调制模式,多种空中传输速率,与2.4GHZ 频段比对,具有良好的穿透力 、绕射性能、抗衰减能力等电磁特性,这些特性可以较好的应对建筑物和楼群等复杂通讯条件下电磁信号杂化( 多路径效应 ) 的挑战,适用于有密集阻挡环境 ( 如集抄项目和其它工业控制项目 ) 时通信效果不理想的环境, HMD40201 收发机采用了 CSMA/CA 碰撞避免的竞争机制,有效解决了网络数据碰撞的问题,并且物理层采用了数据收发校验,失败重发机制,保证了数据传输的安全性与稳定性。
接口方式:TTL 串口,115200,8,N,1,并提供 SPI 接口和 I2C 接口及更多 GPIO接口,资源丰富,方便二次开发;模块采用 1.27m m间距标准数据接口,通过插座进行连接,可以方便的接入用户底板。配置 I-PEX 射频天线端子,可选配多种增益的橡胶天线、吸盘天线等,满足实际需要;工作于 780M/920M 免费 ISM 频段,4 个可选信道,系统容量大;超低功耗设计,最大发射功率 5mW ,接收电流小于 10mA 。支持 IEEE 802.15.4 标准协议,超高抗干扰能力和低误码率,视距可靠传输距离远。
图1:Zigbee芯片实物图 图2:Zigbee引脚简图
1.4.3 单片机模块------- STC12C5A60S2
STC12C5A60S2/AD/PWM系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
a. 增强型8051 CPU,1T,单时钟/机器周期,指令代码完全兼容传统8051。
b. STC12C5A60S2系列有双串口。
1.4硬件框图
节点: Zigbee
GPS
报警器
电源
单片机
显示屏
控制模块
图3:节点硬件框图
网关:
Zigbee
电源
单片机
图4:网关硬件框图
1.5软件流程
节点:
系统加电启动
单片机发送组网命令
NO
Zigbee组网成功?
YES
单片机采集GPS数据信号
单片机解析GPS数据,并做相应打包
通过Zigbee模块发送给基站
等待回送数据
接受并处理回送数据
显示、报警
图5:节点程序框图
网关:
系统加电启动
单片机接受组网命令
NO
Zigbee组网成功?
YES
单片机接受节点数据
注册或者更新节点数据
处理已注册的交互信息
单片机组建通信协议回送给相应节点
等待处理下一个节点数据
打开接受串口
图6:网关程序框图
2.PCB和实物图
图7:PCB底层铺铜
图8:系统原理图
图9:系统实物图(俯视)
图10:系统实物图(侧视)
3. 程序
3.1网关程序:
#include <reg52.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define uchar unsigned char
#define PI 3.1415926535898
#define EARTHR 6371004
uchar xdata mark=0;
uchar xdata rev_buf[36];//Receive buffer
uchar xdata send_buf[38];//send buffer
uchar xdata distance_hun,distance_others;
uchar xdata rev_start = 0; //Receive start mark
uchar xdata rev_stop = 0; //Receive stop mark
uchar xdata num = 0; //
uchar xdata tmp;
uchar xdata i,j,m,k;
uchar xdata exist_flag;
uchar xdata car_all=0;
uchar xdata second=0;
uchar xdata send_flag=1;
uchar xdata dev_flag=0;
int xdata tmp_dis=1500;
int xdata distance;
uchar xdata reflash=0;
xdata struct Car{
uchar car_number[8];
uchar car_type;
uchar speed;
};
xdata struct Disp{
float direction;//same direction
float weidu;
float jingdu;
struct Car close_in;
struct Car itself;
uchar time;
uchar free; //flag
uchar car_num;
};
xdata struct Disp disp_all[4]; //should not to be too large
float dfm_chang_du(unsigned char GPS_Degree,unsigned char GPS_Point,float GPS_Second,float GPS_Sec)
{ float data1= GPS_Sec/100;
data1=data1+GPS_Second;
data1=data1/60;
data1=data1+GPS_Point;
data1=data1/60;
data1=data1+GPS_Degree;
return data1;
}
double D_jw(float LatFrom,float LonFrom,float LatTo,float LonTo)
{
double LatFrom1,LonFrom1,LatTo1,LonTo1,LonDiff;
double Temp1,Temp2,Temp3;
double Distance;
LatFrom1=LatFrom*PI/180;
LonFrom1=LonFrom*PI/180;
LatTo1=LatTo*PI/180;
LonTo1=LonTo*PI/180;
LonDiff=LonTo1-LonFrom1;
Temp1=cos(LatTo1)*sin(LonDiff);
Temp1=Temp1*Temp1;
Temp2=cos(LatFrom1)*sin(LatTo1)-sin(LatFrom1)*cos(LatTo1)*cos(LonDiff);
Temp2=Temp2*Temp2;
Temp3=sin(LatFrom1)*sin(LatTo1)+cos(LatFrom1)*cos(LatTo1)*cos(LonDiff);
Distance=atan(sqrt(Temp1+Temp2)/Temp3);
Distance=EARTHR*Distance;
return Distance ;
}
void Uart_Init1(void)//115200bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
TR0 = 1; //start the timer0
SM0=0;
SM1=1;
EA=1;
REN=1; //Allows the receiving data
ES=1;
}
void Struct_init()
{
for(i=0;i<4;i++)
{
disp_all[i].itself.car_number[0]=0x00;
disp_all[i].itself.car_number[1]=0x00;
disp_all[i].itself.car_number[2]=0x00;
disp_all[i].itself.car_number[3]=0x00;
disp_all[i].itself.car_number[4]=0x00;
disp_all[i].itself.car_number[5]=0x00;
disp_all[i].itself.car_number[6]=0x00;
disp_all[i].itself.car_number[7]=0x00;
disp_all[i].free=0;
disp_all[i].car_num=0;
}
}
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{
Uart_Init1();
Struct_init();
while (1)
{
if(rev_stop)
{ rev_stop=0;
//transfer the bcd code to dec code then the folling can processing it.
exist_flag=0;
for(i=0;i<4;i++)//Update the device information
{
if(disp_all[i].free)
{ //just mark the last byte to identity the car is exist?
if(disp_all[i].itself.car_number[7]==rev_buf[19])
{
exist_flag=1;
// red=~red;
//just adjust the car's gps information on time.
disp_all[i].car_num=car_all;
disp_all[i].direction=rev_buf[30]*100+rev_buf[31];
disp_all[i].weidu=dfm_chang_du(rev_buf[21],rev_buf[22],rev_buf[23],rev_buf[24]);
disp_all[i].jingdu=dfm_chang_du(rev_buf[25],rev_buf[26],rev_buf[27],rev_buf[28]);
// disp_all[i].weidu =(rev_buf[21]+(rev_buf[22]/60)+(rev_buf[23]+(rev_buf[24]/100)/3600))*PI/180;
// disp_all[i].jingdu=(rev_buf[25]+(rev_buf[26]/60)+((rev_buf[27]+rev_buf[28]/100)/3600))*PI/180;
disp_all[i].itself.speed=rev_buf[29];
disp_all[i].time=second;
disp_all[i].free=1;
disp_all[i].itself.car_number[0]=rev_buf[12];
disp_all[i].itself.car_number[1]=rev_buf[13];
disp_all[i].itself.car_number[2]=rev_buf[14];
disp_all[i].itself.car_number[3]=rev_buf[15];
disp_all[i].itself.car_number[4]=rev_buf[16];
disp_all[i].itself.car_number[5]=rev_buf[17];
disp_all[i].itself.car_number[6]=rev_buf[18];
disp_all[i].itself.car_number[7]=rev_buf[19];
mark=i;
reflash++;
break;
}
}
}
for(i=0;i<4;i++)//Register device information
{
if(!exist_flag)
{ if(!disp_all[i].free)
{
// led=~led;//test
disp_all[i].car_num = ++car_all;
disp_all[i].direction=rev_buf[30]*100+rev_buf[31];
disp_all[i].weidu=dfm_chang_du(rev_buf[21],rev_buf[22],rev_buf[23],rev_buf[24]);
disp_all[i].jingdu=dfm_chang_du(rev_buf[25],rev_buf[26],rev_buf[27],rev_buf[28]);
// disp_all[i].weidu=(rev_buf[21]+(rev_buf[22]/60)+(rev_buf[23]+rev_buf[24]/100)/3600)*PI/180;
// disp_all[i].jingdu=(rev_buf[25]+(rev_buf[26]/60)+(rev_buf[27]+rev_buf[28]/100)/3600)*PI/180;
disp_all[i].itself.speed=rev_buf[29];
disp_all[i].itself.car_type = rev_buf[32];
disp_all[i].free=1;
disp_all[i].time=second;
//juts copy the mac address to the array.
disp_all[i].itself.car_number[0]=rev_buf[12];
disp_all[i].itself.car_number[1]=rev_buf[13];
disp_all[i].itself.car_number[2]=rev_buf[14];
disp_all[i].itself.car_number[3]=rev_buf[15];
disp_all[i].itself.car_number[4]=rev_buf[16];
disp_all[i].itself.car_number[5]=rev_buf[17];
disp_all[i].itself.car_number[6]=rev_buf[18];
disp_all[i].itself.car_number[7]=rev_buf[19];
mark=i;
reflash ++;
break;
//make it clear,it does as the following code.
/******************************************
disp_all[i].itself.car_number[0]=rev_buf[12];
.....
diap_all[i].itself.car_number[7]=rev_buf[19];
********************************************/
}
}
}
for(j=0;j<4;j++)
{
if((j!=mark)&&disp_all[j].free&&disp_all[mark].free)
{
if(abs((int)(disp_all[j].direction-disp_all[mark].direction))<20)
{
//change the value to be a arc value,then can use it in the following code.
/* transfer=sin(disp_all[mark].weidu)*sin(disp_all[j].weidu)+
cos(disp_all[mark].weidu)*cos(disp_all[j].weidu)*cos(disp_all[j].jingdu-disp_all[j].jingdu);
distance = 111120*cos(1/transfer);*/
distance = (int)(D_jw(disp_all[mark].weidu,disp_all[mark].jingdu
,disp_all[j].weidu,disp_all[j].jingdu));
if(distance<tmp_dis) //
{
tmp_dis=distance;
tmp=j;
}
}
//just 20 second to reflash the struct Disp,to avoid the car leave the base tower's control space.
//i no sure about this number ,you can change it longer.
if(abs(disp_all[j].time-second)>=5)
{
disp_all[j].itself.car_number[0]=0x00;
disp_all[j].itself.car_number[1]=0x00;
disp_all[j].itself.car_number[2]=0x00;
disp_all[j].itself.car_number[3]=0x00;
disp_all[j].itself.car_number[4]=0x00;
disp_all[j].itself.car_number[5]=0x00;
disp_all[j].itself.car_number[6]=0x00;
disp_all[j].itself.car_number[7]=0x00;
disp_all[j].free=0;
car_all--;
}
}
}
//just find out the close_in car
if(tmp_dis!=1500)
{
disp_all[mark].close_in.car_number[0]=disp_all[tmp].itself.car_number[0];
disp_all[mark].close_in.car_number[1]=disp_all[tmp].itself.car_number[1];
disp_all[mark].close_in.car_number[2]=disp_all[tmp].itself.car_number[2];
disp_all[mark].close_in.car_number[3]=disp_all[tmp].itself.car_number[3];
disp_all[mark].close_in.car_number[4]=disp_all[tmp].itself.car_number[4];
disp_all[mark].close_in.car_number[5]=disp_all[tmp].itself.car_number[5];
disp_all[mark].close_in.car_number[6]=disp_all[tmp].itself.car_number[6];
disp_all[mark].close_in.car_number[7]=disp_all[tmp].itself.car_number[7];
disp_all[mark].close_in.car_type = disp_all[tmp].itself.car_type;
disp_all[mark].close_in.speed = disp_all[tmp].itself.speed;
distance_hun=tmp_dis/100;
distance_others=tmp_dis%100;
}
//send_back.disp=disp_all[i];
// Convect10To16(distance_hun,&buf[0]);
// Convect10To16(distance_others,&buf[1]);
//send_back.data_long=0x0F;
//reconstruct the data package;
//use the bcd code,this code should to be change,for the zigbee signaling have itself pricipline.
send_buf[0]=0xCC;
send_buf[1]=0xFF;
send_buf[2]=0x21;
send_buf[3]=0x67;
//send jiedian
send_buf[4]=disp_all[mark].itself.car_number[0];
send_buf[5]=disp_all[mark].itself.car_number[1];
send_buf[6]=disp_all[mark].itself.car_number[2];
send_buf[7]=disp_all[mark].itself.car_number[3];
send_buf[8]=disp_all[mark].itself.car_number[4];
send_buf[9]=disp_all[mark].itself.car_number[5];
send_buf[10]=disp_all[mark].itself.car_number[6];
send_buf[11]=disp_all[mark].itself.car_number[7];
//send gateway
send_buf[12]=0x86;
send_buf[13]=0x25;
send_buf[14]=0x01;
send_buf[15]=0x00;
send_buf[16]=0x01;
展开阅读全文