Hi,
I got some issues to get data from multiple sensors using RS485 Modbus RTU protocols. Below is the wiring and program using CR1000X. I can get sucsessful reading from the three RS-232 sensors, but never got reading from the three RS-485 sensors (these sensors have been set with address # 1, 2, 3). I just want to double check that I correctly used the ModbusMaster function. I followed the register # from these sensors (OXYBase-RS485) manual and the PreSens Modbus instructions, but just can't get the reading. Not sure what happended.
Thanks for the help!!!
'CR1000X connect with one SDM-SIO4A I/O expansion module
'----------------------------------------------------------------------------------
' Connections explain:
' SDM-SIO4A to CR1000X: C1 to C1,C2 to C2,C3 to C3, +12V to +12 V, G to G
' OXYBase-RS232 DO #1 sensor to SDM-SIO4A: brown (+5V to CR1000X +5V),
'green (TxD) to Port 1 Tx, yellow (RxD) to Port 1 Rx, white (G) to Port 1 G
' OXYBase-RS232 DO #2 sensor to SDM-SIO4A: brown (+5V to CR1000X +5V),
'green (TxD) to Port 2 Tx, yellow (RxD) to Port 2 Rx, white (G) to Port 2 G
' OXYBase-RS232 DO #3 sensor to SDM-SIO4A: brown (+5V to CR1000X +5V),
'green (TxD) to Port 3 Tx, yellow (RxD) to Port 3 Rx, white (G) to Port 3 G
' OXYBase-RS485 all three DO sensors to SDM-SIO4A: brown (7-30 VDC to CR1000X +12V, not 5V!),
'green (RS485A) to Port 4 TD+, yellow (RS485B) to Port 4 TD-, white (G) to Port 4 G
' A Decagon VP3 Temperature and Humidity Sensor using SDI-12 protocol:
' Red (data) to C7, black (power) to 12V, bare (ground) to G
' A PAR sensor that use an analog port
'----------------------------------------------------------------------------------
'Declare Variables and Units
Public PTemp, batt_volt 'datalogger temp and battery voltage
' Three OXYBase RS232 and three RS485
Public SendText(6) As String * 256
Public ReceiveText(6) As String * 128
Public SerialError(3) As Long
Public SplitText(6) As String * 16
Public OXYBaseAmp(3) As Long
Public OXYBasePhase(3) As Float
Public OXYBaseTemp(3) As Float
Public OXYBaseOxygen(3) As Float
Public OXYBaseTemp2(3) As Float
Public OXYBaseOxygen2(3) As Float
Public OXYSet2(8)
Public OXYSet3(3)
Public OXYBaseError(3) As Long
Public RawString(6) As String *128
Public MBResult(3) As String * 128
Alias OXYBaseTemp(1)=T1
Alias OXYBaseTemp(2)=T2
Alias OXYBaseTemp(3)=T3
Alias OXYBaseTemp2(1)=T4
Alias OXYBaseTemp2(2)=T5
Alias OXYBaseTemp2(3)=T6
Alias OXYBaseOxygen(1)=DO1
Alias OXYBaseOxygen(2)=DO2
Alias OXYBaseOxygen(3)=DO3
Alias OXYBaseOxygen2(1)=DO4
Alias OXYBaseOxygen2(2)=DO5
Alias OXYBaseOxygen2(3)=DO6
Public PPFD
Public SDI12(3)
Alias SDI12(3)=AirRH
Alias SDI12(2)=AirTemp
Units batt_volt=Volts
Units PTemp,AirTemp=Deg C
Units PPFD=mol/m2/s
Units AirRH=%
'Define Data Tables
DataTable (DOLoggerVandT,True,-1)
DataInterval(0,10,Min,10)
Average(1,batt_volt,FP2,False)
Minimum(1,batt_volt,FP2,False,False)
Maximum(1,batt_volt,FP2,False,False)
Average(1,PTemp,FP2,False)
Minimum(1,PTemp,FP2,False,False)
Maximum(1,PTemp,FP2,False,False)
EndTable
DataTable(DOThermoc,True,-1)
DataInterval(0,10,Min,10)
Sample(3,OXYBaseTemp(),FP2,False)
Sample(3,OXYBaseOxygen(),FP2,False)
Sample(3,OXYBaseTemp2(),IEEE4,False)
Sample(3,OXYBaseOxygen2(),IEEE4,False)
Sample(1,PPFD,FP2,False)
Sample(1,AirRH,FP2,False)
Sample(1,AirTemp,FP2,False)
EndTable
Sub OXYBaseSerialSetup
'subroutine to initialize the RS232 interface
'Const SensorPort = 32 'Declare the serial port the sensor is set to
'The sensors address switch should be set to position 0
Call OXYBaseSend
' RS232
SerialOpen (32,19200,0,20,1000) 'SensorPort = 32 (SDM-SIO4A address = 0)
'open the serial port to the sensor
SendText(1)="mode0001"+CHR(13)
SerialOpen (33,19200,0,20,1000) ' Sensorport = 33 (SDM-SIO4A address = 1)
SendText(2)="mode0001"+CHR(13)
SerialOpen (34,19200,0,20,1000) ' Sensorport = 34 (SDM-SIO4A address = 2)
SendText(3)="mode0001"+CHR(13)
Call OXYBaseSend
EndSub
Sub OXYBaseData
'subroutine to receive data
SendText(1)="data"+CHR(13)
ReceiveText(1)=""
SendText(2)="data"+CHR(13)
ReceiveText(2)=""
SendText(3)="data"+CHR(13)
ReceiveText(3)=""
Call OXYBaseSend
EndSub
Sub OXYBaseSend
'subroutine to send texts
SerialError(1)=SerialOut (32,SendText(1),"",1,100)
SerialError(2)=SerialOut (33,SendText(2),"",1,100)
SerialError(3)=SerialOut (34,SendText(3),"",1,100)
EndSub
'Main Program
BeginProg
'Main Scan
Call OXYBaseSerialSetup
SerialOpen (35,19200,7,20,512) ' Sensorport = 35 (SDM-SIO4A address = 3)
Scan (10,Sec,0,0) 'exemplary 10 sec as interval
'Default CR1000X Datalogger Battery Voltage measurement 'BattV'
Battery(batt_volt)
'Default CR1000X Datalogger Wiring Panel Temperature measurement 'PTemp_C'
PanelTemp(PTemp,60)
'Generic Differential Voltage measurements 'PPFD'
VoltDiff(PPFD,1,mV200,8,True,500,60,100,0)
'Generic SDI-12 Sensor measurements 'RH', and 'Temp'
SDI12Recorder(SDI12(),C7,"0","M!",1,0,-1)
AirRH = AirRH * 100
Call OXYBaseData 'sending "data" to the OXYBase results in sending of the data as an ASCII-String
SerialIn(RawString(1),32, 200,13,256) 'reading in the string
SplitStr(SplitText(),RawString(1), CHR(59),6,0) 'splitting the string into the value parts
OXYBaseAmp(1)=Mid(SplitText(2),1,7)
OXYBasePhase(1)=Mid(SplitText(3),1,7)
OXYBaseTemp(1)=Mid(SplitText(4),1,7)
OXYBaseOxygen(1)=Mid(SplitText(5),1,8)
OXYBaseError(1)=Mid(SplitText(6),1,8)
SerialIn(RawString(2),33, 200,13,256) 'reading in the string
SplitStr(SplitText(),RawString(2), CHR(59),6,0) 'splitting the string into the value parts
OXYBaseAmp(2)=Mid(SplitText(2),1,7)
OXYBasePhase(2)=Mid(SplitText(3),1,7)
OXYBaseTemp(2)=Mid(SplitText(4),1,7)
OXYBaseOxygen(2)=Mid(SplitText(5),1,8)
OXYBaseError(2)=Mid(SplitText(6),1,8)
SerialIn(RawString(3),34, 200,13,256) 'reading in the string
SplitStr(SplitText(),RawString(3), CHR(59),6,0) 'splitting the string into the value parts
OXYBaseAmp(3)=Mid(SplitText(2),1,7)
OXYBasePhase(3)=Mid(SplitText(3),1,7)
OXYBaseTemp(3)=Mid(SplitText(4),1,7)
OXYBaseOxygen(3)=Mid(SplitText(5),1,8)
OXYBaseError(3)=Mid(SplitText(6),1,8)
ModbusMaster(MBResult(1), 35, 19200,1,3, OXYSet2(),1031, 8, 5, 100,2)
' Check the connection by reading the firmware version with register 1031 and size 8 by using
the Modbus command ‘Read Holding Register’ (= 0x03)
ModbusMaster(MBResult(1), 35, 19200,1,16, OXYSet3(),3499, 2, 5, 100,2)
' To set an interval, use register 3499 (size: 2 registers), data type is ‘int32’, Modbus command
is ‘Write Multiple Registers’ (= 0x10).
ModbusMaster(MBResult(1), 35, 19200,1,3, OXYBaseTemp2(), 4903, 2, 5, 100,0)
' Measure Tem
ModbusMaster(MBResult(1), 35, 19200,1,3, OXYBaseOxygen2(),2091, 2, 5, 100,2)
' Measure DO
ModbusMaster(MBResult(2), 35, 19200,2,3, OXYBaseTemp2(), 4903, 2, 5, 100,2)
ModbusMaster(MBResult(2), 35, 19200,2,3, OXYBaseOxygen2(), 4905, 2, 5, 100,2)
ModbusMaster(MBResult(3), 35, 19200,3,3, OXYBaseTemp2(), 4903, 2, 5, 100,10)
ModbusMaster(MBResult(3), 35, 19200,3,3, OXYBaseOxygen2(), 4905, 2, 5, 100,12)
'recalculating data
OXYBasePhase(1)=OXYBasePhase(1)/100
OXYBaseTemp(1)=OXYBaseTemp(1)/100
OXYBaseOxygen(1)=OXYBaseOxygen(1)/10000
OXYBasePhase(2)=OXYBasePhase(2)/100
OXYBaseTemp(2)=OXYBaseTemp(2)/100
OXYBaseOxygen(2)=OXYBaseOxygen(2)/10000
OXYBasePhase(3)=OXYBasePhase(3)/100
OXYBaseTemp(3)=OXYBaseTemp(3)/100
OXYBaseOxygen(3)=OXYBaseOxygen(3)/10000
'storing the obtained values in the data table
CallTable DOLoggerVandT
CallTable DOThermoc
NextScan
EndProg
Look at the tables in the SDM-SIO4A to select the correct Format value for SerialOpen. Also double check the wiring.
A good thing to try with RS485 devices is swapping the A and B wires. Some manufacturers label them opposite. A termination resistor may also be needed, depending on the cable length.