I would like to “emulate” a Modbus RTU slave. We know the FC used by the master and the address indicated by the master.
The idea is to use a PLC with serial interface and write a code using the library “DRV_mbus” on the slave side.
I am a little it in doubt about how to write in the code the registry adress of the variable in my slave software.
Example:
3rd party Modbus RTU master use FC3 for read data from slave device with Module ID 1 on adress “0000h”.
On the B&R Modbus RTU slave, how can I associate the data to the adress “0000h”?
I read on AS help the “MBSOpen” description but I didn’t understand how configure “pCoilStat”, “pInputStat”, “pInputReg”, pHoldingReg".
I only found out that if I set such values to 0, based on the FC used by the master, I have to declare global array MB0[x], MB1[x], MB3[x] and MB4[x].
As you already found in the Help to simulate Modbus variables on our System you have to define 4 different arrays with exactly the same name MB0,MB1,MB3,MB4 for those 4 tables.
Thanks Valerio for your answer but it doesn’t works at all.
The 3rd party Modbus RTU master uses RS485. I connect the RS485 interface to an external 3rd party converter which converts the signal to an RS232 and it goes to an
X20CP3684.
I thought that the converter could be the problem but I also tried to simulate the Modbus slave with a software installed on my PC and it works (so the converter is not the
problem).
Master use FC4 to read 2 input register at address 30005 on slave (so adress 30005 and 30006).
Master make requests to the slave every 200 ms more or less.
If I understand well if I leave “0” at MBSOpen_0.pInputReg I can define global MB3 array and MB3[0] should correspond to Input register at address 30001 and so on, right?
This is the code and variable declaration:
PROGRAM _INIT
(* init program *)
Slave.S1 := 0;
//MB4[0] := 0;
//MB4[1] := 0;
//MB4[2] := 0;
MB3[4] := -10000;
MB3[5] := -1;
Slave.MBSOpen_0.enable := TRUE;
Slave.MBSOpen_0.pDevice := ADR('IF1'); (* Device description string *)
Slave.MBSOpen_0.pMode := ADR('/PHY=RS232 /PA=N /DB=8 /SB=1 /BD=9600'); (* Mode description string *)
Slave.MBSOpen_0.pCoilStat := 0; (* Coil Status (Modbus simulation variable) *)
Slave.MBSOpen_0.pInputStat := 0; (* Input Status (Modbus simulation variable) *)
Slave.MBSOpen_0.pInputReg := 0; (* Input Register (Modbus simulation variable) *)
Slave.MBSOpen_0.pHoldingReg := 0; (* Holding Register (Modbus simulation variable) *)
Slave.MBSOpen_0.own_ID := 1; (* Own node number *)
Slave.MBSOpen_0.timeout := 5000; (* Timeout in milliseconds (the value must be a multiple of 10 and >250ms) *)
Slave.MBSOpen_0();
Slave.MBSlave_0.enable := TRUE;
Slave.MBSlave_0.ident := Slave.MBSOpen_0.ident;
END_PROGRAM
PROGRAM _CYCLIC
(* cyclic program *)
Slave.MBSlave_0();
(*When the command S1 is TRUE, then the driver environment is closed*)
IF (Slave.S1 = TRUE) THEN
Slave.MBSClose_0.enable := TRUE;
Slave.MBSClose_0.ident := Slave.MBSOpen_0.ident;
Slave.MBSClose_0();
END_IF
END_PROGRAM
>If I understand well if I leave “0” at MBSOpen_0.pInputReg I can define global MB3 array and MB3[0] should correspond to Input register at address 30001 and so on, right?
At least so far we see the Modbus Master has sent message in correct format
Back to your original settings, do you have serial sniffer to connect to your pc? it will be nice to grab again rx/tx messages displayed for example with RealTerm
Sometimes we have an offset on the registers so first on my test I read multi registers (20 for example) starting from address 0 just to find some values and understand in a second step the offset.
Ciao
Valerio
At least so far we see the Modbus Master has sent message in correct way
Yes, that is why in my opinion there is something wrong on slave side with PLC B&R (with slave on my PC there are no problems).
Some questions:
Requests from the master are every 200 ms. MBSlave() answers only on master requests or answers cyclically (with the task class in which the task of MBSlave() is inserted)?
In case MBSlave() answers only on master’s requests, if requests are every 200ms which is the right task class for the MBSlave() FB?
if I’m you I will just focus on grabbing one read request ( Function Code=3: Read Holding Registers, so I will play with MB4[]) and the answer:
From Master side (in the example below I’m reading 24 registers in one request, and 0 offset), the code below is running every 50 ms (I don’t think the time is too important for the moment):
Thanks Valerio but I have just one B&R PLC, so I have to decide to act as master or slave.
Now I found out the way to analyse Modbus traffic between master (3rd party device) and slave (B&R PLC).
The very strange thing is that when I write NEGATIVE values on the slave the master seems to be more “stable” (I write 2 values, -1000 and -1) :
On the other end when I write on the slave POSITIVE values the master read values that are completely out (I write -10000 and 0 and especially for the register 0 the master
read very wrong values and fluctuated a lot) :
I find out that when I modified parameter of MBSOpen() /RIT /TIT the situation change a little bit.
What’s the meaning of such parameters? Could be the road to success or not? Frankly speaking I am a little bit in doubt..
======================================
Around 20 years ago I did something similar on what you are doing, in my case I used 2 X20 CPU and I installed the 2 examples you see in the help Examples in ANSI C.
In that moment I didn’t have a serial sniffer in the office, I configured in the mode RS232 and worked with no issue. We use DRV_mbus library in many projects so I don’t think there
is an issue on that.
just as a side note without digging deeper into the whole topic from my side (I haven’t the chance right now to do so) :
please be aware, that the sign of an integer (negative or positive) is defined by the highest bit of the 16bit value.
So if negative values seem to be “more stable” then positive ones, I think that could be an indicator for a physical / timing problem between sender and receiver, because it would mean that the first bit is most often true, independent of the value. That the behavior changes when playing around with RIT / TIT also points into that direction.
So even if the converter is working with your PC, I don’t think we can rule it out with 100% as root cause.
If possible, I would try to use a RS485 interface on the PLC, and using the bus termination resistors specified for RS485, because even with very short cables I’ve seen misbehavior in past when termination of the bus wasn’t used as specified.
Thank you very much @alexander.hefner for your answer. I also think it is a “field” problem (terminating resistor over all that I can’t put in an RS23 line).
I don’t understand when you say this:
So even if the converter is working with your PC, I don’t think we can rule it out with 100% as root cause.
Why?
For sure I have to try with a native RS485 interface.
You’re right, I just forgot to explain why I mentioned that.
As you’re using a converter, both of the interfaces RS485 and RS232 could possibly cause a physical issue.
As it works on your PC, the converter seems to be okay for this setup. But still, there could be some incompatibilities / interferences between the converter and the PLC serial chipsets.
I’ve worked a lot with serial interfaces very long ago in past, and here and there I’ve seen strange behaviors in some combinations, even if it worked in others. Sometimes, the reason was a different timing and buffering behavior of the chipsets/drivers, sometimes it was based on voltage signals nearby the specified minimum or a floating ground between the 2 serial voltage signals, and also a long time ago it got even worse when the chipset manufacturers started using 3.3 TTL based chips instead of the 5V chips that were used before, and when USB based RS converters were replacing the chipset integrated RS interfaces on PC side.
All in all, I just wanted to mention that such rare, but real exisiting effects also could cause strange behavior.
Therefore, I always try to eliminate as much signal converting as possible … but as I said, this information is just based on my learnings a long time ago