MODBUS checksum errors!

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I'm building a system that will use a linux MODBUS master to communicate with a number of atmega164P slaves vie rs485.

Right now, I'm trying to get the freeMODBUD demo up and running on the avr.

I've got modpoll running on the linux box and it is able to send packets to the avr. The avr is then responding but modpoll is reporting a checksum error on the packet that the avr is sending back?

From looking at the forum, I know that a number of you have gotten this working.

I've looked into the CRC16 calculation in freeMODBUS, and it uses the same code to calculate the checksum for incoming packets and outgoing packets (of course it does!)

Why is it that the modpoll is not accepting the avr's packets?

I've got a jtag and an old (not digital) oscilloscope, but I'm not exactly sure how to approach de-bugging this.

Thanks,

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, the AVR is accepting MODBUS CRC as valid in the messages from the linux box?

Fishing here, because I'm not that familiar with MODBUS or CRC16.

Lets see - isn't there a "seed" that has to be supplied to the CRC16 function? If so, are you using the same seed, everywhere?

Have you properly initialized the variables used for the receive CRC before you start the transmit one?

Can you create a response message that should have a known CRC, then check on the host end to see where it is failing?

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

More fishing - if the received CRC is correct according to the AVR, then are you perhaps not calculating the TX CRC over the right data?

You really need to find or build a known TX message and RX response, along with known CRCs, to find where the problem lies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good questions.

Yes, the avr is accepting CRC as valid in messages from the linux box and then using the same function to calculate it's outgoing crc which the linux box then rejects.

Regarding seeds, it seems the seed is 0xFFFF and is set in the avr's CRC16 function that is being used during both receive and transmit... so it appears to be identical in both instances.

The variables appear to be getting setup correctly, though I will dig a bit deeper in to this.

I'm not sure how to create such a message. This is part of my current dilemma. Also, while modpoll is free, it does not appear to be open source, so I am unable to check the CRC16 algorithm it is using in code.

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Modbus crc was discussed recently and a few of us posted code. Post your request and response data and we might be able to detect a problem. The other tning to be aware of is bus biading when using rs485 - get it wrong and you can get a dud char added to the packet which upsets the protocol.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,

It took me a little while to figure out how to get this info, but I think I got it right.

The master is sending out the same frame over and over. it has a length of 0x08 and looks like this...

0x00   -   0x0A
0x01   -   0x04
0x02   -   0x03
0x03   -   0xE7
0x04   -   0x00
0x05   -   0x04
0x06   -   0x40
0x07   -   0xC1

The slave is sending back packets that are changing, but they are all the same length 0x0D. Here are 2...

0x00   -   0x0A
0x01   -   0x04
0x02   -   0x08
0x03   -   0x81
0x04   -   0x90
0x05   -   0x00
0x06   -   0x00
0x07   -   0x00
0x08   -   0x00
0x09   -   0x00
0x0A   -   0x00
0x0B   -   0x58
0x0C   -   0x8C
0x0D   -   0x00

0x00   -   0x0A
0x01   -   0x04
0x02   -   0x08
0x03   -   0x83
0x04   -   0xF6
0x05   -   0x00
0x06   -   0x00
0x07   -   0x00
0x08   -   0x00
0x09   -   0x00
0x0A   -   0x00
0x0B   -   0xDF
0x0C   -   0x53
0x0D   -   0x00

I haven't yet figured out how to independently check the crc.

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like the rs485 biasing is wrong as you have a 0x00 on the end. The byte length is 8 and then the 2 byte crc. Then you have the dud 0x00. If you are using rs485 you are getting a break when the transmitter finishes otherwise you are sending one byte too many.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmmm...

It seems that the spec calls for the frame length to be counted from zero so 0-7 is in fact 8 bytes, and that the 0x00 at 0x0D on the end is actually beyond the frame.

Also, the length that I posted is the buffer length generated in the code, so it includes the crc.

Ok, so dissecting the master's output frame...

It seems that the master is sending function code 0x04 which corresponds to "Read Input Register" in the MODBUS spec.

According to that function spec, there are 2 bytes that define the starting register which are 0x03 & 0xE7, which is 999 in decimal. (this refers to register 1000 as it is subject to the same "starting at zero" thing as described in the spec)

Then we have 2 bytes to define the quantity of input registers to read, 0x00 & 0x04 which is to say 4.

Then the CRC for 2 bytes. Frame length 8 (starting at 0x00)

This all seems well and good.

-

So the response frame is supposed to go like this I think.

First 2 bytes are slave address followed by function code... 0x0A and 0x04.

Next byte (address 0x02) is the data byte count, which is to say the number of 16 bit registers x 2. This is 0x08 which is exactly correct as the number of registers to be read was 4.

Only the first register has any data in it, so we get that data plus 3 empty registers, or 6 bytes of 0x00.

Then we get the CRC for 2 bytes, and then the end of the frame.

This all appears to check out with the spec.

So, I guess that the thing to do would be to see what the master is receiving. Once again, I'm stuck on the fact that I am not able to directly observe the data that the modpoll program is receiving. I guess I need to find either an open source MODBUS master program that I can compile and run in gdb, or I need to find a closed MODBUS master program that will give me more detailed access to the frame data.

Suggestions?

Thanks.

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With modbus rtu, the data packet is framed by time. Therefore if there really is the extra byte of 0 it will upset the receiver. Most receiver code will simply receive any number of bytes until there is no data for the required 3.5 char times. Then it will do a crc check on the packet. With the extra 0 on the end of the packet, the crc will fail and the packet will be rejected. If you want some open source modbus code, if you are using linux, look at mbusd which is a modbus gateway app. It is not very big as it doesnt have to do too much. If you are using Windows, there is modscan and modsim. Modscan is the master and you can have it display the serial data sent/ received.

Just because the master knows what the request was and can figure out the expected length of the response, most don't work that way - you can always get an exception which is 5 bytes long. I know my code frames by time and most others do the same according to the modbus spec. This feature makes it a pain to do modbus rtu on a PC whereas modbus adcii is a breeze.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting.

I'm not sure exactly what was sent. Rather, this is just what was in the send and receive buffer. The send buffer was quite long, and I just copied and pasted one extra byte of data.

I'll look into mdusd and modscan. Thanks!

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,

So, I'm still stumped a bit on this issue.

I've downloaded modscan and it is great. It lets me see both the data being sent to the slave and the data being received by the master.

What is clear from this is that the slave is correctly receiving the frame, and then correctly formulating a response frame. Then, as I step through the code, it appears that it is sending the correct response frame...

but, the master appears to receive a bunch of crap bytes before it gets the beginning of the correct frame.

This is very weird, in part because it is not as though the master is simply receiving random crap. Rather, it is receiving the exact same 7 bytes of crap before the correctly formatted frame begins?????

What the slave is sending is as above. What the master is receiving is...

0x00   -   0x9F
0x01   -   0x31
0x02   -   0xFF
0x03   -   0xF7
0x04   -   0xFF
0x05   -   0xFA
0x06   -   0x00
0x07   -   0x0A
0x08   -   0x04
0x09   -   0x08
0x0A   -   0x12
0x0B   -   0x9A
0x0C   -   0x00

As you can see, the real frame seems to start at 0x07 (with data = 0x0A) and appears to be coming in correctly before it gets cut off by the master who is only looking for 13 bytes.

Where is this pre-frame crap coming from, and how do I get rid of it???

Suggestions?

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,

I got it. It seems I had a bad piece of hardware. The rs-485 to USB converter was creating a reflection I guess. Moving to the a backup fixed the problem!

Thanks for your help

B

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

More likely that the RS485 bus is not biased correctly as I mentioned earlier or the interface echoes the send data. Modbus RTU requires you to have 'clean' data - no crap before or after the packet. Whereas other protocols that have start and end tokens can tolerate this such as Modbus ascii. The other thing that can bring you unstuck is timing gaps in the packet. This can happen if you use protocol converters.