将 GNSS 接收器与 Arduino 连接以获取位置

arduinoarduino boardsarduino idearduino programming language

在本教程中,我们将 Arduino 与 GNSS 接收器连接并获取当前位置。任何 GNSS 接收器通常都使用 UART 进行通信。我们将使用 ublox Neo6M GNSS 模块。

电路图

如您所见,我们将 Vcc 连接到 5V,GND 连接到 GND,将 Neo 6M 的 RX 连接到 Arduino Uno 的引脚 3,将 Neo 6M 的 TX 连接到 Arduino Uno 的引脚 4。

所需库

将 Arduino Uno 与 OLED 显示屏连接起来需要 TinyGPS 库 −

前往工具 →管理库,搜索此库,然后点击"安装"。

代码演示

我们将演示 TinyGPS 库附带的示例代码。前往文件 → 示例 → TinyGPS → simple_test 访问代码。

或者,您也可以在 GitHub 上访问代码 − https://github.com/mikalhart/TinyGPS/blob/master/examples/simple_test/simple_test.ino

如您所见,我们首先要添加所需的库:SoftwareSerial 和 TinyGPS。 SoftwareSerial 是一个库,可以与任何非串行端口的数字引脚进行串行通信。在这里,我们将使用该库来实现与 Arduino Uno 的 3 号和 4 号引脚的串行通信。

#include −SoftwareSerial.h>

#include −TinyGPS.h>

接下来,我们定义 TinyGPS 对象和 Software Serial 对象。定义 Software Serial 对象时,需要提供 RX 和 TX 引脚作为参数。由于 Arduino 的 4 号引脚连接到 Neo 6M 模块的 TX 引脚,因此 4 号引脚在 Arduino 端是 RX 引脚,同理,3 号引脚是 TX 引脚。

TinyGPS gps;
SoftwareSerial ss(4, 3);

在设置过程中,我们初始化了串口和软件串口。示例代码中,软件串口的波特率初始化为 4800。请查看您的 Neo 6M 模块的数据手册,如果您需要更高的波特率,例如 9600,请进行相应的更改。之后,我们添加了几个打印语句,其中包含库的版本号。

void setup()
{
   Serial.begin(115200);
   ss.begin(4800);

   Serial.print("Simple TinyGPS library v. ");
   Serial.println(TinyGPS::library_version());
   Serial.println("by Mikal Hart");
   Serial.println();
}

现在让我们仔细检查一下这个循环。循环首先定义几个变量 −

void loop()
{
   bool newData = false;
   unsigned long chars;
   unsigned short sentence, failed;

接下来是一个持续一秒的 for 循环,用于解析来自软件串口的数据。  gps.encode() 函数接收来自软件串口的每个字节,并在数据完全解析并可供使用时返回 true。

因此,当它返回 true 时,我们将  newData 设置为 true。

   // 我们解析 GPS 数据并报告一些关键值一秒钟
   for (unsigned long start = millis(); millis() - start lt; 1000;)
   {
      while (ss.available())
      {
         char c = ss.read();
         // Serial.write(c); // 如果要查看 GPS 数据流,请取消注释此行
         if (gps.encode(c)) // 是否有新的有效语句?
            newData = true;
      }
   }

如果 newData 为 true,我们将使用 f_get_position() 函数获取浮点型经纬度值,并获取数据年龄(即收集数据的时间)。我们使用 .satellites() 函数获取接收器可见的卫星数量,并使用 .hdop() 函数获取水平精度因子。您可以在此处阅读有关 hdop 的更多信息 https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation)#:~:text=DOP%20can%20be%20expressed%20as,position%20(3D)%20dilution%20of%20precision

在每个打印语句中,我们检查 INVALID 标志是否为真,如果为真,则打印 0,否则打印计算值。

if (newData)
   {
      float flat, flon;
      unsigned long age;
      gps.f_get_position(&flat, &flon, &age);
      Serial.print("LAT=");
      Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
      Serial.print(" LON=");
      Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
      Serial.print(" SAT=");
      Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
      Serial.print(" PREC=");
      Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
   }

稍后,我们使用 .stats() 函数计算从 GNSS 接收器接收到的字符数、句子数以及校验和计算失败的次数。

gps.stats(&chars, &sentences, &failed);
   Serial.print(" CHARS=");
   Serial.print(chars);
   Serial.print(" SENTENCES=");
   Serial.print(sentences);
   Serial.print(" CSUM ERR=");
   Serial.println(failed);
   if (chars == 0)
      Serial.println("** 未从 GPS 接收到字符:请检查接线 **");

请注意,您可能需要将接收器及其天线靠近窗户才能获得准确的位置。另请注意,GNSS 接收器的冷启动时间通常约为 30-40 秒。这意味着开机后大约需要 30-40 秒才能获得有效的位置信息。


相关文章