Hello,
I remember Campbell doesn't provide any support for this kind of developpement, but maybe somebody can explain to me where is my mistake. So I try to establish a connection between a CR200X and a linux PC by a python code that use modbus protocol. It seem to almost works but I need to know the register table from the datalogger.
Is there anybody already use this ?
Have a nice day,
bye
You need to create a custom register map in the datalogger.
I suggest reading this document to get started:
https://s.campbellsci.com/documents/us/technical-papers/dataloggers-as-modbus-slave-devices.pdf
Hello JDavis,
thank you for this document, very interesting ! So I have to try a lot of thing before come back write here.
But it's to bad, in ShortCut there is not a "modbus salve" sensor control in library for CR200X...
bye.
Hello JDavis,
thank you for this document, very interesting ! So I have to try a lot of thing before come back write here.
But it's to bad, in ShortCut there is not a "modbus salve" sensor control in library for CR200X...
bye.
Hello,
so actually, there no way with shortcut to programming a modbus slave function, only with CRBasic editor. I don't know how to program it in other way that the way you said to me before.
I have tried to use Public variable "As X" like FP2 or Long for see if there are differences, but CR200X seem not to be able to interpretate variable like this :
"Public SEVolt As Long"
Compiler said
"Too many parameters: As"
I begin to believe this is not possible to retrieve modbus values with a CR200X ...
Bye
Just to be sure, can you please explain to me the difference between "datavariable" and "booleanvariable" ?
Thank you,
bye
Hi,
I don't have try anymore for the moment but I come back to the news, maybe smeone can answer me about my problem.
It seems to be a coding problem, 16bit or not, so is there any way to setup a specific kind of value (as long, fp2, etc) in a CR200X program ? (see above)
And, for my comprehension, what is a boolean variable ?
Have a nice day,
bye.
Benjamin,
Below are example Modbus programs - let us know if this helps. You can copy and paste this in the datalogger editor. These are example programs from the CRBasic Help for the CR200X.
--------------------------------------------------------------------------------------
ModBusSlave Example
Following are two examples of the ModBusSlave instruction.
'Example 1, registers and coils defined as data array:
Public batt_volt, I, flag
Public MBReg(3) 'array of modbus inputs / registers
Public MBCoil(3) 'array of modbus coils
DataTable (Test,1,1000)
DataInterval (0,15,min)
Minimum (1,batt_volt,0,0)
EndTable
BeginProg
'configure logger as modbus RTU slave,
'listening on RS-232 at 9600/8/N/1
'with slave address is 1
ModBusSlave (2,9600,1,MBReg,MBCoil,0,0)
Scan (5,Sec)
Battery (batt_volt) 'measure battery supply
I = I + 1 'increment counter
flag = NOT flag 'toggle flag
CallTable Test
'update register and coil arrays
MBReg(1) = batt_volt 'reg 1&2 = latest batt_volt measurement
MBReg(2) = Test.batt_volt_Min(1,1) 'reg 3&4 = minimum batt_volt from table
MBReg(3) = I 'reg 4&5 = counter
MBCoil(3) = flag 'coil 1
MBCoil(3) = flag 'coil 2
MBCoil(3) = flag 'coil 3
NextScan
EndProg
'Example 2,(Coils state maps to state of C1 & C2):
Public batt_volt, I
Public MBReg(3) 'array of modbus inputs / registers
DataTable (Test,1,1000)
DataInterval (0,15,min)
Minimum (1,batt_volt,0,0)
EndTable
BeginProg
'configure logger as modbus RTU slave,
'listening on RS-232 at 9600/8/N/1
'with slave address is 1
'modbus coils are mapped to state of C1 and C2
ModBusSlave (2,9600,1,MBReg,0,0,0)
Scan (5,Sec)
Battery (batt_volt) 'measure battery supply
I = I + 1 'increment counter
CallTable Test
'update register and coil arrays
'starting with register 1, offset of 0
MBReg(1) = batt_volt 'reg 1&2 = latest batt_volt measurement
MBReg(2) = Test.batt_volt_Min(1,1) 'reg 3&4 = minimum batt_volt from table
MBReg(3) = I 'reg 4&5 = counter
NextScan
EndProg
Hello Karl,
thank you very much for your program, this allowed me to confirm that the problem doesn't come from my CR200X, but from my program to retrieve modbus values.
I think I will resolve this soon.
Another question : if we consider that the retrieve via modbus is ok, is there a mean to do a better program :
1 - archived the value (of battery for example of your first program) in CR200X memory (one day values, one week, ...it depends of the size of values and the CR200X memory, I presume)
2 - retrieve that memory via modbus ?
I hope so ...
Thanks.
Hello,
finally it seem to be ok, I succeed to retrieve all modbus value ! Great day, people.
For the eventuallity that somebody what to try the same thing, little tips :
- You better have to call alll registers and put them into variables by register, rather calling two per two and put into variables (see after), don't why but it seem to disturb the datalogger.
- Look all the minimalmodbus site, a lot of "hidden" documentation... Or difficult to find, at least.
- Be careful, the CR200X seem to write floting value in a CDAB bytes order.
- Don't try to retrieve registers 3000X or 4000X and use function code of your register reading (03 read input reg or 04 read holding reg)
Examples of my program (it's a bash executable in python2.7) :
#!/usr/bin/env python import minimalmodbus as mmbus mmbus.CLOSE_PORT_AFTER_EACH_CALL = True import serial import time ins = mmbus.Instrument('/dev/ttyUSB0', 1, mode='rtu') ins.debug = True ins.serial.baudrate = 9600 ins.serial.bytesize = 8 ins.serial.parity = serial.PARITY_NONE ins.serial.stopbits = 2 ins.serial.timeout = 1 values = ins.read_registers(0, numberOfRegisters=6, functioncode=3) voltage = ((mmbus._numToTwoByteString(values[1])) + (mmbus._numToTwoByteString(values[0]))) minbat = ((mmbus._numToTwoByteString(values[3])) + (mmbus._numToTwoByteString(values[2]))) counter = ((mmbus._numToTwoByteString(values[5])) + (mmbus._numToTwoByteString(values[4]))) floatvalue1 = mmbus._bytestringToFloat(voltage) floatvalue2 = mmbus._bytestringToFloat(minbat) floatvalue3 = mmbus._bytestringToFloat(counter) print(ins.read_registers(0, numberOfRegisters=6, functioncode=3)) print(floatvalue1) print(floatvalue2) print(floatvalue3)
Thank you for all Campbell help, now I need to deploy this retrieve process on the field and try to implement a remote function.
Bye.
One thing to keep in mind when setting up Modbus communication between a datalogger and Modbus slave or master - is that the datalogger references values NOT registers. The datalogger takes care of either asking for, or sending the correct number of registers.
You can read or send the inverse byte order by entering a value other than 0 in the ByteOrder parameter.
Regards,
Hello Karl,
yes, thanks for that I have spend lot of time on this detail ... I didn't understand the manual on this point. But it's ok now.
But actually, no byte order parameter on CR200X (remember above in the topic !).
And do you have any idea to record several values on a modbus register ? Is there a way to program this in the datalogger ? You know, like if I want to retrieve a Table instead of a value when I call the the register ?
Thanks
Modbus has no provision for collecting tables. It is a limitation of the protocol. Everything you want to be able to collect must be put into the array used in ModbusSlave.
On the CR200X, the data format will always be what is option 0 on the other dataloggers. You may need to swap the bytes on the other end.