40m QIL Cryo_Lab CTN SUS_Lab TCS_Lab OMC_Lab CRIME_Lab FEA ENG_Labs OptContFac Mariner WBEEShop
  40m Log  Not logged in ELOG logo
Message ID: 16323     Entry time: Mon Sep 13 17:05:04 2021
Author: Tega 
Type: Summary 
Category: PEM 
Subject: Infrasensing temperature sensor modbus configuration 

Anchal mentioned it would be good to put more details about how I arrived at the values needed to configure the modbus drive for the temperature sensor, since this information is not in the manual and is hard to find on the internet, so here is a breakdown.

So the generic format is:

drvAsynIPPortConfigure("<TCP_PORT_NAME>","<UNIT_IP_ADDRESS>:502",0,0,1)
modbusInterposeConfig("<TCP_PORT_NAME>",0,5000,0)
drvModbusAsynConfigure("<PORT_NAME>","<TCP_PORT_NAME>",<slaveAddress>,<modbusFunction>,<modbusStartAddress>,<modbusLength>,<dataType>,<pollMsec>,<plcType>)

which in our case become:

drvAsynIPPortConfigure("c1pemxendtemp","192.168.113.240:502",0,0,1)
modbusInterposeConfig("c1pemxendtemp",0,5000,0)
drvModbusAsynConfigure("C1PEMXENDTEMP","c1pemxendtemp",0,4,199,2,0,1000,"ServerCheck")

As can be seen, the parameters of the first two functions "drvAsynIPPortConfigure" and "modbusInterposeConfig" are straight forward, so we restrict our discussion to the case of third function "drvModbusAsynConfigure". Well, after hours of trolling the internet, I was able to piece together a coherent picture of what needs doing and I have summarised them in the table below.

 

drvModbusAsynConfigure

Once the asyn IP or serial port driver has been created, and the modbusInterpose driver has been configured, a modbus port driver is created with the following command:

drvModbusAsynConfigure(portName,                # used by channel definitions in .db file to reference this unit)
                       tcpPortName,             # reference to portName created with drvAsynIPPortConfigure command
                       slaveAddress,            # 
                       modbusFunction,          # 
                       modbusStartAddress,      # 
                       modbusLength,            # length in dataType units
                       dataType,                # 
                       pollMsec,                # how frequently to request a value in [ms]
                       plcType);                #

drvModbusAsynConfigure command
Parameter Data type Description
portName string Name of the modbus port to be created.
 
tcpPortName string Name of the asyn IP or serial port previously created.

tcpPortName = { 192.168.113.240:502192.168.113.241:502192.168.113.242:502 }
 
slaveAddress int The address of the Modbus slave. This must match the configuration of the Modbus slave (PLC) for RTU and ASCII. For TCP the slave address is used for the "unit identifier", the last field in the MBAP header. The "unit identifier" is ignored by most PLCs, but may be required by some.

ServersCheck API ignores this value, as confirmed with pymodbus query, so set to default value: 
slaveAddress = 0
 
modbusFunction int

modbus supports the following 8 Modbus function codes:

Modbus Function Codes
Access Function description Function code
Bit access Read Coils 1
Bit access Read Discrete Inputs 2
Bit access Write Single Coil 5
Bit access Write Multiple Coils 15
16-bit word access Read Input Registers 4
16-bit word access Read Holding Registers 3
16-bit word access Write Single Register 6
16-bit word access Write Multiple Registers 16
modbusStartAddress int Start address for the Modbus data segment to be accessed.
(0-65535 decimal, 0-0177777 octal).

Modbus addresses are specified by a 16-bit integer address. The location of inputs and outputs within the 16-bit address space is not defined by the Modbus protocol, it is vendor-specific. Note that 16-bit Modbus addresses are commonly specified with an offset of 400001 (or 300001). This offset is not used by the modbus driver, it uses only the 16-bit address, not the offset.

For ServersCheck, the offset is "30001", so that

modbusStartAddress = 30200 - 30001 = 199

modbusLength int The length of the Modbus data segment to be accessed.
This is specified in bits for Modbus functions 1, 2, 5 and 15.
It is specified in 16-bit words for Modbus functions 3, 4, 6 and 16.
Length limit is 2000 for functions 1 and 2, 1968 for functions 5 and 15,
125 for functions 3 and 4, and 123 for functions 6 and 16.

ServersCheck uses two's complement 32-bits word (with big-endian byte order & little-endian word order) format to store floating-point data, as confirmed with pymodbus query, so that:

modbusLength = 2
 
modbusDataType int The modbusDataType is used to tell the driver the format of the Modbus data. The driver uses this information to convert the number between EPICS and Modbus. Data is transferred to and from EPICS as epicsUInt32, epicsInt32, and epicsFloat64 numbers.

Modbus data type:
0 = binary, twos-complement format
1 = binary, sign and magnitude format
2 = BCD, unsigned
3 = BCD, signed

Some Modbus devices (including ServersCheck) use floating point numbers, typically by storing a 32-bit float in two consecutive 16-bit registers. This is not supported by the Modbus specification, which only supports 16-bit registers and single-bit data. The modbus driver does not directly support reading such values, because the word order and floating point format is not specified.

Note that if it is desired to transmit BCD numbers untranslated to EPICS over the asynInt32 interface, then data type 0 should be used, because no translation is done in this case. 

For ServersCheck, we wish to transmit the untranslated data, so:

modbusDataType = 0
 
pollMsec int Polling delay time in msec for the polling thread for read functions.
For write functions, a non-zero value means that the Modbus data should
be read once when the port driver is first created.

ServersCheck recommends setting sensor polling interval between 1-5 seconds, so we can try:

pollMsec = 1000
 
plcType string Type of PLC (e.g. Koyo, Modicon, etc.).
This parameter is currently used only to print information in asynReport.
In the future it could be used to modify the driver behavior for a specific PLC.

plcType = "ServersCheck"
 

 

Useful links

https://nodus.ligo.caltech.edu:8081/40m/16214

https://nodus.ligo.caltech.edu:8081/40m/16269

https://nodus.ligo.caltech.edu:8081/40m/16270

https://nodus.ligo.caltech.edu:8081/40m/16274

 

http://manuals.serverscheck.com/InfraSensing_Sensors_Platform.pdf

http://manuals.serverscheck.com/InfraSensing_Modbus_manualv5.pdf

https://community.serverscheck.com/discussion/comment/7419#Comment_7419

 

https://wiki-40m.ligo.caltech.edu/CDS/SlowControls

https://www.slac.stanford.edu/grp/ssrl/spear/epics/site/modbus/modbusDoc.html#Creating_a_modbus_port_driver

 

https://github.com/riptideio/pymodbus

 

https://en.wikipedia.org/wiki/Modbus

https://deltamotion.com/support/webhelp/rmctools/Communications/Ethernet/Supported_Protocols/Ethernet_Modbus_TCP.htm

ELOG V3.1.3-