单片机创意小制作,GPS记录器DIY
全球定位系统,小名GPS,大家一定不陌生,对于我们来说,它只有一个功能——定位,说白了,就是它能告诉我们现在所处的经纬度。
虽然功能简单,可由此衍生出来的应用可就不少了,比如车载导航仪,不光能告诉我们现在在哪,还能告诉我们怎么去想去的地方;又如某个车队要了解车辆的位置,那就给每个车子装个GPS和无线收发设备,实时了解车辆信息。
图12.1 GPS 记录器的显示界面
除此之外,还有些另类的应用:比如 GPS授时,所谓授时,就是告诉我们现在几点钟了。虽然这有点大材小用的意思,不过这时间是相当准确的,可以精确到毫秒级,可以作为许多应用的标准时钟。再有就是今天我们要DIY的这个“GPS 记录器”(见图12.1)了,简单来说,就是把我们所经过的位置记录下来的装置。有人要问了,这有什么用呢?假如有驴友旅行过程中发现一段非常漂亮的路径,路上湖光山色,风景秀丽,他就可以利用这个装置将路径记录下来和朋友们分享;假如探险家外出探险,也可以利用这个装置将路径记录下来,探险结束后按原路安全返回。这,就是路径回溯功能。
接下来让我们了解一下必备的基础知识。
GPS原理简介
GPS应用已经非常普及,现在很多手机都集成了GPS导航的功能,但是光有导航仪或者是GPS接收器是不行的,它还得有天上挂着的24颗卫星作为信号的来源。这24颗卫星就像草莓外面的籽一样均匀地分布在地球上空,基本上在全球任意地方都能接收到GPS卫星的信号。接收器根据卫星发送的含有报文的信号来计算处于哪个位置。除此之外,我们不能将卫星发射上去之后就不管了,所以,地球上还有地面中心对这些卫星进行监控和数据修正。所以,完整的GPS系统包括 GPS卫星、用户接收端、地面监控中心。
图12.2 解析流程
GPS 接收端与通信协议
上面讲的GPS系统包含3部分,但是我们平时能接触到的只有接收端。别看现在市面上各种牌子的导航仪和接收器数不胜数,但上面用的GPS接收处理的芯片,全球就只有几家公司有能力设计。其中,SiRF的芯片占据了民用市场七八成的份额,而目前用的比较多的是2004年发布的SiRFstar III,也就是所谓的“第3代”芯片。
接下来就是让其他产品能“听懂”从GPS芯片发出的数据是什么意思了,这时就需要有个通信协议。目前大部分GPS模块采用的是NMEA0138协议。这个协议涵盖了许多方面,GPS只是用到其中的一部分。
NMEA 协议简介
NMEA 是由美国全国海洋电子协会(The National Marine Electronics Association)制定的一套通信协议,是目前GPS最常见的通信协议。
以笔者的这个GPS 模块为例,它将接收到的GPS卫星信号解码之后,通过串口以NMEA格式输出,而用到的语句只有4个:$GPGGA、$GPGSA、$GPGSV、$GPRMC,其中美元符号($)代表前缀,表示语句开始;GP 代表对象,代表用在 GPS 上;后面的GGA、GSA、GSV、RMC等是语句类型;每条语句的各个数据字段用半角逗号(,)分开;结尾为*XX,XX 是整个语句的校验和,以检验收到的语句是否正确,代表回车和换行,表示该条语句结束。
我们所要做的就是将其接收下来,解析出我们要的数据,再进行下一步的应用。
数据解析和保存
有了从模块那里收到的数据,接下来就是解析出里面有用的数据了。图12.2所示为简单的解析流程。
由于使用的是单片机,所以最简单的保存数据的方案便是使用SPI接口的Flash。另外由于NMEA语句是为了便于传输,采用字符形式,所以“身材”比较大,基本上每次的数据量在300~500字节,由于Flash容量限制,不能将原始的NMEA 语句直接保存,所以我们自己定义了一个存储格式,将其中有用的数据摘出来以二进制的格式保存,这样每次的数据顺利地缩小了。在实际应用中,每个点的数据只需要32字节。
如何浏览路径
说到这里,就必须请出神器——Google Earth了。这是谷歌出的一款可以看卫星图的软件,可惜的是目前的6.0 版还不能直接支持 NMEA 协议。不过 Google Earth 支持另外一种语言,那就是KML。其全称是Keyhole Markup Language,基于XML,同样,它包含了很多复杂和高级的内容,在此不再赘述,我们只需要用到其中一部分——在Google Earth 中画路径。
下面是一个最简单的KML示例:Path from GPS Logger V2
Path Name
这个KML文件被Google Earth读取后会生成:
简单来说,它告诉Google Earth,生成一个文档,名字为Path from GPS Logger V2,其中有一个路径,名字叫Path Name,路径的是“连线”的模式,颜色为黄色(ff00ffff),线宽5像素,而具体经纬度信息则包含在标签中,继而Google Earth会根据其中的经纬度信息绘制出一条折线。
所以,只要将之前保存的每个点的数据,依次填充到标签中,则生成的KML被Google Earth读取之后显示的就是我们记录的路径。
至此,我们自制记录器所需要了解的背景都全部知道了,接下来便是制作的过程了。
主要功能目标
直接显示当前日期和时间、经纬度、海拔、速度、方向等信息,显示卫星信号强度、卫星数目、分布情况等。
将位置信息记录到存储器中,并显示当前空间使用情况。板载的Flash可用保存50994个记录点,按每秒一次计,可连续记录14小时。当空间满了之后,可以将数据转存至TF卡之后重新记录。可实时浏览存储器中的数据,也可将存储器中的记录导出,或者转换成 Google Earth可以识别的KML格式。
图12.3 GPS 记录器的模块框图
GPS 记录器的设计
GPS记录器的模块框图如图12.3所示。数据通信方面,GPS模块通过串口与MCU通信,TF卡和SPI Flash则分别挂载在两个硬件SPI上,LCD通过并行方式与MCU连接。供电方面,采用锂电池(自带过充过放保护电路)供电,由于GPS内置了LDO(低压差线性稳压器),所以直接与电池连接;另外一路则经3.3V LDO输出给MCU、LCD、Flash和TF卡供电;同时,用STM32自带的ADC模数转换测出锂电池的电压,以此估算剩余电池电量。图12.4为根据框图设计出的PCB原理图。
图12.4 GPS 记录器的PCB 原理图
绘制 PCB
根据液晶显示屏的尺寸,确定了主控板的大小。元器件不多,所以PCB尺寸只有显示屏的1/2左右。制作完成的PCB图与实物如图12.5所示。
表12.1 制作所需原材料和元器件
图12.5 制作完成的PCB图与实物
图12.6 焊接完元器件的PCB
图12.7 GPS 模块通过支架来安装,电池也加以更换
焊接元器件和PCB调试
笔者的习惯是焊接完一部分立刻检测该部分是否能正常工作,这样可以尽早发现问题并快速判断出问题源。
在焊接之前,目测一下板子是否有断路或短路的情况,然后用万用表测量电源正负极之间是否短路。
首先焊接电源部分,将USB座、LDO稳压管和充电芯片及阻容元件焊上,然后供电,测量输出是否为3.3V,有条件的话,还可以接在示波器上看看输出的电压是否纯净。
在LDO输出和整版的供电之间,笔者增加了一个0Ω的电阻,这个电阻可作为跳线使用,断开后可以检测芯片部分是否有短路等情况,调试完成后可直接短接导通。
电源部分完成后,接下来焊接单片机和外围的晶体振荡器、复位电路,组成最小系统。要判断单片机是否能运行起来,可以将板上的两个LED也装上,然后编写一个测试程序,循环点亮和熄灭,如果成功,则表明单片机基本正常。
最后焊接Flash芯片、TF卡座、按键等。
至此,原来的空PCB已经比较像一块电路板了,如图12.6所示。
一般来说,使用陶瓷天线的GPS模块需要尽量使天线面向天空,这样才能尽可能地接收信号,所以安装GPS模块的时候设计了一个支架,使得模块天线与接收器成45°角,平时手持的时候刚好面向天空,即使平放或立着放都能部分面向天空,如图12.7所示。另外,还为模块换了一个备用电池。
全部元件组装完成后的样子如图12.8所示。装上电池和后盖,如图12.9所示,硬件装配至此就完成了。
软件设计思路与调试
由于功能简单,软件不需要复杂的结构,流程如图12.10所示。开机初始化完成后,系统便进入无限主循环中,循环检查GPS是否接收完毕,是否有按键按下。
图12.8 全部元器件组装完毕的样子
图12.9 装上电池和后盖
GPS接收和解析使用了中断,当接收完成后,设置标志位,主循环检测到数据接收完成,便将数据显示在LCD上,如果设置需要记录,则再记录到SPI Flash中。
如果“菜单”按键被按下,则转到菜单函数;如果“显示模式”按键被按下,则切换显示模式;如果“记录”按键被按下,则切换是否记录到SPI Flash中。
图12.10 软件流程框图
操作方式和界面
记录器上部有4个按钮,用途分别为“菜单/退出”、“上一个/显示模式”、“下一个/记录模式”、“确定”。
常规显示时屏幕分为3个区域,顶部显示电池电量、卫星信息、时间等,中间用大字体显示当前经纬度,下半屏则根据显示模式分别显示卫星信息、速度航向和记录信息3种模式。按“显示模式”按键可以在3种模式中循环切换,如图12.11所示。
图12.11 显示屏下半部具备3种显示模式
图12.12 将数据存储到 TF 卡中
按“记录模式”键可以切换记录开始和停止模式。按“菜单”键可进入功能菜单。选择“菜单→转储→TF卡(KML)”可将存储器中的数据以KML文件的格式转存到TF卡中,如图12.12所示。选择“菜单→转储→TF卡(转储)”可将存储器中的数据以原始二进制格式存到TF卡中。
转储之后,在TF卡的GPS目录中就会有已经生成好的KML 文件,如果装了 Google Earth,就会出现如图12.13所示的图标。
图12.13 存储在TF卡中的KML文件
直接双击之后会自动打开 Google Earth,黄色的连线就是我们记录下的路径,如图12.14所示。
图12.14 GPS记录器记录下的路径可在 Google Earth 中显示
选择“菜单→浏览记录”可以实时浏览存储器中记录的路径和记录点的信息,并能直观地了解存储器空间使用情况,如图12.15所示。选择“菜单→擦除空间”,可将数据擦除,继续记录,如图12.16所示。
后记
其实市场上早已有产品化的GPS记录器,而且成本更低、功能更强,但是DIY的乐趣在于更深地了解其中的原理,以及发挥自己的想象力,根据自己的需要定制。比如,还是这套硬件,通过修改软件,还能实现GPS测面积的功能。
图12.15 实时浏览存储器中记录的路径和记录点的信息
图12.16 擦除记录
用个8位单片机+sim900a+gps模块自制建议定位装置
gps定位器是一个被广泛使用的小工具,说不定你老婆就在你的身上放了一个。这玩意很容易买的到。当然自己做一个也可以,毕竟看这内容的人一般都是单身狗。
需要材料,一款diy界网红arduino uno,采用8位AVR单片机,自带bootloader和一大推的支持库。配合arduino开发环境可以快速简单的编写arduino的程序。
一个ICOMSAT扩展板,集成收发短信的sim900模块
一个GPS shield扩展板
这些都是扩展版,直接堆叠插在一起就好了,第一层是arduino uno(这是废话),第二层是ICOMSAT扩展板,第三层是GPS shield扩展板。这就是arduino的魅力,拥有大量的周边扩展模块,直接连接。让没有硬件开发知识人,只要会简单的c语言就可以玩转arduino。
首先对ICOMSAT扩展板操作,开关拨到UART的一端,跳线帽按照RXD->D2,TXD->D3如图,接上GSM天线和插上手机SIM卡。详细跳帽和引脚请下载查阅产品手册和原理图
然后对GPS shield扩展板操作,开关拨到5V,跳线帽按照RXD->D1,TXD->D0如图连接,接上GPS天线
最后按照顺序把三个家伙给堆起来
在编译程序之前我们需要下载arduino的gsm和gps的支持库,解压后放在Arduino\libraries的目录下
下面是程序代码复制粘帖过去IDE中,编译好后下载到arduino中就好了
#include "SIM900.h"
#include <SoftwareSerial.h>
//#include "inetGSM.h"
#include "sms.h"
//#include "call.h"
#include <string.h>
#include <TinyGPS.h>
/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/
TinyGPS gps;
#define ledpin 13
#define pwrkey 27
//**************************************************************************
char sms_rx[122]; //Received text SMS
byte type_sms=SMS_ALL; //Type of SMS
byte del_sms=1; //0: No deleting sms - 1: Deleting SMS
char number_incoming[20];
//**************************************************************************
SMSGSM sms;
int error;
boolean started=false;
bool newData = false;
char gps_year[8];
char gps_mon[3];
char gps_day[3];
char gps_hour[3];
char gps_min[3];
char gps_sec[3];
char gps_lon[20];
char gps_lat[20];
char gps_sms[100];
void setup()
{
//software power sim900 up
pinMode(pwrkey,OUTPUT);
digitalWrite(pwrkey,HIGH);
delay(600);
digitalWrite(pwrkey,LOW);
Serial.begin(115200);
Serial2.begin(9600);
if (gsm.begin(9600)) {
Serial.println("\nstatus=READY");
gsm.forceON(); //To ensure that SIM908 is not only in charge mode
started=true;
} else Serial.println("\nstatus=IDLE");
if(started)
{
//delete all sms message
Serial.println("Deleting SMS");
char error = DeleteAllSMS();
if (error==1)Serial.println("All SMS deleted");
else Serial.println("SMS not deleted");
}
else
{Serial.println("SIM900 NOT EXISTED"); while(1);}
delay(10000);
}
void loop()
{
if(started)
{
check_gps();
Check_SMS();
}
}
void Check_SMS() //Check if there is an sms 'type_sms'
{
char pos_sms_rx; //Received SMS position
pos_sms_rx=sms.IsSMSPresent(type_sms);
if (pos_sms_rx!=0)
{
//Read text/number/position of sms
sms.GetSMS(pos_sms_rx,number_incoming,sms_rx,120);
Serial.print("Received SMS from ");
Serial.print(number_incoming);
Serial.print("(sim position: ");
Serial.print(word(pos_sms_rx));
Serial.println(")");
Serial.println(sms_rx);
if (del_sms==1) //If 'del_sms' is 1, i delete sms
{
error=sms.DeleteSMS(pos_sms_rx);
if (error==1)Serial.println("SMS deleted");
else Serial.println("SMS not deleted");
}
if((strstr(sms_rx,"gps")!=0)&&(strlen(sms_rx)==3))
{
Serial.println("\nsending SMS");
if(newData)
{
if (sms.SendSMS(number_incoming, gps_sms))
Serial.println("\nSMS sent OK");
else
Serial.println("\nSMS sent error");
}
else
{
if (sms.SendSMS(number_incoming, "gps not ready"))
Serial.println("\nSMS sent OK");
else
Serial.println("\nSMS sent error");
}
}
Serial2.flush();
}
newData=false;
return;
}
char check_gps()
{
newData=false;
unsigned long chars;
unsigned short sentences, failed;
// For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (Serial2.available())
{
char c = Serial2.read();
// Serial.write(c); // uncomment this line if you want to see the GPS data flowing
if (gps.encode(c)) // Did a new valid sentence come in?
newData = true;
}
}
if (newData)
{
float flat, flon;
unsigned long age;
int _year;
byte _month, _day,_hour,_minute,_second,_hundredths;
gps.f_get_position(&flat, &flon, &age);
gps.crack_datetime(&_year,&_month,&_day,&_hour,&_minute,&_second,&_hundredths,&age);
flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6;
flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6;
dtostrf(flat, 11, 6, gps_lat);
dtostrf(flon, 10, 6, gps_lon);
strcpy(gps_sms,"lat:");
strcat(gps_sms,gps_lat);
strcat(gps_sms,"\n");
strcat(gps_sms,"lon:");
strcat(gps_sms,gps_lon);
strcat(gps_sms,"\n");
strcat(gps_sms,"time:");
itoa(_year,gps_year,10);
strcat(gps_sms,gps_year);
itoa(_month,gps_mon,10);
if(strlen(gps_mon)==1)
strcat(gps_sms,"0");
strcat(gps_sms,gps_mon);
itoa(_day,gps_day,10);
if(strlen(gps_day)==1)
strcat(gps_sms,"0");
strcat(gps_sms,gps_day);
itoa(_hour,gps_hour,10);
if(strlen(gps_hour)==1)
strcat(gps_sms,"0");
strcat(gps_sms,gps_hour);
itoa(_minute,gps_min,10);
if(strlen(gps_min)==1)
strcat(gps_sms,"0");
strcat(gps_sms,gps_min);
itoa(_second,gps_sec,10);
if(strlen(gps_sec)==1)
strcat(gps_sms,"0");
strcat(gps_sms,gps_sec);
Serial.println(gps_sms);
}
}
char DeleteAllSMS()
{
char ret_val = -1;
if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val);
gsm.SetCommLineStatus(CLS_ATCMD);
ret_val = 0; // still not present
gsm.SimpleWriteln(F("AT+CMGDA=\"DEL ALL\""));
switch (gsm.WaitResp(8000, 50, "OK")) {
case RX_TMOUT_ERR:
// response was not received in specific time
ret_val = -2;
break;
case RX_FINISHED_STR_RECV:
// OK was received => SMS deleted
ret_val = 1;
break;
case RX_FINISHED_STR_NOT_RECV:
// other response: e.g. ERROR => SMS was not deleted
ret_val = 0;
break;
}
gsm.SetCommLineStatus(CLS_FREE);
return (ret_val);
}
通过9v电池供电或者是充电宝usb供电,把做好的三层不明物体放在开阔的地方,想arduino的手机号码发送“gps”短信,之后会收到一个回信,内容为
lat:23.036960
lon:114.418800
time:20170919114516
lat表示纬度,lon表示经度,time表示时间,不过是“格林尼治时间”(本初子午线)不是北京时间,和北京时间相差8小时。不会算的回去学地理。
如果你收到“gps not ready”回信,那就是说明没有搜到gps卫星,等一下或者是换个地方。
相关问答
怎样把 GPS 得到的经纬度转换为详细位置-ZOL问答1.实现将一组GPS模块获取的经纬度数据在百度地图上绘制轨迹2.标准的GPS经纬度坐标直接在地图上绘制会有偏移,这是测绘局和地图商设置的加密,要转换成百度地图坐...
rxd 单片机 引脚干什么的?51单片机的串口工作模式如果选择为模式0时,就是同步移位寄存器的模式。这种模式与其它三种不同:其它三种都是一般意义上的异步串行通讯模式,接收信息使用RXD...
高德地图 gps 需要经纬度转换吗-ZOL问答单就51单片机与GPS模块通讯而言,获得的经纬度已经是空间坐标最准确的信息了。你只需要将经纬度通过GPRS模块传给客户端即可。客户端根据经纬度数据从地图数据...
51 单片机 编程有什么用?51单片机作为学习单片机的过程中必须要经过的一个过程来讲是非常重要的,原因在于51单片机从内部的硬件到软件有一套完整的按位操作系统,称作位处理器,处理对象...
如何重新复位 gps 信号?在可编程的芯片(如单片机),可编程控制器(PLC),微机等电子设备的运行中,会出现程序跑飞的情况或程序跳转,可用手动或自动的方法发给硬件特定接口使软件的运...
单片机 主要应用于哪些领域? - 潘耶耶- 的回答 - 懂得1.单片在一个系统中只使用一片机,这是目前应用最多的一种方式。主品单片机与传统的机械产品相结合,使传统的机械产品结构简单化、控制智能化,构成了...
怎么让手机 gps 定位到其他地方?你的意思是欺骗GPS吗?那就需要一个GPS模拟器来产生一个假信息了。不过那个东西很贵哦更简单的办法是把里面的GPS数据线断开,引出来,用单片机产生一个想要的位...
GPS 车辆管理系统多少钱?[回答]选择什么样的GPS主要看个人用途,应用较多的是出租车、公交车、私家车等等车辆,根据自己的需求,选择合适的,具体可以咨询安徽星踪有限公司。1)硬件...
GPS 车辆管理系统多少钱?[回答]选择什么样的GPS主要看个人用途,应用较多的是出租车、公交车、私家车等等车辆,根据自己的需求,选择合适的,具体可以咨询安徽星踪有限公司。1)硬件...
基于 单片机 的超速报警是什么意思?超速报警软件包含了GPS测速、超速报警、语音报速、记录行进轨迹、查看历史轨迹、记录出行时间、记录出行里程等功能。超速报警软件包含了GPS测速、...