Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading from serial port with while-loop

Tags:

go

I’ve written a short program in Go to communicate with a sensor through a serial port:

package main

import (
    "fmt"
    "github.com/tarm/goserial"
    "time"
)

func main() {
    c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 9600}
    s, err := serial.OpenPort(c)

    if err != nil {
            fmt.Println(err)
    }

    _, err = s.Write([]byte("\x16\x02N0C0 G A\x03\x0d\x0a"))

    if err != nil {
            fmt.Println(err)
    }

    time.Sleep(time.Second/2)

    buf := make([]byte, 40)
    n, err := s.Read(buf)

    if err != nil {
            fmt.Println(err)
    }

    fmt.Println(string(buf[:n]))

    s.Close()
}

It works fine, but after writing to the port I have to wait about half a second before I can start reading from it. I would like to use a while-loop instead of time.Sleep to read all incoming data. My attempt doesn’t work:

buf := make([]byte, 40)
n := 0

for {
    n, _ := s.Read(buf)

    if n > 0 {
        break
    }
}

fmt.Println(string(buf[:n]))

I guess buf gets overwritten after every loop pass. Any suggestions?

like image 926
laserbrain Avatar asked Jul 11 '13 16:07

laserbrain


1 Answers

Your problem is that Read() will return whenever it has some data - it won't wait for all the data. See the io.Reader specification for more info

What you want to do is read until you reach some delimiter. I don't know exactly what format you are trying to use, but it looks like maybe \x0a is the end delimiter.

In which case you would use a bufio.Reader like this

reader := bufio.NewReader(s)
reply, err := reader.ReadBytes('\x0a')
if err != nil {
    panic(err)
}
fmt.Println(reply)

Which will read data until the first \x0a.

like image 104
Nick Craig-Wood Avatar answered Oct 05 '22 19:10

Nick Craig-Wood