ublox의 GPS 모듈의 포지셔닝 간격을 변경하는 명령을 golang으로 만들었습니다.

13501 단어 5RaspberryPiGPS


USB로 연결하는 GPS 모듈을 얻었습니다.
ublox 칩셋을 사용하는 것입니다.
기본적으로 초당 한 번의 간격으로 포지셔닝을 수행합니다. 보통의 용도라면 이대로 해도 괜찮습니다만, 이것을 변경하는 커멘드를 조사해, 그것을 보내는 커멘드를 golang로 만들었습니다

ublox 확장 명령을 사용하므로 ublox 사의 칩에서만 사용할 수 있습니다.

사용법


$ ./gps_ublox
Usage: ./gps_ublox /dev/ttyACM0 rate
rate is in msec. (100 <= rate <= 65535)

500ms 간격으로 위치를 지정하려면 다음을 수행합니다. (/dev/ttyACM0은 GPS 모듈의 장치 파일)
$ ./gps_ublox /dev/ttyACM0 500
$ cat /dev/ttyACM0 > gps.nmea

빌드 방법


$ go get .
$ go build
GOARCH=arm go build 로 크로스빌드하면 라즈파이에서도 사용할 수 있습니다.

소스 코드



gps_ublox.go

package main

import (
    "bufio"
    "fmt"
    "github.com/tarm/serial"
    "io"
    "log"
    "os"
    "strconv"
)

// Refer "u-blox 7 Receiver Description Including Protocol Specification V14"

func main() {
    if len(os.Args) < 3 {
        fmt.Fprintf(os.Stderr, "Usage: %s /dev/ttyACM0 rate\nrate is in msec. (100 <= rate <= 65535)\n", os.Args[0])
        os.Exit(1)
    }

    c := &serial.Config{Name: os.Args[1], Baud: 115200}
    s, err := serial.OpenPort(c)
    if err != nil {
        log.Fatal(err)
    }
    defer s.Close()

    rate, err := strconv.Atoi(os.Args[2])
    if err != nil {
        log.Fatal(err)
    }
    if rate < 100 {
        rate = 100
    }   
    if rate > 0xffff {
        rate = 0xffff
    }
    cmd := []byte{0x06, 0x08,
        0x06, 0x00, /* len */
        byte(rate & 0xff),
        byte((rate >> 8) & 0xff),
        0x01, 0x00, 0x00, 0x00}
    sendCmd(s, cmd)
    os.Exit(0)
}

func sendCmd(s io.ReadWriter, cmd []byte) {
    cmdbuf := []byte{0xb5, 0x62}
    cmdbuf = append(cmdbuf, cmd...)
    ck_a, ck_b := chksum(cmd)
    cmdbuf = append(cmdbuf, ck_a, ck_b)

    //fmt.Printf("cmdbuf = %x\n", cmdbuf)
    n, err := s.Write(cmdbuf)
    if err != nil {
        log.Fatal(err)
    }
    if n != len(cmdbuf) {
        log.Fatal(err)
    }

    waitAck(s, cmd[0], cmd[1])
}

func chksum(payload []byte) (ck_a, ck_b byte) {
    ck_a = 0
    ck_b = 0
    for _, b := range payload {
        ck_a += b
        ck_b += ck_a
    }
    return
}

func waitAck(s io.Reader, class_id, msg_id byte) {
    ack := []byte{0xb5, 0x62, 0x05, 0x01, 0x02, 0x00, class_id, msg_id}

    reader := bufio.NewReaderSize(s, 128)
loop:
    for {
        _, err := reader.ReadBytes(0xb5)
        if err != nil {
            log.Fatal(err)
        }
        for _, a := range ack[1:] {
            b, err := reader.ReadByte()
            if err != nil {
                log.Fatal(err)
            }
            //fmt.Printf("b = %x\n", b)
            if b != a {
                continue loop
            }
        }
        /* TODO: check check sum */
        //fmt.Printf("ack ok\n")
        return
    }
}

좋은 웹페이지 즐겨찾기