Hello,
I was wondering if anyone has any ideas,
This is my problem:
I am going to monitor a dam construction with the following Geokon sensors:
4700 VW temperature sensors
6850-1-1 Pendulum
4420-1-12.5 VW crackmeter
4422-1-VW crackmeter
And my problem is that my client wants me to deliver the data from the datalogger(cr-1000)in one of the following formats:
1. IEC 60870-5-104 over ethernet rj45 (prefered solution)
2. Analogue value 4-20 mA (alternative solution)
I need to have an IP-adress and a RTU-number for the loggersystem as well. This is for my clients SCADA system to work with my sensors.
Regards,
Oskar
Oskar,
I think the easiest thing is to use a protocol gateway/converter. Not only does the CR1000 understand CSI's PakBus, but also a variety of other including ModBus and DNP3.
I have never used this product. I found it with a simple internet search. But maybe something like these will help you solve this problem.
http://www.kalkitech.com/offerings/sync-field_protocol_io_gateways/
http://www.prosoft-technology.com/prosoft/products/stand_alone_gateways/serial/modbus_master_slave/modbus_master_slave_to_iec60870_5_101_slave_communication_module
So i should be able to use Kalkitechs SYNC 1000 together with the CR1000 to get the protocol to 60870-5-104? If that would work i think it would be great solution.
I've never used the products, so I'm not sure. However I do know that we have used similar products to handle ModBus ASCII, BACNet, etc.
I suggest calling the company and letting them help you pick the best product. They won't know anything about the CR1000 I'm sure, but they will understand that you have a device that can talk ModBus, DNP3, NTCIP, HTTP, etc.
So I think ive solved the problem and only one question remains.
How do I setup the CR1000 to talk over ModBus protocol instead PakBus?
AFOskar,
Check out CRBasic Help -> Search -> Modbus. You'll find instructions and examples for setting up the logger as a ModBus Master or ModBus Slave.
You might also find the following interesting:
Section 15.2, Page 380
http://www.campbellsci.com/documents/manuals/cr1000.pdf
Last page of
http://www.campbellsci.com/documents/technical-papers/bacnet.pdf
I have not been able to solve this problem yet so once again i will ask for help. This is the situation:
Four vibrating wire sensors connected to multiplexer one and ten vibrating wire sensors connected to multiplexer two. Both multiplexers connected to a AVW200 and a CR-1000 datalogger.
This is then connected via RS-232 to a protocol converter - Fastnet RTU, Radius http://www.radius.net/Products/fastnet-rtu.html
This is to convert the communicationprotocol from MODBUS into IEC 60870-5-104. Its then connected to a router and then connected to a SCADA server who polls for sensor values. Will this setup work? And if so how should I setup the CR-1000 using Modbus communication?
Best regards,
Is the CR1000 manual, section 15.2 not helpful? If not, what can we do to improve that section of the manual?
Here is an example of putting data into the modbus registers for polling by a ModBus Master.
Public PTemp, batt_volt
Public Result
Public AVWDest(7)
Public ModBus(9)
Dim Port(8) As Boolean
BeginProg
ModBusSlave (ComRS232,9600,1,ModBus(),Port(),2)
Scan (1,Min,0,0)
PanelTemp (PTemp,250)
Battery (batt_volt)
AVW200 (Result,COM1,-1,1,AVWDest(),1,1,1,450,6000,1,_60Hz,1,0)
ModBus(1) = PTemp
ModBus(2) = batt_volt
ModBus(3) = AVWDest(9)
ModBus(4) = AVWDest(9)
ModBus(5) = AVWDest(9)
ModBus(6) = AVWDest(9)
ModBus(7) = AVWDest(9)
ModBus(8) = AVWDest(9)
ModBus(9) = AVWDest(9)
NextScan
EndProg
Ok cant seem to get this to work. Here is my program for the datalogger. Can you figure out whats wrong? Im not very good at this so :(
'Define Switches
AngleDegrees
SequentialMode
'Define Public Variables
Public Logger_ID as Float
Public Year as Float
Public Julian_Day as Float
Public Time_HHMM as Float
Public Seconds as Float
Public Decimal_Day as Float
Public Elapsed_Hours as Float
Public Elapsed_Minutes as Float
Public Elapsed_Seconds as Float
Public Battery_Volts as Float
Public Panel_Temp as Float
Public Program_Mode as Float
Public Complete_Scans as Float
Public ReadFlag as Float
Public Flag(8) as Float
Public Reading_Loc as Float
Public GageType_Loc as Float
Public Channel as Float
Public MuxNumber as Float
Public Read_Time as Float
Public Int_Counter as Float
Public Int_Current as Float
Public Int_Iterations as Float
Public UserLoc(16) as Float
Public Pendulum_X as Float
Public Pendulum_Y as Float
Public Mux1CH(16) as Float
Public Mux1TempCH(16) as Float
Public Mux2CH(16) as Float
Public Mux2TempCH(16) as Float
'Define Other Variables
Dim ScratchLoc(32) as FLOAT
Dim MuxReadingLoc(48) as FLOAT
Dim sInBuf as STRING * 512
Dim sOutBuf as STRING * 512
Dim SDM1Loc(8) as FLOAT
Dim SDM2Loc(8) as FLOAT
Dim SDM3Loc(8) as FLOAT
Dim SDM4Loc(8) as FLOAT
Dim ScratchStr(10) as STRING * 20
'Define Constants
'Define Data Tables
DataTable(FSDATA,1,-1)
Sample(1,Logger_ID,IEEE4)
Sample(1,Year,IEEE4)
Sample(1,Julian_Day,IEEE4)
Sample(1,Time_HHMM,IEEE4)
Sample(1,Seconds,IEEE4)
Sample(1,Decimal_Day,IEEE4)
Sample(1,Elapsed_Hours,IEEE4)
Sample(1,Elapsed_Minutes,IEEE4)
Sample(1,Elapsed_Seconds,IEEE4)
Sample(1,Battery_Volts,IEEE4)
Sample(1,Panel_Temp,IEEE4)
Sample(1,Pendulum_X,IEEE4)
Sample(1,Pendulum_Y,IEEE4)
Sample(16,Mux1CH(),IEEE4)
Sample(16,Mux1TempCH(),IEEE4)
Sample(16,Mux2CH(),IEEE4)
Sample(16,Mux2TempCH(),IEEE4)
ENDTABLE
'Define Subroutines
Sub GetTime
RealTime(ScratchLoc())
Year = ScratchLoc(1)
Julian_Day = ScratchLoc(9)
Time_HHMM = (ScratchLoc(4)*100)+ScratchLoc(5)
Seconds = ScratchLoc(6)
Decimal_Day = ((((((ScratchLoc(6)/60) + ScratchLoc(5))/60) + ScratchLoc(4))/24) + ScratchLoc(9)-1)/365.25
EndSub
Sub ReadGages
Reading_Loc = 0
If GageType_Loc = 1 then
SDI12Recorder (sInBuf,7,0,"XVW1400,3500,2!",1.0,0)
SDI12Recorder (ScratchLoc(2),7,0,"M1!",1.0,0)
if ScratchLoc(2) > 0 then
if ScratchLoc(3) > 0.1 then
Reading_Loc = ScratchLoc(2)^2 * 0.001
UserLoc(1) = ScratchLoc(3)
Else
Reading_Loc = -99999
EndIf
Else
Reading_Loc = -99998
EndIf
EndIf
If GageType_Loc = 2 then
if ScratchLoc(7) > 55.6 and ScratchLoc(7) < 201100 then
Reading_Loc = 1/(.0014051 + (.0002369*Log(ScratchLoc(7))) + (.0000001019*(Log(ScratchLoc(7))^3))) - 273.2
Else
Reading_Loc = -99.99
Endif
EndIf
If GageType_Loc = 3 then
SDI12Recorder (sInBuf,7,0,"XVW2000,3500,2!",1.0,0)
SDI12Recorder (ScratchLoc(2),7,0,"M1!",1.0,0)
if ScratchLoc(2) > 0 then
if ScratchLoc(3) > 0.1 then
Reading_Loc = ScratchLoc(2)^2 * 0.001
UserLoc(1) = ScratchLoc(3)
Else
Reading_Loc = -99999
EndIf
Else
Reading_Loc = -99998
EndIf
EndIf
If GageType_Loc = 4 then
SDI12Recorder (sInBuf,7,0,"XVW400,6000,2!",1.0,0)
SDI12Recorder (ScratchLoc(2),7,0,"M1!",1.0,0)
if ScratchLoc(2) > 0 then
if ScratchLoc(3) > 0.1 then
Reading_Loc = ScratchLoc(2)^2 * 0.001
UserLoc(1) = ScratchLoc(3)
Else
Reading_Loc = -99999
EndIf
Else
Reading_Loc = -99998
EndIf
EndIf
EndSub
Sub ReadMux1Sub
MuxNumber = 1
Move(MuxReadingLoc(),48,0.0,1)
PortSet(1,1)
Delay(0,125,MSEC)
For Channel = 1 TO 16
PortSet(8,1)
Delay(0,10,MSEC)
PortSet(8,0)
Delay(0,10,MSEC)
Reading_Loc = 0
Select Case Channel
Case 1
GageType_Loc = 1
Call Readgages
Case 2
GageType_Loc = 1
Call Readgages
Case 3
GageType_Loc = 1
Call Readgages
Case 4
GageType_Loc = 1
Call Readgages
Case 5
GageType_Loc = 3
Call Readgages
Case 6
GageType_Loc = 3
Call Readgages
Case 7
GageType_Loc = 3
Call Readgages
Case 8
GageType_Loc = 1
Call Readgages
Case 9
GageType_Loc = 4
Call Readgages
Case 10
GageType_Loc = 4
Call Readgages
EndSelect
MuxReadingLoc(Channel) = Reading_Loc
Reading_Loc = 0
Select Case Channel
Case 1
GageType_Loc = 2
Call ReadGages
Case 2
GageType_Loc = 2
Call ReadGages
Case 3
GageType_Loc = 2
Call ReadGages
Case 4
GageType_Loc = 2
Call ReadGages
Case 5
GageType_Loc = 2
Call ReadGages
Case 6
GageType_Loc = 2
Call ReadGages
Case 7
GageType_Loc = 2
Call ReadGages
Case 8
GageType_Loc = 2
Call ReadGages
Case 9
GageType_Loc = 2
Call ReadGages
Case 10
GageType_Loc = 2
Call ReadGages
EndSelect
MuxReadingLoc(Channel + 16) = Reading_Loc
PortSet(8,1)
Delay(0,10,MSEC)
PortSet(8,0)
Delay(0,10,MSEC)
Next
PortSet(1,0)
If MuxReadingLoc(1) > -99990 then MuxReadingLoc(1) = (MuxReadingLoc(1) - 4339.347656) * 0.003008
If MuxReadingLoc(2) > -99990 then MuxReadingLoc(2) = (MuxReadingLoc(2) - 4139.629883) * 0.002985
If MuxReadingLoc(3) > -99990 then MuxReadingLoc(3) = (MuxReadingLoc(3) - 4847.144043) * 0.002989
If MuxReadingLoc(4) > -99990 then MuxReadingLoc(4) = (MuxReadingLoc(4) - 4058.355469) * 0.002981
If MuxReadingLoc(5) > -99990 then MuxReadingLoc(5) = (MuxReadingLoc(5) - 4579.000000) * -0.033890
If MuxReadingLoc(6) > -99990 then MuxReadingLoc(6) = (MuxReadingLoc(6) - 4537.000000) * -0.033680
If MuxReadingLoc(7) > -99990 then MuxReadingLoc(7) = (MuxReadingLoc(7) - 4072.000000) * -0.034680
If MuxReadingLoc(8) > -99990 then MuxReadingLoc(8) = (MuxReadingLoc(8) - 4517.856445) * 0.001143
If MuxReadingLoc(9) > -99990 then MuxReadingLoc(9) = (MuxReadingLoc(9) - 5317.368164) * 0.002993
If MuxReadingLoc(10) > -99990 then MuxReadingLoc(10) = (MuxReadingLoc(10) - 5444.545898) * 0.002990
Move(Mux1CH(),16,MuxReadingLoc(),16)
Move(Mux1TempCH(),16,MuxReadingLoc(17),16)
MuxNumber = 0
EndSub
Sub ReadMux2Sub
MuxNumber = 2
Move(MuxReadingLoc(),48,0.0,1)
PortSet(2,1)
Delay(0,125,MSEC)
For Channel = 1 TO 16
PortSet(8,1)
Delay(0,10,MSEC)
PortSet(8,0)
Delay(0,10,MSEC)
Reading_Loc = 0
Select Case Channel
Case 1
GageType_Loc = 3
Call Readgages
Case 2
GageType_Loc = 3
Call Readgages
Case 3
GageType_Loc = 3
Call Readgages
Case 4
GageType_Loc = 3
Call Readgages
EndSelect
MuxReadingLoc(Channel) = Reading_Loc
Reading_Loc = 0
Select Case Channel
Case 1
GageType_Loc = 2
Call ReadGages
Case 2
GageType_Loc = 2
Call ReadGages
Case 3
GageType_Loc = 2
Call ReadGages
Case 4
GageType_Loc = 2
Call ReadGages
Case 5
GageType_Loc = 2
Call ReadGages
Case 10
GageType_Loc = 2
Call ReadGages
Case 13
GageType_Loc = 2
Call ReadGages
EndSelect
MuxReadingLoc(Channel + 16) = Reading_Loc
PortSet(8,1)
Delay(0,10,MSEC)
PortSet(8,0)
Delay(0,10,MSEC)
Next
PortSet(2,0)
If MuxReadingLoc(1) > -99990 then MuxReadingLoc(1) = (MuxReadingLoc(1) - 4506.000000) * -0.033510
If MuxReadingLoc(2) > -99990 then MuxReadingLoc(2) = (MuxReadingLoc(2) - 4548.000000) * -0.034050
If MuxReadingLoc(3) > -99990 then MuxReadingLoc(3) = (MuxReadingLoc(3) - 4395.000000) * -0.033540
If MuxReadingLoc(4) > -99990 then MuxReadingLoc(4) = (MuxReadingLoc(4) - 5292.000000) * -0.033290
Move(Mux2CH(),16,MuxReadingLoc(),16)
Move(Mux2TempCH(),16,MuxReadingLoc(17),16)
MuxNumber = 0
EndSub
'Main Program
BeginProg
Scan(1,HR,1,0)
Logger_ID = 100
Program_Mode = 0
Flag(5) = 0
Flag(6) = 0
Flag(7) = 0
Flag(8) = 0
Call GetTime
ReadFlag = 1
If ReadFlag then
Timer (1,uSec,2)
Battery(Battery_Volts)
PanelTemp(Panel_Temp,250)
'Read Direct Connect Instruments
Move(MuxReadingLoc(),48,0.0,1)
Reading_Loc = 0
Channel = 1
VoltDiff (Reading_Loc,1,mv2500,1,False,0,250,.008264463,0)
MuxReadingLoc(1) = Reading_Loc
Reading_Loc = 0
Channel = 2
VoltDiff (Reading_Loc,1,mv2500,2,False,0,250,.008264463,0)
MuxReadingLoc(2) = Reading_Loc
If MuxReadingLoc(1) > -99990 Then MuxReadingLoc(1) = (MuxReadingLoc(1) - 4.000000) * 3.125000
If MuxReadingLoc(2) > -99990 Then MuxReadingLoc(2) = (MuxReadingLoc(2) - 4.000000) * 3.125000
Pendulum_X = MuxReadingLoc(1)
Pendulum_Y = MuxReadingLoc(2)
'Read Instruments on Mux 1
Call ReadMux1Sub
'Read Instruments on Mux 2
Call ReadMux2Sub
'Data Output Programming
CALLTABLE(FSDATA)
Complete_Scans = Complete_Scans + 1
Read_Time = Timer (1,uSec,4) / 1000000
Timer (1,uSec,3)
EndIf
NextScan
Public PTemp,batt_volt
Public Result
Public AVWDest(7)
Public ModBus(9)
Dim Port(8) As Boolean
ModBusSlave (COMRS232,9600,5,ModBus(),Port(),2)
Scan (5,Min,0,0)
'Read Direct Connect Instruments
Move(MuxReadingLoc(),48,0.0,1)
Reading_Loc = 0
Channel = 1
VoltDiff (Reading_Loc,1,mv2500,1,False,0,250,.008264463,0)
MuxReadingLoc(1) = Reading_Loc
Reading_Loc = 0
Channel = 2
VoltDiff (Reading_Loc,1,mv2500,2,False,0,250,.008264463,0)
MuxReadingLoc(2) = Reading_Loc
If MuxReadingLoc(1) > -99990 Then MuxReadingLoc(1) = (MuxReadingLoc(1) - 4.000000) * 3.125000
If MuxReadingLoc(2) > -99990 Then MuxReadingLoc(2) = (MuxReadingLoc(2) - 4.000000) * 3.125000
Pendulum_X = MuxReadingLoc(1)
Pendulum_Y = MuxReadingLoc(2)
Modbus(47) = MuxReadingLoc(1)
ModBus(48) = MuxReadingLoc(2)
ModBus(11) = PTemp
ModBus(10) = batt_volt
ModBus(49) = AVWDest(9)
ModBus(50) = AVWDest(9)
ModBus(51) = AVWDest(9)
ModBus(52) = AVWDest(9)
ModBus(53) = AVWDest(9)
ModBus(54) = AVWDest(9)
ModBus(55) = AVWDest(9)
ModBus(56) = AVWDest(9)
ModBus(57) = AVWDest(9)
ModBus(58) = AVWDest(9)
ModBus(65) = AVWDest(9)
ModBus(66) = AVWDest(9)
ModBus(67) = AVWDest(9)
ModBus(68) = AVWDest(9)
ModBus(69) = AVWDest(9)
ModBus(70) = AVWDest(9)
ModBus(71) = AVWDest(9)
ModBus(72) = AVWDest(9)
ModBus(73) = AVWDest(9)
ModBus(74) = AVWDest(9)
ModBus(81) = AVWDest(9)
ModBus(82) = AVWDest(9)
ModBus(83) = AVWDest(9)
ModBus(84) = AVWDest(9)
ModBus(97) = AVWDest(9)
ModBus(98) = AVWDest(9)
ModBus(99) = AVWDest(9)
ModBus(100) = AVWDest(9)
NextScan
EndProg
Did you write this program?
Without trying to wade through the bulk of the program, a few items jump out at me.
* The 1 HR scan will be entered and never exited. Thus, the 5 minute scan will never be executed
* The ModBusSlave instruction will never be executed as it lies after the 1 HR scan that will never be exited.
* The ModuBus() updates occur inside the 5 minute scan and therefore will never occur because the 5 minute scan never executes.
It almost looks like you took another program and just tacked on a new scan.
Yeah my programming aint that good so I am trying my best here. I would appreciate if you could give me some help/pointers on how to get modbus slave function into this program.
Regards,
Oskar
This post is under review.