go - 无法通过串口解析GPS信息

标签 go serial-port gps

我使用了以下软件包:

  1. 从串口读取 (go get go.bug.st/serial)
  2. 解析来自串口的传入消息(go get adrianmo/go-nmea)

主机:Windows 10

Go 版本:go 版本 go1.14.4 windows/amd64

根据文档,我编写了一个简单的代码,打开专用串行端口(COM4)并从端口读取 NMEA 数据,并尝试根据 go- 解析数据nmea

数据

来自 GPS 传感器的传入数据:

$GPRMC,135533.000,A,5306.6644,N,00851.3177,E,0.11,214.59,300620,,,A*6E

$GPRMC,135534.000,A,5306.6643,N,00851.3177,E,0.06,187.72,300620,,,A*68

$GPRMC,135535.000,A,5306.6643,N,00851.3177,E,0.22,341.68,300620,,,A*6C

$GPRMC,135536.000,A,5306.6644,N,00851.3176,E,0.20,324.35,300620,,,A*60

$GPRMC,135537.000,A,5306.6645,N,00851.3176,E,0.12,348.37,300620,,,A*69

代码片段

package main

import (
    "fmt"
    "log"

    "github.com/adrianmo/go-nmea"
    "go.bug.st/serial"
)

func main() {

    mode := &serial.Mode{
        BaudRate: 9600,
        Parity:   serial.NoParity,
        DataBits: 8,
        StopBits: serial.OneStopBit,
    }
    serPort, err := serial.Open("COM4", mode)
    if err != nil {
        log.Fatal(err)
    }

    defer serPort.Close()

    buff := make([]byte, 1024)

    for {
        n, err := serPort.Read(buff)
        if err != nil {
            log.Fatal(err)
            break
        }
        if n == 0 {
            fmt.Println("\nEOF")
            break
        }
        rawSentence := string(buff[:n])
        fmt.Print(rawSentence)
        s, err := nmea.Parse(rawSentence)
        if err != nil {
            log.Fatal(err)
        }
        if s.DataType() == nmea.TypeRMC {
            m := s.(nmea.RMC)
            fmt.Printf("Raw sentence: %v\n", m)
            fmt.Printf("Time: %s\n", m.Time)
            fmt.Printf("Validity: %s\n", m.Validity)
            fmt.Printf("Latitude GPS: %s\n", nmea.FormatGPS(m.Latitude))
            fmt.Printf("Latitude DMS: %s\n", nmea.FormatDMS(m.Latitude))
            fmt.Printf("Longitude GPS: %s\n", nmea.FormatGPS(m.Longitude))
            fmt.Printf("Longitude DMS: %s\n", nmea.FormatDMS(m.Longitude))
            fmt.Printf("Speed: %f\n", m.Speed)
            fmt.Printf("Course: %f\n", m.Course)
            fmt.Printf("Date: %s\n", m.Date)
            fmt.Printf("Variation: %f\n", m.Variation)
        }
    }
}

问题

如果我运行代码,我会收到以下错误:

2020/06/30 16:02:16 nmea: sentence does not start with a '$' or '!'
exit status 1

这很奇怪,因为如果我注释掉代码解析代码:

        // s, err := nmea.Parse(rawSentence)
        // if err != nil {
        //  log.Fatal(err)
        // }
        // if s.DataType() == nmea.TypeRMC {
        //  m := s.(nmea.RMC)
        //  fmt.Printf("Raw sentence: %v\n", m)
        //  fmt.Printf("Time: %s\n", m.Time)
        //  fmt.Printf("Validity: %s\n", m.Validity)
        //  fmt.Printf("Latitude GPS: %s\n", nmea.FormatGPS(m.Latitude))
        //  fmt.Printf("Latitude DMS: %s\n", nmea.FormatDMS(m.Latitude))
        //  fmt.Printf("Longitude GPS: %s\n", nmea.FormatGPS(m.Longitude))
        //  fmt.Printf("Longitude DMS: %s\n", nmea.FormatDMS(m.Longitude))
        //  fmt.Printf("Speed: %f\n", m.Speed)
        //  fmt.Printf("Course: %f\n", m.Course)
        //  fmt.Printf("Date: %s\n", m.Date)
        //  fmt.Printf("Variation: %f\n", m.Variation)
        // }

串口打印如上所述的GPS坐标。

我哪里出错了?我尝试通过在代码中执行以下操作来删除换行回车:

        rawSentence := string(buff[:n])
        rawSentence = string.ReplaceAll(rawSentence, "\r\n", "")
        fmt.Print(rawSentence)

但我仍然遇到同样的错误。

最佳答案

我能够找出问题所在。我首先检查我的字节通常是如何从以下代码中读取的:

     n, err := serPort.Read(buff)
     fmt.Printf("%d", n)

它依次给出值17374。假设1是设备本身发送的换行符,我发现这可能是代码无法捕获$GPRMC的原因。

因此我修改了代码来检查读取的字节数是否始终大于 1 字节

    for {
        n, err := serPort.Read(buff)
        fmt.Printf("%v\n", n)
        if err != nil {
            log.Fatal(err)
            break
        }
        // do not try to parse a single read byte
        // instead parse the actual incoming string.
        if n > 1 {
            rawSentence := string(buff[:n])
            fmt.Print(rawSentence)
            s, err := nmea.Parse(rawSentence)
            if err != nil {
                log.Fatal(err)
            }
            if s.DataType() == nmea.TypeRMC {
                m := s.(nmea.RMC)
                fmt.Printf("Raw sentence: %v\n", m)
                fmt.Printf("Time: %s\n", m.Time)
                fmt.Printf("Validity: %s\n", m.Validity)
                fmt.Printf("Latitude GPS: %s\n", nmea.FormatGPS(m.Latitude))
                fmt.Printf("Latitude DMS: %s\n", nmea.FormatDMS(m.Latitude))
                fmt.Printf("Longitude GPS: %s\n", nmea.FormatGPS(m.Longitude))
                fmt.Printf("Longitude DMS: %s\n", nmea.FormatDMS(m.Longitude))
                fmt.Printf("Speed: %f\n", m.Speed)
                fmt.Printf("Course: %f\n", m.Course)
                fmt.Printf("Date: %s\n", m.Date)
                fmt.Printf("Variation: %f\n", m.Variation)
            }
        }
    }

果然,代码现在可以运行,并且导出的输出正是我所期望的:

$GPRMC,142312.000,A,5306.6774,N,00851.3114,E,0.04,14.48,300620,,,A*5A
Raw sentence: $GPRMC,142312.000,A,5306.6774,N,00851.3114,E,0.04,14.48,300620,,,A*5A
Time: 14:23:12.0000
Validity: A
Latitude GPS: 5306.6774
Latitude DMS: 53° 6' 40.644000"
Longitude GPS: 851.3114
Longitude DMS: 8° 51' 18.684000"
Speed: 0.040000
Course: 14.480000
Date: 30/06/20
Variation: 0.000000

关于go - 无法通过串口解析GPS信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62659313/

相关文章:

go - GC是否处理数组的未指向部分

c++ - 无法打开 UART。确保它没有被其他应用程序使用

Android - 进程已死亡问题

Golang 更改导入模块名称失败

shell - 在 Golang 中需要交互式输入的测试执行程序

java - 什么比从modbus串口读取数据更好,关闭或保持连接打开

vba - 从 VBA 访问串行端口的最佳方法是什么?

android - 使用 GPS 获取用户的当前位置

c# - 适用于 .Net/C# 的 GPS 驱动程序,用于从任何支持 NMEA 的 GPS 装置中提取 GPS 数据

google-app-engine - 在 Go 中合并独立的 webapp 和 GAE