View previous topic :: View next topic |
Author |
Message |
snock
Joined: 10 Oct 2011 Posts: 24
|
CCS Modbus (RTU) libraries |
Posted: Fri Mar 13, 2020 8:30 pm |
|
|
Hello everyone. I am using the CCS included Modbus library for a Modbus RTU project and everything is working normally except for what I think is lack of CRC error checking on received packets.
I think that I'm picking up a little noise on the RS485 lines from a three phase motor and that this is causing some bits to be flipped in the modbus_rx array of the CCS library.
If that is indeed the case then it's extremely unlikely that the CRCs would match. I haven't gone through the code much yet, but can does anyone know whether the CCS library actually compares the CRCs and if so, where in the code it does so?
I'm actually using this one two different boards, one master and the other slave, so I'd have to modify the library in two places if that's my problem.
Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sat Mar 14, 2020 1:29 am |
|
|
The library _calculates_ the CRC.
It is up to you to then test that this matches. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sat Mar 14, 2020 7:25 am |
|
|
re: ... Quote: | I think that I'm picking up a little noise on the RS485 lines from a three phase motor. |
Be sure to have the proper and correct pullup, bias, and pulldown resistors ! Calculate based upon baudrate as well as distance and wire type.
Also have you turned off that 3* motor to confirm it's the source of the EMI ? |
|
|
snock
Joined: 10 Oct 2011 Posts: 24
|
|
Posted: Mon Mar 23, 2020 5:42 pm |
|
|
The source of the EMI is irrelevant as noise on the RS485 line would yield a bad CRC, but it is indeed coming from the motor leads.
Yeah, I see where it is calculated in the modbus_phy_layer_rtu.c file, but like Ttelmah says, it only calculates the CRC and never does anything with it. The issue is that reading modbus_serial_crc.d always reads 0xffff right after I use the read holding registers function. I haven't had much time to go through the CCS code but I think the received CRC bytes should be in modbus_rx.data[modbus_rx.len+2] and modbus_rx.data[modbus_rx.len+3] as the code appears decrement modbus_rx.len by two upon receipt of a packet which makes perfect sense as those are the last two bytes.
In any case, the Modbus code should be fixed to check the CRC and set the modbus_rx.error byte if the check fails. I don't think I am doing anything wrong, but like I said, modbus_serial_crc.d always reads 0xffff after reading the holding registers.
I forgot to mention that I am running v5.093 which should be the latest. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Mar 23, 2020 7:46 pm |
|
|
re:
Not irrelevent. As you've confirmed the source of the EMI, you should be able to eliminate the EMI.
I've run low speed serial links though shops filled with dozens of 3* welding machines and other 'EMI generators', and never had communications disrupted or corrupted data. I've also run miles, yes, miles of serial links without loss or corrupted data. |
|
|
snock
Joined: 10 Oct 2011 Posts: 24
|
|
Posted: Mon Mar 23, 2020 8:53 pm |
|
|
Sorry, I meant it's only irrelevant in the case of not comparing the received CRC with the calculated CRC. There still needs to be a way of detecting errors on the line.
I've been digging through the code and it looks like they're calculating the CRC for every byte that comes in including the CRC which isn't any good.
Once the timeout occurs (modbus_timeout_now) then modbus_rx.len has 2 subtracted from it to just disregard the CRC bytes.
Anyways, I added a crc member to the modbus_rx struct and modified the code as follows:
Code: |
// Purpose: Handles a timeout when waiting for a response
// Inputs: None
// Outputs: None
// Not used for ASCII mode
void modbus_timeout_now(void)
{
if((modbus_serial_state == MODBUS_GETDATA) && (modbus_serial_crc.d == 0x0000) && (!modbus_serial_new))
{
modbus_rx.crc=make16(modbus_rx.data[modbus_rx.len-2],modbus_rx.data[modbus_rx.len-1]); // 03/23/20
modbus_rx.len-=2;
modbus_serial_new=TRUE;
} else {
modbus_serial_new=FALSE;
}
modbus_serial_crc.d=0xFFFF;
modbus_serial_state=MODBUS_GETADDY;
modbus_enable_timeout(FALSE);
}
|
|
|
|
|