Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

modbus communication via python CR200 & CR1000


Benjamin.vial Feb 14, 2017 07:15 AM

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


JDavis Feb 17, 2017 11:28 PM

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


Benjamin.vial Feb 20, 2017 10:08 AM

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.


Benjamin.vial Feb 20, 2017 10:08 AM

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.


Benjamin.vial Mar 1, 2017 02:27 PM

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


Benjamin.vial Mar 1, 2017 02:39 PM

Just to be sure, can you please explain to me the difference between "datavariable" and "booleanvariable" ?

Thank you,

bye


Benjamin.vial Mar 13, 2017 07:31 AM

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.


Karl Mar 17, 2017 06:15 PM

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


Benjamin.vial Mar 22, 2017 07:59 AM

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.


Benjamin.vial Mar 28, 2017 07:12 AM

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.


Karl Mar 28, 2017 11:05 PM

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,


Benjamin.vial Apr 3, 2017 06:36 AM

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


JDavis Apr 3, 2017 02:46 PM

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.

Log in or register to post/reply in the forum.