Dear All, Happy new 2013
I want to acquire experience with the modbus protocol,
also by simulation, in our office of a system of virtual installation
(i.e. SCADA management of a wind farm) through free or evaluation SW,
and integrate in this system, a CR1000 datalogger.
Does anyone have suggestions?
Thanks
Regards
Smile
the cr1000 supports modbus rtu, ascii(os 26), and modbus tcp.
I have used the following software during my desktop testing.
http://www.modbustools.com/modbus_poll.asp
http://www.chipkin.com/problem-solving/modbus-rtu-solutions/modbus-rtu-software-and-tools/
Dear Sam
I try it now, too. many thanks
Smile
Smile,
Here is a decent reference guide. It has more information than what you need. However, it presents the transmission modes and framing of the packets which should help you learn the protocol.
http://modbus.org/docs/PI_MBUS_300.pdf
Will
Dear all,
for have date and time of the events of maximum, minimum, and other, I used an array of string to 50 characters in the array of locations modbus, if the normal locations will use two registers 40000, with these strings how many records will be used and how?
I suspect that the strings can be not used.
If so, how do I get variables with at least the hour and minute of the various events, since the datatable is every 10 minutes ( with getrecord and splitstring I copy last 10 min datatable in the array for modbus)
In the help list these possibilities for VarDataType.
0-Default; 32-bit float or Long with no reversal of the byte order (ABCD)
1-If the ModBus variable array is defined as a Long, variables are treated as 16-bit signed integers
2-If the ModBus variable array is defined as a 32-bit float or a Long, the standard ordering of the 2 byte registers are reversed (CDAB)
Thanks
Regards
Smile
I think there are a variety of ways to do this.
------------------------------
Convey the minimum time as seconds since 1990. If you used the following, your Modbus master device or software (capabilities willing) could query Modbus holding registers 1-6 (three 4-byte values) and then interpret registers 3 & 4 as a single 4-byte long representing seconds since 1990.
Public PTemp, batt_volt
Public MBReg(3) As Float
Public MBCoil(2) As Boolean
DataTable (test,1,1000)
DataInterval (0,30,Sec,10)
Minimum (1,batt_volt,FP2,0,True)
Sample (1,PTemp,FP2)
EndTable
BeginProg
ModBusSlave (502,115200,1,MBReg(),MBCoil(),2)
Scan (1,Sec,0,0)
PanelTemp (PTemp,250)
Battery (batt_volt)
CallTable test
If Test.Output Then
MBReg(1) = Test.batt_volt_min(1,1)
MoveBytes (MBReg(2),0,Test.batt_volt_TMn(1,1),0,4)
MBReg(3) = Test.PTemp(1,1)
EndIf
NextScan
EndProg
------------------------------
2) Like (1) above, convey the minimum time as seconds since 1990 but also force all of your other variable to long (4 byte signed integers). For example,
Public PTemp, batt_volt
Public MBReg(3) As Long
Public MBCoil(2) As Boolean
DataTable (test,1,1000)
DataInterval (0,30,Sec,10)
'mult by 10 to preserve 1st digit after decimal
Minimum (1,batt_volt*10,Long,0,True)
Sample (1,PTemp*10,Long)
EndTable
BeginProg
ModBusSlave (502,115200,1,MBReg(),MBCoil(),2)
Scan (1,Sec,0,0)
PanelTemp (PTemp,250)
Battery (batt_volt)
CallTable test
If Test.Output Then
GetRecord (MBReg,test,1)
EndIf
NextScan
EndProg
------------------------------
3) Yes, you can transfer strings via modbus. Remember a string is just a collection / array of bytes. And each register in modbus can contain 2 bytes. This isn't the most efficient way you could do this. And you would need to see if your modbus master can reassemble the registers into a string on the other end for you. You need to be careful about registry management and allocation. But here is a simplified example where I have allocated registers 1-2 for a floating point measurement, 3-20 for my string variable, and 21-22 for the next measurement.
Public StringMsg As String = "I am a string"
Public MBReg(11) As Float
Public MBCoil(2) As Boolean
BeginProg
ModBusSlave (502,115200,1,MBReg(),MBCoil(),2)
Scan (1,Sec,0,0)
' might be a battery voltage
MBReg(1) = 13.1
'initialize string registers to 0's
Move (MBReg(2),9,0,1)
'transfer string into registers
MoveBytes (MBReg(2),0,StringMsg,0,Len(StringMsg))
'maybe another measurement
MBReg(11) = 100
NextScan
EndProg
And there have to be a half dozen other ways to get done what you want with a little imagination.
Many thanks Sam,
your message has stimulated my fantasy.
In order to not complicate the situation because of my little experience, I thought to transform the time of the events in HHMM,SS. Since, however, having outputs 10 minutes with 1 sec scan, the year, month and day are repeated continuously. So to provide the tag list to the scada system, I must to associate in pairs the register 40000 for all locations numeric floating-point I declared the array of modbuslave.
modln(1)= 40001&40002 = battVolt
modln(2)=40003&40004 = airtemp
From other tread
"Therefore, the first register corresponding to any array location X is holding register 40000+2X-1. For example, to retrieve array value number 3, you would ask for two registers starting with 40005."
modln(x)= 40000+2x-1 = min airTemp Time (HHMM,S)
Correct?
Regards
Smile
The string "HHMM,SS" is 8 bytes long.
7 bytes for the items of interest and 1 for the terminating null character.
8 bytes requires 4 modbus registers.
Public myTime as string = "2400,00"
MoveBytes (MBReg(1),0,myTime,0,8)
puts this string into registers 1-4 (each register contains 2 bytes)
MoveBytes (MBReg(5),0,myTime,0,8)
puts the string into registers 11-14
Hi Sam
Sorry but the comma caused a misunderstanding, in fact it would be correct to write HHMM.SS, because I want to create for the time of the events normal floating-point locations like other measurements. So a time event loc is 513.45 means the 5AM 13 minutes and 45 sec or if is 2254.35 means 10PM 54 minutes and 35 seconds. So is always the rule 2 modbus registers for each location.
However, thanks to your last description I understand the relationship between bytes, strings and Modbus register.
Thanks again
Regards
Smile
That is the general rule.
Generally folks are dealing with the FLOAT or LONG data type.
And each of these occupy 4-bytes of memory.
Since the registers are only 2-bytes, the FLOAT or LONG data occupy 2 registers.
Hello,
I think I have find want I'm looking for (in part). Is this a modbus TCP or RTU ? The 502 could be the port, so it's TCP.
Can I use your program examples sam, for a CR200X, which communicate in RTU ?
But I'm afraid I just can't understand all your actions ...
Thank you,
bye.
Our products support both Modbus TCP/IP (default Port 502) and Modbus RTU. See below for Modbus master example program and Modbus slave program example, in both cases is Modbus RTU. We offer a system configuration app called ShortCut that can be used to configure our dataloggers for Modbus (https://www.campbellsci.com/scwin). For Modbus TCP/IP use 502 instead of RS-232 in program examples below.
CR300 Example:
ModbusMaster Example
The following is an example program using the ModbusMaster instruction to set up a datalogger to read the holding registers of a Modbus slave device.
This program was written for a CR1000, but other dataloggers can use similar code (voltage ranges, channel numbers, or other parameters may need to be changed to reflect the specifications of the datalogger).
'Declare Public Variables
Public PTemp, batt_volt,ModbusData(20),Result
'Define Data Tables
DataTable (Test,1,-1)
DataInterval (0,15,Sec,10)
Minimum (1,batt_volt,FP2,0,False)
Sample (1,PTemp,FP2)
Sample (1,ModbusData(),FP2)
EndTable
'Main Program
BeginProg
Scan (1,Sec,0,0)
PanelTemp (PTemp,60)
Battery (Batt_volt)
'Retrieve Modbus Data
ModbusMaster (Result,COMRS232,115200,3,3,ModbusData(),1,10,3,100)
'Enter other measurement instructions
'Call Output Tables
CallTable Test
NextScan
EndProg
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ModbusSlave Example
Public PTemp, batt_volt, ModResult,I
Public ModIn(80)
'
'Main Program
BeginProg
ModbusSlave (ComRS232,9600,1,ModIn(),0)
Scan (2,Sec,0,0)
PanelTemp (PTemp,60)
Battery (Batt_volt)
ModIn(1) = batt_volt
ModIn(2) = PTemp
ModIn(3) = ModResult
NextScan
EndProg
Hello,
thanks a lot for your answer. If the CR300 program very interess me (since few month we prefer this datalogger), it remains a problem : what about the CR200X ? Is this datalogger can be in modbus TCP or only RTU ?
I will try the CR300 program in few days (one of them come back of the field).
I have tried use this program on CR200X but with adaptation, and now I can see some value in register with a windows RTU software (first time, youhou)!
Now I'm trying to read the same thing with a pyton program (minimalmodbus). When I will successfully read a value and make a clean table, I will probably come again and ask some program improvement, because I'm not a specialist of CR Basic...
Thanks,
bye
Hello again,
so, good new, I can reach the CR200X with my python program. But there is a strange thing : I'm asking th reads from the register 1 to 4 (16 bit reading) and have a response but I don't understand the values. And when I'm trying to read registers 3000X or 4000X, I can't.
Have I miss something ?
bye.
Hello,
I have tried a lot of way, but CR200X denied request farther than register addresse 12. All request on 30001 or 40001 are denied ans the response is "illegal data address", like the CR200X don't recognize my register request. I'm pretty sure that's not a python program problem.
Have you an idea ?
Maybe there is missing somethine in the CR200X program ?
Thanks, bye.
Can you post the CR200X program?
of course, here it is :
'CR200/CR200X Series 'Declare Variables and Units Public BattV Public SEVolt Public Rain_mm Public Moddata(80) Public ModResult Units BattV=Volts Units SEVolt=mV Units Rain_mm=mm 'Define Data Tables DataTable(Table1,True,-1) DataInterval(0,1,Min) Sample(1,BattV) Sample(1,SEVolt) Totalize(1,Rain_mm,False) EndTable DataTable(Table2,True,-1) DataInterval(0,1,Min) Minimum(1,BattV,False,False) EndTable 'Main Program BeginProg ModBusSlave (2,9600,1,Moddata(),0,0,0) 'Main Scan Scan(10,Sec) 'Default CR200 Series Datalogger Battery Voltage measurement 'BattV' Battery(BattV) 'Generic Single-Ended Voltage measurement 'SEVolt' VoltSe(SEVolt,1,1,1,0) '52202/52203 Rain Gage (CSL) measurement 'Rain_mm' PulseCount(Rain_mm,P_SW,2,0,0.2,0) 'Call Data Tables and Store Data Moddata(1)=BattV Moddata(2)=SEVolt Moddata(3)=ModResult CallTable Table1 CallTable Table2 NextScan EndProg
I precize that no sensor is connected on for the moment.
Bye.
if you're asking the slave for 16-bit, then you need to configure the CR200X for 16-bit. Edit the last parameter in your ModbusSlave instruction for the right data type:
ModbusSlave
ModbusOption ModbusOption is an optional parameter that is used to specify the data type of the Modbus variables.
Code Description
0 Default; 32-bit float or Long, the standard ordering of the 2 byte registers are reversed (CDAB)
1 If the Modbus variable array is defined as a Long, variables are treated as 16-bit signed integers
2 If the Modbus variable array is defined as a 32-bit float or a Long, with no reversal of the byte order (ABCD)
3 If the Modbus variable array is defined as a Long, variables are treated as 16-bit unsigned integers
10 Modbus ASCII, 4 bytes, CDAB
11 Modbus ASCII, 2 bytes, signed
12 Modbus ASCII, 4 bytes, ABCD
13 Modbus ASCII, 2 bytes, unsigned
Effectively, i'm asking a 16-bit response from the registers but where in the function can I set this parameter ?
ModbusSlave (COMPortMB,Baudrate,ModbusAddress,ModbusVariable,ModbusBooleanVar,ByteOrder,OffsetMB)
Because in CRBasic editor I can't see the "ModbusOption" parameter type (only for the CR300).
But I have test the 1 option at the end of the function (write as "offsetMB"), just in case, it doen't work.
But thank you for your answer.
Sorry, I keep thinking of the CR300. For the CR200 you must have special OS:
CR200 MODBUS OS v.10 (1.97 MB) 09-08-2010
Special operating system that supports ModBus communication and SDI-12 sensors . Also included is the Compiler and CRBasic Editor support files for the CR2xx dataloggers.
Use of this file will update the datalogger compiler and CRBasic Editor support files.
Note: Not to be used with the CR200X series.
Includes: MODBUS Instructions, SDI12Sensor, WindVector
please download from the Downloads section on this page:
https://www.campbellsci.com/cr200
here is more information about modbusslave in CR200X:
ModBusSlaveModBusSlave
Example
For the CR200, this instruction is supported only in a special operating system version M. You must have this special operating system loaded in your datalogger, and the datalogger program must be compiled with an alternate precompiler that supports this instruction.
No special operating system is needed for the CR200X.
The ModBusSlave instruction sets up a datalogger as a ModBus slave device.
Syntax
ModBusSlave ( ComPort, BaudRate, ModBusAddr, ModBusVariable, BooleanVariable, ByteOrder [optional], Offset [optional] )
Remarks
This instruction sets up a ModBus slave device to respond to the data request of a ModBus master. Supported ModBus functions are 01, 02, 03, 04, 05, 15, and 16. See the ModBusMaster help for details on these functions.
This instruction may be placed outside the main program scan. It only needs to be executed once.
ComPort The ComPort parameter specifies the communication port and mode that will be used for this instruction.
Alphanumeric Code Description
0 RS232 ModBus/PakBus
1 RF Port
2 RS232 Port
3 COM1, Datalogger's control ports C1 (TX) and C2 (RX)
Option 0, ModBus/PakBus, uses the PakBus Datagram protocol with an application ID of 502 that will allow ModBus packets to be routed via PakBus on the RS232 port.
BaudRate The BaudRate parameter is used to set the rate, in bps, for communication. The options are 1200 and 9600. Selecting one of these options fixes the baud rate at that rate of communication. This parameter is ignored if RF Port ComPort option is selected.
The datalogger uses 8 data bits and no parity for ModBus communication.
ModBusAddr The ModBusAddr parameter is used to assign an address to the ModBusSlave. Valid ranges are 1 - 127 for ModBus, or 1 - 247 for ModBus/PakBus.
ModBusVariable The ModBusVariable parameter is used to specify the variable array that is used as the source of data for the ModBusMaster, or the variable array that is used as the destination for data received from the ModBusMaster. The maximum size allowed for this variable is 15 elements. The datalogger does not differentiate between holding and input registers. The only difference is the address offset. The specified array will be used for requests of input (address offset of 30000) or holding (address offset of 40000) registers.
Floating point variables take two ModBus registers. The ModBus input registers are offset by 30000; ModBus holding registers are offset by 40000. Therefore, the first register corresponding to any array location X is holding register 40000+2X-1. For example, to retrieve array value number 3, you would ask for two registers starting with 40005.
BooleanVariable The BooleanVariable parameter is a variable or variable array that is used to hold the result if the master sends one of the discrete on/off commands to the slave (i.e., 01 Read Coil/Port Status, 02 Read Input Status, 05 Force Single Coil/Port, 15 Force Multiple Coils/Ports). Each element in the variable array maps to one Boolean value. The array size determines the number of Boolean values; the maximum size of the array is 16 elements.
If a 0 is entered for this parameter, then the discrete commands are mapped to control ports C1 and C2 instead. Note that if 0 is entered for this parameter, there will be a conflict if ComPort is configured for option 3, COM 1.
ByteOrder ByteOrder is an optional parameter that indicates the byte order of the floating point value. If this parameter is not used or is set to 0, no inverse on float values is used. Any value greater than 0 indicates that inverse order for float values will be used.
Offset Offset is an optional parameter that specifies the offset for the starting register.
Notes:
The datalogger communicates in RTU mode (not ASCII mode) to other ModBus devices. The communications port, baud rate, data bits, stop bits, and parity are set in the ModBus driver for PC-based software or on the PLC.
A datalogger acting as a ModBus slave returns a ModBus exception code 01 (Illegal Function) if a query is invalid, and an exception code of 02 (Illegal data address) if data values beyond the size of an array are requested.
Some ModBus devices (e.g., some RTUs made by Bailey Controls that use less common CPUs) require reverse word order (MSW/LSW versus LSW/MSW) in the floating point format. Some software packages have a setting to work with this original ModBus format. For example, the “Modicon 32-bit floating point order (0123 vs. 3201)” advanced option must be enabled for the ModBus object in National Instruments’ Lookout.
Hello Matt,
thank for your answer. So I have a CR200X, no special OS needed, as you said.
Thank you to have copy the CRBasic function help but, as you can see, there is not the parameter type "ModbusOption" in ModbusSlave for CR200X.
So I remains stuck, I don't find a solution to set the datalogger to 16bit communication for the moment.
But maybe it's another problem. What do you think about this ?
Bye
The CR200X only supports the equilavent of ModbusOption set to 0.