一板网电子技术论坛

风筝
发表于: 2018-1-15 11:50:36 | 显示全部楼层

本文主要介绍如何使用Arduino开发板连接NEO-6M GPS模块,然后获取GPS数据。 GPS全称全球定位系统,当你旅行时,它可以用来确定位置、时间和速度。

NEO-GPS-Arduino-thumbnail.jpg


NEO-6M GPS模块简介

NEO-6M GPS模块如下图所示。它带有一个外部天线,并没有附带插头引脚。所以,你需要自备以及焊接。

NEO-GPS-1.jpg

●    该模块带有一个外部天线,并且内置EEPROM。

●    接口:RS232 TTL

●    电源:3V至5V

●    默认波特率:9600 bps

●    支持标准的NMEA

NEO-6M GPS模块兼容其他的微控制器电路板。要了解如何在Raspberry Pi上使用NEO-6M GPS模块,您可以阅读以下链接:使用Raspberry Pi和GPS模块的位置变化的电子邮件报警系统


引脚接线

NEO-6M GPS模块有四个引脚:VCC、RX、TX和GND。该模块使用TX和RX引脚通过串行通信与Arduino开发板进行通信,所以接线特别简单:

NEO-6M GPS模块
Arduino UNO连线
VCC
5V
RX
软件串行通信中定义的TX引脚
TX
软件串行通信中定义的RX引脚
GND
GND

获取GPS原始数据

要获取原始的GPS数据,只需使用软件串口启动与GPS模块的串行通信。继续阅读,看看如何做到这一点。


所需材料

为了测试这个例子,你需要以下几个材料:

●    Arduino入门套件

●    NEO-6M GPS模块

●    跳线


原理图

按照以下原理图将NEO-6M GPS模块连接到您的Arduino开发板。

NEO_6M_Arduino.png

●    模块GND引脚连接到Arduino的GND引脚

●    模块RX引脚连接到Arduino引脚3

●    模块TX引脚连接到Arduino引脚4

●    模块VCC引脚连接到Arduino的5V引脚


代码

将以下代码复制到您的Arduino IDE并上传到您的Arduino开发板上。

  1. /*
  2. * Rui Santos
  3. * Complete Project Details http://randomnerdtutorials.com
  4. */

  5. #include <SoftwareSerial.h>

  6. // The serial connection to the GPS module
  7. SoftwareSerial ss(4, 3);

  8. void setup(){
  9.   Serial.begin(9600);
  10.   ss.begin(9600);
  11. }

  12. void loop(){
  13.   while (ss.available() > 0){
  14.     // get the byte data from the GPS
  15.     byte gpsData = ss.read();
  16.     Serial.write(gpsData);
  17.   }
  18. }
复制代码

本示例假定您使用引脚4和3作为RX和TX串行引脚与GPS模块建立串行通信。如果您正在使用其他引脚,则应在编辑以下代码行:

  1. SoftwareSerial ss(4,3);
复制代码

此外,如果您的模块使用不同于9600 bps的默认波特率,则应修改以下行中的代码:

  1. ss.begin(9600);
复制代码

这个示例监听GPS串行端口,当从模块接收到数据时,它被发送到串行监视器。

  1. while (ss.available() > 0){
  2.   // get the byte data from the GPS
  3.   byte gpsData = ss.read();
  4.   Serial.write(gpsData);
  5. }
复制代码

使用波特率9600打开串行监视器。

GPS-raw-data-serial-monitor-blurred-2.png

你应该得到一堆GPS标准语言NMEA的信息。串行监视器中的每一行都是NMEA语句。

NMEA全称美国国家海洋电子协会(National Marine Electronics Association),在GPS领域,它是GPS制造商支持的标准数据格式。


了解NMEA语句

NMEA语句以$字符开头,每个数据字段用逗号分隔

  1. $GPGGA,110617.00,41XX.XXXXX,N,00831.54761,W,1,05,2.68,129.0,M,50.1,M,,*42
  2. $GPGSA,A,3,06,09,30,07,23,,,,,,,,4.43,2.68,3.53*02
  3. $GPGSV,3,1,11,02,48,298,24,03,05,101,24,05,17,292,20,06,71,227,30*7C
  4. $GPGSV,3,2,11,07,47,138,33,09,64,044,28,17,01,199,,19,13,214,*7C
  5. $GPGSV,3,3,11,23,29,054,29,29,01,335,,30,29,167,33*4E
  6. $GPGLL,41XX.XXXXX,N,00831.54761,W,110617.00,A,A*70
  7. $GPRMC,110618.00,A,41XX.XXXXX,N,00831.54753,W,0.078,,030118,,,A*6A
  8. $GPVTG,,T,,M,0.043,N,0.080,K,A*2C
复制代码

有NMEA句子的不同类型。消息的类型由第一个逗号前的字符指示。

$之后的GP表示它是GPS位置。 $ GPGGA是基本的GPS NMEA消息,提供3D位置和准确性数据。在下面的句子中:

  1. $ GPGGA,110617.00,41XX.XXXXX,N,00831.54761,W,1,05,2.68,129.0,男,50.1,M,* 42
复制代码

●    110617 - 表示固定地点的时间,UTC时间11:06:17

●    41XX.XXXXX,N - 北纬41度XX.XXXXX'N

●    00831.54761,W - 经度008度31.54761'W

●    1 - 固定质量(0 =无效; 1 = GPS修正; 2 = DGPS修正; 3 = PPS修正; 4 =实时运动学; 5 =浮动RTK; 6 =估计(航位推测); 7 =手动输入模式; 8 =模拟模式)

●    05 - 正在跟踪的卫星数量

●    2.68 - 水平位置因子

●    129.0,M - 海拔高度,以米为单位

●    50.1,M - 大于WGS84椭球体的大地水准面(平均海平面)的高度

●    空字段  - 自上次DGPS更新以来的秒数

●    空字段 - DGPS台站ID号

●    * 42 - 校验和,数据总是以*开头

其他NMEA句子提供了其他的信息:

●    $ GPGSA - GPS DOP和主动卫星

●    $ GPGSV - 详细的GPS卫星信息

●    $ GPGLL - 地理纬度和经度

●    $ GPRMC - 基本的GPS pvt(位置、速度、时间)数据

●    $ GPVTG - 速度很好

要知道这些句子中每个数据字段的含义,可以在以下链接查阅NMEA数据:http://www.gpsinformation.org/dale/nmea.htm

跳转到指定楼层
风筝
发表于: 2018-1-15 13:48:00 | 显示全部楼层

使用TinyGPS ++库解析NMEA语句

您可以使用GPS中的原始数据,也可以通过将字符序列保存为变量,将这些NMEA消息转换为可读且有用的格式。为此,我们将使用TinyGPS ++库

这个库使得我们可以以一种有用和容易理解的格式获得位置信息变得简单。您可以点击这里获取更多关于TinyGPS ++库的信息。


安装TinyGPS ++库

按照以下步骤在您的Arduino IDE中安装TinyGPS ++库:

    1.  点击这里下载TinyGPSPlus库。您的Downloads文件夹中应该有一个.zip文件

    2.  解压缩.zip文件,你应该得到TinyGPSPlus-master文件夹

    3.  将您的文件夹从TinyGPSPlus-master重命名为TinyGPSPlus

    4.  将TinyGPSPlus文件夹移动到您的Arduino IDE安装库文件夹

    5.  最后,重新打开你的Arduino IDE


软件库提供了几个关于如何使用它的例子。在您的Arduino IDE中,您只需转到File> Examples> TinyGPS ++,然后从提供的示例中进行选择。

注意:库中提供的示例假设GPS模块的波特率为4800。如果您使用NEO-6M GPS模块,则需要将其更改为9600。


使用NEO-6M GPS模块和TinyGPS ++库获取位置

您可以通过使用TinyGPS ++库以便于使用的格式获取位置。下面,我们提供一段代码来获取从GPS的位置。这是一个库例子的简化版本。

  1. /*
  2. * Rui Santos
  3. * Complete Project Details http://randomnerdtutorials.com
  4. */

  5. #include <TinyGPS++.h>
  6. #include <SoftwareSerial.h>

  7. static const int RXPin = 4, TXPin = 3;
  8. static const uint32_t GPSBaud = 9600;

  9. // The TinyGPS++ object
  10. TinyGPSPlus gps;

  11. // The serial connection to the GPS device
  12. SoftwareSerial ss(RXPin, TXPin);

  13. void setup(){
  14.   Serial.begin(9600);
  15.   ss.begin(GPSBaud);
  16. }

  17. void loop(){
  18.   // This sketch displays information every time a new sentence is correctly encoded.
  19.   while (ss.available() > 0){
  20.     gps.encode(ss.read());
  21.     if (gps.location.isUpdated()){
  22.       Serial.print("Latitude= ");
  23.       Serial.print(gps.location.lat(), 6);
  24.       Serial.print(" Longitude= ");
  25.       Serial.println(gps.location.lng(), 6);
  26.     }
  27.   }
  28. }
复制代码

您首先需要导入所需的库:TinyGPSPlus和SoftwareSerial:

  1. #include <TinyGPS++.h>
  2. #include <SoftwareSerial.h>
复制代码

然后,您可以定义软件串行RX和TX引脚,以及GPS波特率。如果您使用其他引脚进行软件串行连接,则需要在此处进行更改。另外,如果你的GPS模块使用不同的默认波特率,你也应该修改它。

  1. static const int RXPin = 4, TXPin = 3;
  2. static const uint32_t GPSBaud = 9600;
复制代码

然后,你创建一个TinyGPS ++对象:

  1. TinyGPSPlus GPS;
复制代码

并在你之前定义的引脚上启动一个串行连接

  1. SoftwareSerial ss(RXPin,TXPin);
复制代码

在setup()中,初始化串行通信,既可以在串行监视器上查看读数,也可以与GPS模块通信。

  1. void setup() {
  2.   Serial.begin(9600);
  3.   ss.begin(GPSBaud);
  4. }
复制代码

在循环中查询信息。要使TinyGPS ++正常工作,必须使用encode()方法从GPS模块中反复输入字符。

  1. while(ss.available()> 0){
  2. gps.encode(ss.read());
复制代码

然后,您可以查询gps对象,查看是否有任何数据字段已更新:

  1. if (gps.location.isUpdated()){
  2.   Serial.print("Latitude="); Serial.print(gps.location.lat(), 6);
  3.   Serial.print("Longitude="); Serial.println(gps.location.lng(), 6);
  4. }
复制代码

获取纬度和经度很简单,分别使用gps.location.lat()和gps.location.lng()。

上传代码到你的Arduino,你应该可以看到在串口监视器上显示的位置。上传代码后,等待几分钟,模块调整位置以获得更准确的数据。

GPS-get-location-serial-monitor-blurred-2.png


使用TinyGPS ++库获取更多的GPS信息

TinyGPS ++库允许您以简单的方式获取更多信息,而不仅仅是位置。 除了位置,你可以得到:

■    日期

■    时间

■    速度

■    航向

■    高度

■    卫星

■    HDOP


以下代码举例说明了如何以简单的方式获取所有信息。

  1. /*
  2. * Rui Santos
  3. * Complete Project Details http://randomnerdtutorials.com
  4. *
  5. * Based on the example TinyGPS++ from arduiniana.org
  6. *
  7. */

  8. #include <TinyGPS++.h>
  9. #include <SoftwareSerial.h>

  10. static const int RXPin = 4, TXPin = 3;
  11. static const uint32_t GPSBaud = 9600;

  12. // The TinyGPS++ object
  13. TinyGPSPlus gps;

  14. // The serial connection to the GPS device
  15. SoftwareSerial ss(RXPin, TXPin);

  16. void setup(){
  17.   Serial.begin(9600);
  18.   ss.begin(GPSBaud);
  19. }

  20. void loop(){
  21.   // This sketch displays information every time a new sentence is correctly encoded.
  22.   while (ss.available() > 0){
  23.     gps.encode(ss.read());
  24.     if (gps.location.isUpdated()){
  25.       // Latitude in degrees (double)
  26.       Serial.print("Latitude= ");
  27.       Serial.print(gps.location.lat(), 6);      
  28.       // Longitude in degrees (double)
  29.       Serial.print(" Longitude= ");
  30.       Serial.println(gps.location.lng(), 6);
  31.       
  32.       // Raw latitude in whole degrees
  33.       Serial.print("Raw latitude = ");
  34.       Serial.print(gps.location.rawLat().negative ? "-" : "+");
  35.       Serial.println(gps.location.rawLat().deg);
  36.       // ... and billionths (u16/u32)
  37.       Serial.println(gps.location.rawLat().billionths);
  38.       
  39.       // Raw longitude in whole degrees
  40.       Serial.print("Raw longitude = ");
  41.       Serial.print(gps.location.rawLng().negative ? "-" : "+");
  42.       Serial.println(gps.location.rawLng().deg);
  43.       // ... and billionths (u16/u32)
  44.       Serial.println(gps.location.rawLng().billionths);

  45.       // Raw date in DDMMYY format (u32)
  46.       Serial.print("Raw date DDMMYY = ");
  47.       Serial.println(gps.date.value());

  48.       // Year (2000+) (u16)
  49.       Serial.print("Year = ");
  50.       Serial.println(gps.date.year());
  51.       // Month (1-12) (u8)
  52.       Serial.print("Month = ");
  53.       Serial.println(gps.date.month());
  54.       // Day (1-31) (u8)
  55.       Serial.print("Day = ");
  56.       Serial.println(gps.date.day());

  57.       // Raw time in HHMMSSCC format (u32)
  58.       Serial.print("Raw time in HHMMSSCC = ");
  59.       Serial.println(gps.time.value());

  60.       // Hour (0-23) (u8)
  61.       Serial.print("Hour = ");
  62.       Serial.println(gps.time.hour());
  63.       // Minute (0-59) (u8)
  64.       Serial.print("Minute = ");
  65.       Serial.println(gps.time.minute());
  66.       // Second (0-59) (u8)
  67.       Serial.print("Second = ");
  68.       Serial.println(gps.time.second());
  69.       // 100ths of a second (0-99) (u8)
  70.       Serial.print("Centisecond = ");
  71.       Serial.println(gps.time.centisecond());

  72.       // Raw speed in 100ths of a knot (i32)
  73.       Serial.print("Raw speed in 100ths/knot = ");
  74.       Serial.println(gps.speed.value());
  75.       // Speed in knots (double)
  76.       Serial.print("Speed in knots/h = ");
  77.       Serial.println(gps.speed.knots());
  78.       // Speed in miles per hour (double)
  79.       Serial.print("Speed in miles/h = ");
  80.       Serial.println(gps.speed.mph());
  81.       // Speed in meters per second (double)
  82.       Serial.print("Speed in m/s = ");
  83.       Serial.println(gps.speed.mps());
  84.       // Speed in kilometers per hour (double)
  85.       Serial.print("Speed in km/h = ");
  86.       Serial.println(gps.speed.kmph());

  87.       // Raw course in 100ths of a degree (i32)
  88.       Serial.print("Raw course in degrees = ");
  89.       Serial.println(gps.course.value());
  90.       // Course in degrees (double)
  91.       Serial.print("Course in degrees = ");
  92.       Serial.println(gps.course.deg());

  93.       // Raw altitude in centimeters (i32)
  94.       Serial.print("Raw altitude in centimeters = ");
  95.       Serial.println(gps.altitude.value());
  96.       // Altitude in meters (double)
  97.       Serial.print("Altitude in meters = ");
  98.       Serial.println(gps.altitude.meters());
  99.       // Altitude in miles (double)
  100.       Serial.print("Altitude in miles = ");
  101.       Serial.println(gps.altitude.miles());
  102.       // Altitude in kilometers (double)
  103.       Serial.print("Altitude in kilometers = ");
  104.       Serial.println(gps.altitude.kilometers());
  105.       // Altitude in feet (double)
  106.       Serial.print("Altitude in feet = ");
  107.       Serial.println(gps.altitude.feet());

  108.       // Number of satellites in use (u32)
  109.       Serial.print("Number os satellites in use = ");
  110.       Serial.println(gps.satellites.value());

  111.       // Horizontal Dim. of Precision (100ths-i32)
  112.       Serial.print("HDOP = ");
  113.       Serial.println(gps.hdop.value());
  114.     }
  115.   }
  116. }
复制代码

注意:TinyGPS ++库在如何使用其所有函数方面都有很好的注释。

我们希望本文能够对你有用。 我们打算用NEO-6M GPS模块和SD卡模块制作一个GPS数据记录仪,敬请期待。谢谢阅读。

回复

使用道具 举报

小明上前线
发表于: 2019-4-12 13:38:44 | 显示全部楼层

楼主你好,我发现这个程序在读取经纬度时,没有显示是   东经西经还是南纬北纬   。有啥方法修正嘛?
回复

使用道具 举报

sinwing
发表于: 2019-6-13 18:32:44 | 显示全部楼层

换了东经之后,数据就无法出来
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 377 | 回复: 691



手机版|

GMT+8, 2019-11-14 20:23 , Processed in 0.046875 second(s), 31 queries . Powered by Discuz! X3.4

YiBoard一板网 © 2015-2018 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表