Closed tcurdt closed 1 year ago
Ah, I guess it's "failed to read" plus protocol error
Hi Torsten,
Indeed, that's "failed to read: protocol error". Usually, this means the library read something back off the serial line and either can't make sense of it or found an actual protocol violation.
I can't look at the code right now, but what's the exact message you've got? Mind posting a snippet of code? Or was it using modbus-cli?
Assuming the VFD speaks modbus RTU and the serial speed is set appropriately, did you try playing with stop bits (1 or 2) and/or parity (even, odd or none)?
On RS-485 links, inverting polarities most often results in timeouts as receivers don't see the framing they are expecting.
On 26/05/2023 15:25, Torsten Curdt wrote:
I am trying debug a connection to a VFD.
Depending on how I switch A and B I get either
failed to read request timed out
or
failed to read protocol error
I didn't quite find the protocol error in the source code. Or is this error https://github.com/simonvetter/modbus/blob/4b0c5defc4ebb0ecf197003cc73260672fafc4d9/tcp_transport.go#L155 it?
To me it sounds like "failed to read protocol error" is getting at least something back - so that's the correct A/B connection. But the data coming back is wrong and hence the protocol error.
— Reply to this email directly, view it on GitHub https://github.com/simonvetter/modbus/issues/30, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAWG3CATUY5VK6FC6AYR3TXICVNDANCNFSM6AAAAAAYQHR25Q. You are receiving this because you are subscribed to this thread.Message ID: @.***>
-- Simon Vetter
Thanks for the quick response!
Indeed, that's "failed to read: protocol error". Usually, this means the library read something back off the serial line and either can't make sense of it or found an actual protocol violation.
That's sounds in line with what I am seeing with another implementation. (A GRBL board that is reading only nonsense values.)
Since I now figured out the details of the error this probably goes beyond the context of the library. So feel free to close at any time.
But since you asked, I'll write down the details. Maybe it's helpful for someone else at some stage. And if you have any pointers to debugging this I'd be more than grateful.
-- I've setup a YL620A VFD. (Link to manual)
P00.13=10 # factory reset
P00.01=3 # controlled by RS485
P07.08=5 # controlled by RS485
P03.00=3 # baud (3=9600, 4=19200)
P03.01=1 # set RS485 slave id to 1
P03.02=2 # 8 N 1
So the RS485 should be set to 9600@8N1.
In theory it could be really bad EMI - which I doubt without a spindle attached or running. I wrote a quick test program to see if I can read some meaningful data.
package main
import (
"fmt"
"time"
"github.com/simonvetter/modbus"
)
type Value int
func uints2value(uints []uint16, signed bool) Value {
value := Value(0)
if signed && uints[0]&(1<<15) != 0 {
value = -1
}
for _, u := range uints {
value = value << 16
value = value | Value(u)
}
return Value(value)
}
func read(BaudRate uint) {
PortPath := "/dev/tty.usbserial-110"
DataBits := uint(8)
Parity := modbus.PARITY_NONE
StopBits := uint(1)
client, err := modbus.NewClient(&modbus.ClientConfiguration{
URL: "rtu://" + PortPath,
Speed: BaudRate,
DataBits: DataBits,
Parity: Parity,
StopBits: StopBits,
Timeout: 500 * time.Millisecond,
})
if err != nil {
panic(fmt.Errorf("cannot create client: %w", err))
}
err = client.Open()
if err != nil {
panic(fmt.Errorf("cannot open client: %w", err))
}
for i:=0 ; i<5 ; i++ {
address := 8451
//address := 8203
signed := false
quantity := 1
registers16, err := client.ReadRegisters(uint16(address), uint16(quantity), modbus.HOLDING_REGISTER)
if err != nil {
fmt.Println("failed to read", err)
} else {
value := uints2value(registers16, signed)
fmt.Println("value", value)
}
time.Sleep(1000)
}
}
func main() {
read(uint(9600))
read(uint(19200))
read(uint(38400))
}
It's a bit absurd. It's not my first rodeo with this VFD. At that time it was one of the wires not having proper contact. After fixing the cable it worked back then. (Doh!) That said, I think I was getting timeouts instead of protocol errors. So when I ran into troubles this time, I switched to a new cable - but so far no luck. It's a shame there is no good way to measure if A+B are connected correctly (to my knowledge).
My first guess was also a baud rate mismatch. Unfortunately I don't have a proper oscilloscope handy to dig a bit deeper into the signals.
Anyway - if you have any ideas it would be great.
But feel free to close the ticket. The original question got answered :)
I'd try to call Close() on the client before switching to the next baudrate to properly close and release the serial port, even though that's probably not the root cause.
Did you place proper 120Ohm termination resistors ? If your bus is short and you only have one, then place one, but those are needed (if not included in the endpoints).
Other things I'd try, if you haven't already :
Since you mentioned not being able to use an oscilloscope, another way of sniffing the wire could be to use two USB to RS485 adapters : one would be used by the modbus client while the other would run a program merely dumping raw bytes seen on the wire.
I'm gonna go ahead and close this but feel free to come back and comment with your findings! HTH, good luck!
I'd try to call Close() on the client before switching to the next baudrate to properly close and release the serial port, even though that's probably not the root cause.
👍
Did you place proper 120Ohm termination resistors ? If your bus is short and you only have one, then place one, but those are needed (if not included in the endpoints).
I measured. It seems only the usb adapter has termination. So that's only one side of a 30cm cable. I'll try with a 2nd 120 ohm resistor when I am back with the machine.
Other things I'd try, if you haven't already :
- configuring 2 stop bits in the client,
Even when it's configured to 1 stop bit on the VFD?
- using a shorter and/or shielded RS-485 wire,
The cable was shielded with the shield connected to the frame. I also tried a 10cm cable.
- wiring the COM terminal in addition to A/B terminals of the RS485 link, and connecting the shield to PE/chassis ground,
After some research it seems connecting GND (not just A+B) is important. But I had done that from the start.
- using another, potentially different make and model USB to RS485 adapter (I've fried a couple in my life in unexpected ways, especially in industrial environments),
It started with the board having problems talking to the VFD. Only then I switched to the adapter that also showed problems. The adapter worked before. So essentially both clients would need to be fried. Possible - but not so likely.
But I might just get another usb adapter to try.
- borrowing an oscilloscope or signal analyzer to dump what goes over the wire.
I will bring my scope the next time I am at the machine. A shame I didn't bring it in the first time.
another way of sniffing the wire could be to use two USB to RS485 adapters : one would be used by the modbus client while the other would run a program merely dumping raw bytes seen on the wire.
Uh, interesting. How would you do that? Just have it in parallel and then open it as serial port and dump the raw bytes?
I will bring my scope the next time I am at the machine. A shame I didn't bring it in the first time.
If you ever get a chance to do that and find what the issue is, would you be able to post the waveforms in here? Just curious.
Uh, interesting. How would you do that? Just have it in parallel and then open it as serial port and dump the raw bytes?
Yes, precisely what I had in mind :)
It will probably take another month until I get to it - but I will keep you posted.
Alright. Finally some time to do some more debugging. This really is beyond the library - but since you asked :)
Maybe you have some insights. I reaching the end of my abilities.
I double checked that the RS485 adapter works. I got another one and created a null-modem connection just fine.
Then I used very short cable of about 15cm, with A/B being twisted and connected the oscilloscope on two channels to A+GND and B+GND.
The base noise level doesn't seem so bad.
When sending data it looks kind of OK to me. I just would have expected higher voltages.
To me it confirms what the transmission LED of the adapter and the error responds suggests: It is sending - but there is just is no response. Now I guess the reasons for that could be endless. That said I am not entirely sure how identify a response coming from the VFD either.
The adapter has a 120 Ohm termination resistor. But I've also tried with another resistor right at the VFD. It didn't change much really. Since I only have GND and no VCC I don't think adding bias resistors is in the cards.
I am wondering if there is any other way to tell whether the RS485 unit on the VFD is just broken - or whether this was the the same behaviour when misconfigured and just not answering.
I could still try the 2nd parallel adapter to read what's on the bus - but if there is no response...
Just for kicks I also tried the 2nd parallel adapter. No dice.
Will order a new VFD :-/
But I've also tried with another resistor right at the VFD. It didn't change much really. Since I only have GND and no VCC I don't think adding bias resistors is in the cards.
Just to make sure, the termination resistors need to be placed between A and B. They're meant to pull the line to line voltage back to 0V after a transmission, they really aren't bias resistors (i.e. pulling lines towards VCC or GND). I'm mentioning this because your first scope screenshot got me thinking: either i'm not reading that properly (which might very well be the case :D) or both lines are at ~1.2V relative to GND when idle, which shouldn't be the case if nothing is driving them (they should be close to 0V).
Also, what's the pinout on that USB to RS485 thingy? aren't the 2 left pins termination resistor connections, in which case they should be tied to A and B? Are you sure GND is indeed the center pin?
Your hex captures with the 2nd adapter show valid modbus RTU requests, with register addresses matching your code, so that's a start.
Just to make sure, the termination resistors need to be placed between A and B.
(nod) That's how I tried it.
They're meant to pull the line to line voltage back to 0V after a transmission, they really aren't bias resistors (i.e. pulling lines towards VCC or GND).
From what I understood biasing is usually the preferred way to setup RS485. But this isn't really an option in my case. I only have A, B and GND. And I suspect this should only be become important on longer cable lengths.
I'm mentioning this because your first scope screenshot got me thinking: either i'm not reading that properly (which might very well be the case :D) or both lines are at ~1.2V relative to GND when idle, which shouldn't be the case if nothing is driving them (they should be close to 0V).
The Rigol UI really isn't great :-/ but that's also how I read it, too. If they should be close 0V - that's good information.
Also, what's the pinout on that USB to RS485 thingy? aren't the 2 left pins termination resistor connections, in which case they should be tied to A and B? Are you sure GND is indeed the center pin?
Yes, it's clearly marked. I am no longer near the machine so I cannot send an actual photo, but here is an image from the web
Your hex captures with the 2nd adapter show valid modbus RTU requests, with register addresses matching your code, so that's a start.
Indeed. Or the ending :)
I gave in and ordered a new VFD (different brand though). RS485 seems to be working with that one.
Although I am still curious to compare the two. Just to learn what went wrong here.
I am trying debug a connection to a VFD.
Depending on how I switch A and B I get either
or
I didn't quite find the protocol error in the source code. Or is this error it?
To me it sounds like "failed to read protocol error" is getting at least something back - so that's the correct A/B connection. But the data coming back is wrong and hence the protocol error.