【雕爷学编程】Arduino动手做(74)---6MV2飞控GPS模块5

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)

在这里插入图片描述
在这里插入图片描述
Arduino实验接线示意图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)

程序十一:使用 TinyGPSCustom 对象数组监视所有可见的卫星

Arduino参考开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序十一:使用 TinyGPSCustom 对象数组监视所有可见的卫星
*/

#include <TinyGPSPlus.h>//导入驱动库
#include <SoftwareSerial.h>

static const int RXPin = 9, TXPin = 8;//定义软串口接脚
static const uint32_t GPSBaud = 9600;

// TinyGPSPlus 对象
TinyGPSPlus gps;

//与 GPS 设备的串行连接
SoftwareSerial ss(RXPin, TXPin);

/* 
  来自 http://aprs.gids.nl/nmea/:
   
  $GPGSV
  
  视野中的 GPS 卫星
  
  例如:
$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74   $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74
$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D

  1 = 此周期中此类消息的总数
  2 = 消息编号
  3 = 视图中的 SV 总数
  4 = SV PRN 号码
  5 = 以度为单位的仰角,最大 90
  6 = 方位角,从真北的度数,000 到 359
  7 = SNR,00-99 dB(不跟踪时为空)
  8-11 = 关于第二个 SV 的信息,与字段 4-7 相同
  12-15=关于第三个 SV 的信息,与字段 4-7 相同
  16-19= 关于第四个 SV 的信息,与字段 4-7 相同
*/

static const int MAX_SATELLITES = 40;

TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1); // $GPGSV 句子,第一个元素
TinyGPSCustom messageNumber(gps, "GPGSV", 2);      // $GPGSV 句子,第二个元素
TinyGPSCustom satsInView(gps, "GPGSV", 3);         // $GPGSV 句子,第三个元素
TinyGPSCustom satNumber[4]; // 稍后初始化
TinyGPSCustom elevation[4];
TinyGPSCustom azimuth[4];
TinyGPSCustom snr[4];

struct{
  bool active;
  int elevation;
  int azimuth;
  int snr;
} sats[MAX_SATELLITES];

void setup(){
  Serial.begin(9600);
  ss.begin(GPSBaud);

  Serial.println(F("SatelliteTracker.ino"));
  Serial.println(F("使用 TinyGPSCustom 监控卫星位置和信号强度"));
  Serial.print(F("测试 TinyGPSPlus 库 v.")); 
  Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("GY-NEO6MV2模块准备就绪"));
  Serial.println();
  
  // 初始化所有未初始化的 TinyGPSCustom 对象
  for (int i=0; i<4; ++i)
  {
    satNumber[i].begin(gps, "GPGSV", 4 + 4 * i); // offsets 4, 8, 12, 16
    elevation[i].begin(gps, "GPGSV", 5 + 4 * i); // offsets 5, 9, 13, 17
    azimuth[i].begin(  gps, "GPGSV", 6 + 4 * i); // offsets 6, 10, 14, 18
    snr[i].begin(      gps, "GPGSV", 7 + 4 * i); // offsets 7, 11, 15, 19
  }
}

void loop(){
  // 初始化所有未初始化的 TinyGPSCustom 对象
  if (ss.available() > 0)
  {
    gps.encode(ss.read());
    if (totalGPGSVMessages.isUpdated())
    {
      for (int i=0; i<4; ++i)
      {
        int no = atoi(satNumber[i].value());
        // Serial.print(F("SatNumber is ")); Serial.println(no);
        if (no >= 1 && no <= MAX_SATELLITES)
        {
          sats[no-1].elevation = atoi(elevation[i].value());
          sats[no-1].azimuth = atoi(azimuth[i].value());
          sats[no-1].snr = atoi(snr[i].value());
          sats[no-1].active = true;
        }
      }
      
      int totalMessages = atoi(totalGPGSVMessages.value());
      int currentMessage = atoi(messageNumber.value());
      if (totalMessages == currentMessage)
      {
        Serial.print(F("Sats=")); 
        Serial.print(gps.satellites.value());
        Serial.print(F(" Nums="));
        for (int i=0; i<MAX_SATELLITES; ++i)
          if (sats[i].active)
          {
            Serial.print(i+1);
            Serial.print(F(" "));
          }
        Serial.print(F(" 海拔="));//海拔
        for (int i=0; i<MAX_SATELLITES; ++i)
          if (sats[i].active)
          {
            Serial.print(sats[i].elevation);
            Serial.print(F(" "));
          }
        Serial.print(F(" 方位角="));//方位角
        for (int i=0; i<MAX_SATELLITES; ++i)
          if (sats[i].active)
          {
            Serial.print(sats[i].azimuth);
            Serial.print(F(" "));
          }
        
        Serial.print(F(" 信噪比="));//信噪比
        for (int i=0; i<MAX_SATELLITES; ++i)
          if (sats[i].active)
          {
            Serial.print(sats[i].snr);
            Serial.print(F(" "));
          }
        Serial.println();

        for (int i=0; i<MAX_SATELLITES; ++i)
          sats[i].active = false;
      }
    }
  }
}

实验串口返回情况

在这里插入图片描述

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)

程序十二:使用 TinyGPSCustom 提取任何 NMEA 字段

Arduino参考开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序十二:使用 TinyGPSCustom 提取任何 NMEA 字段
*/

#include <TinyGPSPlus.h>//导入驱动库
#include <SoftwareSerial.h>

static const int RXPin = 9, TXPin = 8;//定义软串口接脚
static const uint32_t GPSBaud = 9600;

// TinyGPSPlus 对象
TinyGPSPlus gps;

//与 GPS 设备的串行连接
SoftwareSerial ss(RXPin, TXPin);

/*
   通过像这样声明 TinyGPSCustom 对象,我们宣布我们
   对 $GPGSA 中的第 15、16 和 17 字段感兴趣
   句子,分别是PDOP(F(“位置精度的稀释”)),
   HDOP (F("horizo​​ntal...")) 和 VDOP (F("vertical..."))。

   (计数从紧跟句子名称的字段开始,
   即 $GPGSA。有关 NMEA 语句的更多信息,请咨询您的
   GPS 模块的文档和/或 http://aprs.gids.nl/nmea/。)

   如果你的 GPS 模块不支持 $GPGSA 语句,那么你
   不会从此程序获得任何输出。
*/

TinyGPSCustom pdop(gps, "GPGSA", 15); // $GPGSA 句子,第 15 个元素
TinyGPSCustom hdop(gps, "GPGSA", 16); // $GPGSA 句子,第 16 个元素
TinyGPSCustom vdop(gps, "GPGSA", 17); // $GPGSA 句子,第 17 个元素

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);

  Serial.println(F("UsingCustomFields.ino"));
  Serial.println(F("使用 TinyGPSCustom 提取任何 NMEA 字段"));
  Serial.print(F("测试 TinyGPSPlus 库 v."));
  Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("GY-NEO6MV2模块准备就绪"));
  Serial.println();
}

void loop() {
  // 每次更新任何内容时,打印所有内容。
  if (gps.altitude.isUpdated() || gps.satellites.isUpdated() ||
      pdop.isUpdated() || hdop.isUpdated() || vdop.isUpdated())
  {
    Serial.print(F("ALT="));   Serial.print(gps.altitude.meters());
    Serial.print(F(" PDOP=")); Serial.print(pdop.value());
    Serial.print(F(" HDOP=")); Serial.print(hdop.value());
    Serial.print(F(" VDOP=")); Serial.print(vdop.value());
    Serial.print(F(" SATS=")); Serial.println(gps.satellites.value());
  }
  while (ss.available() > 0)
    gps.encode(ss.read());
}

实验串口返回情况

在这里插入图片描述
Arduino实验场景图

在这里插入图片描述
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)

程序十三:在OLED上显示日期、时间、纬度和经度

Arduino参考开源代码

/*
  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  程序十三:在OLED上显示日期、时间、纬度和经度
*/

#include <TimeLib.h>//导入驱动库
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <U8glib.h>

//用于连接GY-NEO6MV2模块的引脚D9/D8
static const int RXPin = 9, TXPin = 8;
// TinyGPS++ 对象
TinyGPSPlus gps;
// GPS模块的串口连接
SoftwareSerial Serial_GPS(RXPin, TXPin);
//OLED显示设置
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_FAST);

void draw() {
  //设置时间/时区
  GPS_Timezone_Adjust();
  //显示的图形命令必须放在这里aqui
  u8g.setFont(u8g_font_8x13B);
  u8g.drawRFrame(0, 0, 128, 64, 4);
  //日期线
  u8g.drawStr(10, 14, "D:        ");
  u8g.setPrintPos(34, 14);
  //显示日期
  if (day() < 10)
  {
    u8g.print("0");
  }
  u8g.print(day());
  u8g.drawStr(51, 14, "/");
  u8g.setPrintPos(60, 14);
  //显示月份
  if (month() < 10)
  {
    u8g.print("0");
  }
  u8g.print(month());
  u8g.drawStr(76, 14, "/");
  u8g.setPrintPos(85, 14);
  //显示年份
  u8g.print(year());
  // 时间线
  u8g.drawStr(10, 29, "H:        ");
  u8g.setPrintPos(45, 29);
  //开始时间
  if (hour() < 10)
  {
    u8g.print("0");
  }
  u8g.print(hour());
  u8g.drawStr(61, 28, ":");
  u8g.setPrintPos(70, 29);
  //显示分钟
  if (minute() < 10)
  {
    u8g.print("0");
  }
  u8g.print(minute());
  u8g.drawStr(86, 28, ":");
  u8g.setPrintPos(95, 29);
  //显示秒数
  if (second() < 10)
  {
    u8g.print("0");
  }
  u8g.print(second());
  //纬度
  u8g.drawStr(10, 44, "Lat:         ");
  u8g.setPrintPos(45, 44);
  u8g.print(gps.location.lat(), 5);
  //经度
  u8g.drawStr(10, 59, "Lon:         ");
  u8g.setPrintPos(45, 59);
  u8g.print(gps.location.lng(), 5);
}
//根据地区调整时区
const int UTC_offset = -3;

void setup() {
  // Arduino 波特率
  Serial.begin(9600);
  //波特率GPS模块
  Serial_GPS.begin(9600);
  //在串口监视器上显示初始信息
  Serial.println(F("日期、时间、纬度和经度"));
  Serial.println(F("GPS 模块 GY-NEO6MV2"));
  Serial.print(F("TinyGPS++ 驱动库 v."));
  Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println();
  //OLED显示设置
  if ( u8g.getMode() == U8G_MODE_R3G3B2 )
  {
    u8g.setColorIndex(255);     // 白色的
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // 最大强度
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         //像素开启
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);
  }
}

void loop() {
  //与GPS模块连接
  while (Serial_GPS.available() > 0)
    if (gps.encode(Serial_GPS.read()))
      displayInfo();
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("未检测到 GPS:检查接线。"));
    while (true);
  }
  //调用屏幕上的绘图例程
  u8g.firstPage();
  do
  {
    draw();
  }
  while ( u8g.nextPage() );
  delay(1000);
}

void displayInfo() {
  //在串口监视器中显示信息
  Serial.print(F("位置:"));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6); //latitude
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6); //longitude
  }
  else
  {
    Serial.print(F("无效"));
  }
  Serial.print(F("  日期/时间: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.day()); //天
    Serial.print(F("/"));
    Serial.print(gps.date.month()); //月
    Serial.print(F("/"));
    Serial.print(gps.date.year());//年
  }
  else
  {
    Serial.print(F("无效"));
  }
  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour()); //小时
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute()); //分钟
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second()); //第二
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("无效"));
  }
  Serial.println();
}

void GPS_Timezone_Adjust() {
  while (Serial_GPS.available())
  {
    if (gps.encode(Serial_GPS.read()))
    {
      int Year = gps.date.year();
      byte Month = gps.date.month();
      byte Day = gps.date.day();
      byte Hour = gps.time.hour();
      byte Minute = gps.time.minute();
      byte Second = gps.time.second();
      //根据GPS数据调整日期和时间
      setTime(Hour, Minute, Second, Day, Month, Year);
      //应用偏移来设置日期和时间
      //根据时区
      adjustTime(UTC_offset * SECS_PER_HOUR);
    }
  }
}

实验串口返回情况(放在电脑桌上,没有GPS信号)

在这里插入图片描述

实验场景图 (放在电脑桌上,没有GPS信号)

在这里插入图片描述

实验串口返回情况(模块放在窗口,接收到GPS信号)

在这里插入图片描述

实验场景图(模块放在窗口,接收到GPS信号)

在这里插入图片描述
在这里插入图片描述

实验接线示意图(GPS软串口接在D9/D8)

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值