查看: 1461|回复: 0

[分享] 用LPC55xx搭建AIOT平台,步骤分解之北斗/GPS定位

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3299

    主题

    6546

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32024
    最后登录
    2024-4-25
    发表于 2021-7-29 09:38:07 | 显示全部楼层 |阅读模式
    用LPC55xx搭建AIOT平台,步骤分解之北斗/GPS定位


    书接上回——上回书在此,上次咱们介绍的如何利用I2C接口接入传感器,这篇文章介绍是如何通过UART连接北斗/GPS模块获取地理位置信息,智慧物流嘛北斗/GPS是传统位置追踪的手段,也可以利用GPS模块给出的时间数据进行校时。


    一、北斗/GPS模块介绍
    GPS购于某宝,类似的厂商有很多知名的有Ublox,,移远等,我这里买的是中科微的,别问为什么选它,问就是便宜... 而且这个模块尺寸小、支持全GNSS系统(北斗、GPS、GLONASS、伽利略、日本的QZSS以及卫星增强系统SBAS)。
    1、接MCU的UART
    11.png
    模块引脚说明如下
    14.png
    GPS模块引脚实际与LPC55S69-IOT kit连接的时候,可以按照如下接法,模块的RX可以不接,看要不要配置模块了,如果不需要配置GPS模块则可以不接的。
    12.png
    2、GPS模块的数据格式- NEMA码
    我们可以先用USB转UART的dongle来看看NEMA长什么样子,本狮这里用的是CP2102的模块,用sscom串口助手来接受GPS模块发出来的数据。数据有点多,但是别怕,之后我们先认真分析下后用“拥抱(CTRL+C) +开源(CTRL+V)”的方式给大家节约点时间,毕竟工作后键盘磨秃的不再是AWSD了~
    下面是模块输出的数据:
    15.png
    这里本狮说的NEMA码指的是NMEA-0183协议的报文,大多数常见的GNSS接收机、GNSS数据处理软件、导航软件都遵守或者兼容这个协议。


    数据里面我们看到三种数据类型GN、GP、BD 分别代表双模模式、GPS 模式、北斗模式。比如下面这条报文:


    根据NMEA-0183协议的规定,$XXGGA报文是关于时间、经纬度位置、解算状态、卫星颗数等相关信息。XX的不同代表模式的不同,比如$GPGGA表示单GPS模式,$BDGGA表示单北斗模式,$GNGGA表示多星联合定位。具体的含义我们对应查表就行了(NEMA-0193协议),微信小文章就不放了,论坛的帖子里我会放具体的表格,定位不一样。

    二、MCU如何获取NEMA码并且解析


    一般来说GPS模块都是和MCU的串口连接的,串口接收数据的方式无非三种,轮询Polling/中断Interrupt/DMA。轮询基本上是不可能选择的模式,所以大多数用户还是用的中断,高阶点的则用DMA的方式。


    1、中断的方式
    中断的方式虽说占用些MCU的资源,但是胜在串口是低速率的并且简单易移植,如果系统设备始终中断资源较少的话影响还好。


    2、DMA的方式
    DMA的方式比较推荐,占用CPU的资源少,一般来说要配置UART的接收完成(Received Idle)信号来完成一次数据的接收,并且启动下一次DMA从串口到RAM的搬运工作。但是LPC55系列除了LPC55S3x系列的UART带有Received Idle的功能,其他的比如LPC55S0x、LPC55S1x、LPC55S2x、LPC55S6x都不具备此模式,所以针对这种没有Received Idle的MCU,我们只能启动一个定时器来做Timeout管理。


    3、代码中如何识别
    咱们可以用strstr的方式去获取GPS的数据头帧的信息,比如:
    1. if(g_GPRSecvCnt>=GPS_BUFFER_SIZE)
    2. {   
    3.     uint8_t*buff=NULL;
    4.     buf=(uint8_t*)strstr((const char*)g_GPRSecvBuf,"SGNRMC,");
    5.      if(buf !=null)
    6. {
    复制代码
    4、借助开源
    Github上关于GPS的NEMA解码有现成的code,比如GPSNMEAparser,现在作者改名叫lwgps了,license比较友好MIT的,基于ANSI C99l垒的码移植起来也很简单,具体见论坛的帖子。


    API使用介绍
    第一步,声明全局句柄lwgps_t hgps;
    第二步,初始化lwgps_init(&hgps);
    第三步,在while(1)或者任务中调用lwgpsprocess(&hgps, gpsrxdata, strlen(gpsrx_data));


    剩下的就可以通过,hgps.is_valid来判断GPS模块是否定位成功,如果定位成功则hgps.latitude和hgps.longitude就是经纬度数据,hgps.altitude就是高度数据。当然也可以通过hgps的date,month,year等获取时间数据,hpgs.speed获取速度数据等等。具体参考hgps的定义即可。

    三、附加知识


    如果你GPS的实际数据上传到百度或者高德地图的话,多半会和你实际的地理位置差了几公里...那是因为你的GPS模块吐出来的一般是WGS84坐标系,百度地图用的是BD-09坐标系,高德地图用的是GCJ-02坐标系。


    国外的地图服务商可能会用WGS84坐标系... 数据偏移的算法也不难,网上可查,但是作为一个CTRL+C/V的程序员还是推荐一个开源的代码库ChinaMapShift,license依旧是友好的MIT。


    API使用介绍
    第一步,声明 WGS84和 GCJ02句柄
    Location WGS84;
    Location GCJ02;
    第二步,将GPS输出的合法的WGS84坐标系的数据赋值给WGS84
    WGS84.lat = hgps.latitude;
    WGS84.lng = hgps.longitude;
    第三步,调用transformFromWGSToGCJ()
    GCJ02 = transformFromWGSToGCJ(WGS84);


    剩下的,GCJ02.lat以及GCJ02.lng就是GCJ02坐标系下的经纬度数据了。


    本人水平有限,非常欢迎大家分享如何使用GPS模块的技巧。



    上篇回顾:
    用LPC55xx搭建AIOT平台,步骤分解之传感器篇



    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 00:11 , Processed in 0.105519 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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