机缘
上过月买了一个GPS模块,然后我用esp32读取GPS数据,并使用LVGL显示GPS信息。期间踩了很多坑,我用乐鑫的IDF开发,自己写了一个GPS信息提取方法,BUG很多,而且加上多任务处理,串口中断,快给我人搞麻了。
今天在网上找到一个解析GPS的库,使用起来非常简单。我立马开始动手实验一下。
硬件
我顺手拿了一块 Arduino UNO和一块LCD1602,然后用杜邦线连一下。
软件部分
这个解析GPS的库是 “TinyGPSPlus”,里面自带很多例子,我照着例子一顿复制粘贴,然后下载运行,一次就成功了。功能是在LCD1602上显示经纬度,已连接卫星个数,距起始点的距离和方向。
//LCD1602
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//GPS
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
double home_lat = 0.0, home_lon = 0.0;
void setup()
{
//初始化LCD屏幕
lcd.begin();
lcd.backlight();
lcd.setCursor(0, 0);
Serial.begin(115200);
ss.begin(GPSBaud);
while(!gps.location.isValid())
{
lcd.print("Searching for stars");
smartDelay(1000);
}
lcd.setCursor(0, 0);
lcd.print(" Search is OK! ");
smartDelay(1000);
home_lat=gps.location.lat();
home_lon=gps.location.lng();
lcd.clear();
lcd.setCursor(0, 0);
}
void loop()
{
double home_lat_NEW = 0.0, home_lon_NEW = 0.0;
if(gps.location.isValid())
{
home_lat_NEW=gps.location.lat();
home_lon_NEW=gps.location.lng();
//输出经纬度
lcd.setCursor(0, 0);
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
lcd.setCursor(0, 1);
printFloat(gps.location.lng(), gps.location.isValid(), 11, 6);
unsigned long distanceKmToLondon =
(unsigned long)TinyGPSPlus::distanceBetween(
home_lat_NEW,
home_lon_NEW,
home_lat,
home_lon);
double courseToLondon =
TinyGPSPlus::courseTo(
home_lat_NEW,
home_lon_NEW,
home_lat,
home_lon);
//输出离家距离,已校准卫星个数,方向
lcd.setCursor(11, 0);
printInt(distanceKmToLondon, gps.location.isValid(), 5);
lcd.setCursor(15, 0);
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
lcd.setCursor(13, 1);
printInt(courseToLondon, gps.location.isValid(), 5);
}
smartDelay(1000);
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("No GPS data received: check wiring"));
}
//只能延时,在延时的过程中处理GPS的数据
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
}
while (millis() - start < ms);
}
static void printFloat(float val, bool valid, int len, int prec)
{
if (!valid)
{
while (len-- > 1)
lcd.print('*');
lcd.print(' ');
}
else
{
lcd.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
lcd.print(' ');
}
smartDelay(0);
}
static void printInt(unsigned long val, bool valid, int len)
{
char sz[32] = "*****************";
if (valid)
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
lcd.print(sz);
smartDelay(0);
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
if (!d.isValid())
{
lcd.print(F("********** "));
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
lcd.print(sz);
}
if (!t.isValid())
{
lcd.print(F("******** "));
}
else
{
char sz[32];
sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
lcd.print(sz);
}
printInt(d.age(), d.isValid(), 5);
smartDelay(0);
}
static void printStr(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
lcd.print(i<slen ? str[i] : ' ');
smartDelay(0);
}
运行效果
这个是在室内测试的,可以接收25颗卫星,在室外可以接收30颗卫星,精度的话,跟手机上的相差不大。
总结
哎,自己写代码,搞三天勉强能用;用别人开源代码,几分钟搞定。以后还是少造轮子吧。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)