Goland 从 EC20 网卡获取 GPS 信息

EC20是移远一款带有GPS功能的LTE模块,本文主要讲述此模块GPS功能的基本使用方法,更多详细的指令操作细节、参数、示例可参考官网提供的手册: Quectel_EC20_GNSS_AT_Commands_Manual_V1.1


端口说明:
在Linux系统下,EC20被成功识别并加载后,会有四个/dev/ttyUSBx设备文件,ttyUSB2用于AT指令收发,ttyUSB1用于GPS NMEA的接收。

开启 GPS 功能 
echo -e "AT+QGPS=1\r\n" >/dev/ttyUSB2

查看 GPS 信息

cat /dev/ttyUSB1




其中

$GPGGA 是 GPS 定位数据

$GPRMC 是 推荐定位数据

我们采用 $GPRMC


$GPRMC,082006.000,A,3852.9276,N,11527.4283,E,0.00,0.0,261009,,*38

$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11><CR><LF>

(1) 标准定位时间(UTC time)格式:时时分分秒秒.秒秒秒(hhmmss.sss)。

(2) 定位状态,A = 数据可用,V = 数据不可用。

(3) 纬度,格式:度度分分.分分分分(ddmm.mmmm)。

(4) 纬度区分,北半球(N)或南半球(S)。

(5) 经度,格式:度度分分.分分分分。

(6) 经度区分,东(E)半球或西(W)半球。

(7) 相对位移速度, 0.0 至1851.8 knots

(8) 相对位移方向,000.0 至359.9 度。实际值。

(9) 日期,格式:日日月月年年(ddmmyy)。

(10) 磁极变量,000.0 至180.0。

(11) 度数。

(12) Checksum.(检查位)



使用 Golang 实现上面功能


package main

import (
"fmt"
"github.com/tarm/serial"
"log"
"shanxi120/util"
"strconv"
"strings"
"time"
)

func main() {
// 初始化配置
GetConfig()

// at 命令发送到 ttyUSB2, 开启 gps 开关
if sendOpen() != nil {
return
}

// 从 ttyUSB1 获取 gps 信息
var data string
c := &serial.Config{Name: "/dev/ttyUSB1", Baud: 115200}
s, err := serial.OpenPort(c)
if err != nil {
log.Fatal(err)
}

// 从 ttyUSB2 获取数据
go receiveData(s, &data)

// 提取 gps 数据
deCode(&data)
}

// at 命令发送到 ttyUSB2, 开启 gps 开关
func sendOpen() error {
c := &serial.Config{Name: "/dev/ttyUSB2", Baud: 9600}
s, err := serial.OpenPort(c)
if err != nil {
fmt.Println("打开 ttyUSB2 失败")
log.Fatal(err)
return err
}
_, err = s.Write([]byte("AT+QGPS=1\r\n"))
if err != nil {
fmt.Println("向 ttyUSB2 发送 命令失败")
log.Fatal(err)
return err
}
s.Close()

return nil
}

// 从 ttyUSB1 获取数据
func receiveData(s *serial.Port, data *string) {
for {
buf := make([]byte, 128)
n, err := s.Read(buf)
if err != nil {
log.Fatal(err)
}

fmt.Printf("Read %d Bytes\r\n", n)

*data += string(buf)
}
}

// 提取 gps 数据
func deCode(data *string) {
for {
start := strings.Index(*data, "$GPRMC")
if start != -1 {
*data = (*data)[start:]
end := strings.Index(*data, "\r")
if end != -1 {
// gps 信息
g := (*data)[:end]
deGps(g)

// 移除已经取出的数据
*data = (*data)[end:]
fmt.Println("gps info ============ data len", len(*data), " --------", time.Now(), "\n", g, "\n")
}
}
}
}

// 坐标转 wgs84
// 转化公式为 dd.ddddd = dd + mm.mmmm/60
func deGps(s string) {
arr := strings.Split(s, ",")
fmt.Println(arr)

if len(arr[3]) <= 0 || len(arr[5]) <= 0 {
fmt.Println(s)
fmt.Println("定位失败 ==================================================")
return
}

// ec20 纬度ddmm.mmmm
ln1, _ := strconv.ParseFloat(arr[3][:2], 10)
ln2, _ := strconv.ParseFloat(arr[3][2:], 10)

// ec20 经度dddmm.mmmm
la1, _ := strconv.ParseFloat(arr[5][:3], 10)
la2, _ := strconv.ParseFloat(arr[5][3:], 10)


// WGS84 地球坐标系

lng := ln1 + ln2/60

   lat := la1 + la2/60

fmt.Println("ec20 gps ", "lng:", lng, "lat", lat)

// BD09 百度坐标系
fmt.Println("百度坐标系 ==================================================")
fmt.Println(util.WGS84toBD09(lng, lat))

}



2222
0
2年前