QModbusRtuSerialMaster CRC calculation problem
-
Hello there,
I am using qt version 5.6.2. I am trying to write an application that works as ModBus RTU master device. I am using QModbusRtuSerialMaster for that purpose. For tests purposes I am running an example code from serialbus/modbus/master. My problem is that I think that the CRC calculation mechanism for the slave response ins not working properly. For example: I am trying to read holding registers (slave address i 0x05) from address 0, in quantity of 1. For this the master message looks like this:hex values 05 03 00 00 00 01 85 8E
And the example master application is sending this message indeed. The problem occurs when I answer from my slave. My answer should look like this:
Hex values 05 03 01 00 00 B9 84
For the CRC calculation, I am using the exact same alghoritm as in here: https://code.woboq.org/qt5/qtserialbus/src/serialbus/qmodbusadu_p.h.html#_ZNK16QModbusSerialAdu4dataEv
Now here is the console output of the QModbusRtuSerialMaster module when receiving answer from slave:
qt.modbus: (RTU client) Sent Serial PDU: 0x0300000001 qt.modbus.lowlevel: (RTU client) Sent Serial ADU: 0x050300000001858e qt.modbus: (RTU client) Send successful: 0x0300000001 qt.modbus.lowlevel: (RTU client) Response buffer: "05" qt.modbus: (RTU client) Modbus ADU not complete qt.modbus.lowlevel: (RTU client) Response buffer: "0503" qt.modbus: (RTU client) Cannot calculate PDU size for function code: 3 , delaying pending frame qt.modbus.lowlevel: (RTU client) Response buffer: "050301" qt.modbus: (RTU client) Incomplete ADU received, ignoring qt.modbus.lowlevel: (RTU client) Response buffer: "05030100" qt.modbus: (RTU client) Cannot calculate PDU size for function code: 3 , delaying pending frame qt.modbus.lowlevel: (RTU client) Response buffer: "0503010000" qt.modbus: (RTU client) Incomplete ADU received, ignoring qt.modbus.lowlevel: (RTU client) Response buffer: "0503010000b9" qt.modbus: (RTU client) Received ADU: "0503010000b9" qt.modbus: (RTU client) Discarding response with wrong CRC, received: 185 , calculated CRC: 61816 qt.modbus.lowlevel: (RTU client) Response buffer: "84" qt.modbus: (RTU client) Modbus ADU not complete qt.modbus: (RTU client) Receive timeout: 0x0300000001
As you see, at the point of first CRC byte arrival, the module already states that the CRC is wrong and shows a wrongly calculated CRC. I even tried to hardcode the CRC for the slave answer to match the one that master calculates, but he still says its wrong at the first CRC byte, not waiting for the other.
The modbus QT module is quite complicated for me, I am now wondering either it wouldnt be faster to write my own qt modbus rtu master library, with limited functionality. Unless it is possible to find the error here somehow. I would really appreciate all help regarding this issue. Is the library bugged? -
I'm using a my own component. please have a look at these functions that work perfectly:
bool QThModbusManager::Crc16In(QByteArray &QBABytes) { if (QBABytes.length()> 2) { bool Ok; int BccIn= QBABytes.mid(QBABytes.length()- 2, 2).toHex().toInt(&Ok, 16); int buffer_length= QBABytes.length()- 2; unsigned char *buffer= (unsigned char*)QBABytes.data(); unsigned char crc_hi = 0xFF; /* high CRC byte initialized */ unsigned char crc_lo = 0xFF; /* low CRC byte initialized */ int i; /* will index into CRC lookup */ while (buffer_length--) { i = crc_hi ^ *buffer++; /* calculate the CRC */ crc_hi = crc_lo ^ table_crc_hi[i]; crc_lo = table_crc_lo[i]; } if (crc_hi== (BccIn & 0xff00) / 0x100 && crc_lo== (BccIn & 0xff)) return true; else return false; } else return false; } void QThModbusManager::Crc16Out(QByteArray &QBABytes) { int buffer_length= QBABytes.length(); unsigned char *buffer= (unsigned char*)QBABytes.data(); unsigned char crc_hi = 0xFF; /* high CRC byte initialized */ unsigned char crc_lo = 0xFF; /* low CRC byte initialized */ int i; /* will index into CRC lookup */ while (buffer_length--) { i = crc_hi ^ *buffer++; /* calculate the CRC */ crc_hi = crc_lo ^ table_crc_hi[i]; crc_lo = table_crc_lo[i]; } QBABytes.append(crc_hi); QBABytes.append(crc_lo); }
Regards.
-
Hi! As the module is still a technology preview, chances are high that you found a bug or something isn't implemented yet. I'd ask the developers on the mailing list.
-
-
Hi,
it would be really nice if you could share your implementation or provide a broken down example how you generate the response.
Regards, Karsten
-
Hi,
it would be really nice if you could share your implementation or provide a broken down example how you generate the response.
Regards, Karsten
@Karsten-Heimrich I am using the modbus master example from qt creator. As for th slace answer I could give you the code for the platform I use but it would be hard for you to create an experimental setup like that. You will be better of sending this slave response manually from a terminal app, like realterm.
-
Hi, while looking at your response you posted:
Hex values: 05 03 01 00 00 B9 84
I think it does not what the spec predicts. It should look like this:
Address: 1 Byte -> 05 Function code: 1 Byte -> 03 Byte count: 1 Byte -> 01 Register value: N* x 2 Bytes High Byte -> 00 Low Byte -> 00
So obviously your Byte count is wrong, you have to send always a minimum byte count of 2, not 1.
Your response should look like this:
Hex values: 05 03 02 00 00 49 84
You can lookup the spec at http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf page 15
Regards, Karsten