-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transaction causes device to spew newlines #160
Comments
Big upvote for this here. I am implementing a driver for a laboratory balance, facing EXACTLY the same issue as above. |
Please provide the source code to reproduce the issue. |
@Darkskald The way I ended up solving this issue is by adding a mutex to the balance struct and making sure I write once every 1 second minimum. Writing faster will trigger the amok state (though have not tested at what frequency the bug pops up). I am not using a read timeout, but am wrapping the serial device with a The code to reproduce would look somewhat like mode := &serial.Mode{
BaudRate: 1200,
Parity: serial.NoParity,
DataBits: 8,
StopBits: serial.OneStopBit,
}
port, _ := serial.Open(ports[0], mode) // Got port from listports
var buffer [1024]byte
cmd := []byte("D05\r\n") // Read scale command.
port.Write(cmd)
n, _ :=port.Read(buffer[:])
port.Write(cmd) // Two fast writes should be enough to trigger error
n, _ =port.Read(buffer[:])
port.Write(cmd)
n, _ =port.Read(buffer[:])
port.Write(cmd)
n, _ =port.Read(buffer[:])
fmt.Println(buffer[:n]) // Get newlines? |
It could be that you get partial Reads. if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err := port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
// The content of the buffer[:n] here may be a partial response
// You may need to read again to get the remainder of the full response
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err = port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err = port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err := port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
fmt.Println(buffer[:n]) |
The partial reads are not material to the issue of newline spewing. The
issue I'm having is that I must be extremely careful when using bugst
compared to cutecom and pyserial since writing too frequently with bugst
will cause the scale to irrecoverably go into a state where all it does is
write newlines until I unplug and plug again.
Normally I'd attribute this to bad firmware or hardware... but I then
observed cutecom and pyserial never run into the issue so I began wondering
if it was a problem in how linux port is handled by bugst.
…On Sun, Feb 18, 2024, 13:16 Cristian Maglie ***@***.***> wrote:
It could be that you get partial Reads.
May you try to print the results of all Read operations?
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err := port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
// The content of the buffer[:n] here may be a partial response
// You may need to read again to get the remainder of the full response
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err = port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err = port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
if err := port.Write(cmd); err != nil {
fmt.Println("Error writing to port: ", err)
}
n, err := port.Read(buffer[:])
fmt.Printf("READ: n=%d err=%v data:>%s<", n, err, buffer[:n])
fmt.Println(buffer[:n])
—
Reply to this email directly, view it on GitHub
<#160 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A5BK55VAXBZN63YQG4WBWXDYUISOTAVCNFSM6AAAAAAZDQNIX2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNJRGM3TINBRGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
I'll also note that I started work on a pyserial syscall-identical serial implementation in Go to test this out here, still not finished since reading syscall python code is quite hard to follow. |
In my opinion, is the firmware that is buggy and goes into this weird loop state if you try to send a command while the scale is still writing the response of the previous command. |
To support my hypothesis you may try to use this function instead of the simple func ReadLine(port serial.Port) (string, error) {
buf := make([]byte, 100)
line := ""
for {
n, err := port.Read(buf[:])
if err != nil {
return "", err
}
if n == 0 {
return line, errors.New("timeout")
}
line += string(buf[:n])
if i := strings.Index(line, "\n\r"); i != -1 {
return line[:i], nil
}
}
} |
For example, I'm working with a electronic scale. When I open it with cutecom and select 1200 baud, 8 bits data, no parity, 1 stop bit I can send the "Get Weight" command which is
D05\r\n
, then I see in console123.032g\r\n
.When I try to use go-serial and writing the command after opening it with same mode parameters, setting the read timeout to 1 second I get my buffer filled with newlines as soon as I send the command. Switching to Cutecom and opening the port in this state causes cutecom to crash due to the newlines filling the log. The only way to reset the devices gone-amok state is by disconnecting and connecting the USB cable.
Why would go-serial give different behavior to pySerial and cutecom? What could be making the device to enter this tilted/"stuck" state?
The text was updated successfully, but these errors were encountered: