﻿%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Device definition for IMSE MxA12
%
% Settings module:
%       Parity: None
%       Baud:   38400
%       Mode:   RTU
%       
% Factory default 
%       Address: 1
% 
% Author: Daniel Carlson, ABELKO AB Luleå
%
% History:  2016-09-23 Initial version (Converted to WMPro)
%

DEVICETYPE MxA12_AO NAMED "MxA12_AO" TYPEID 21480 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Communication timeout
    ComTimeout: "ComTimeout"; 

    % Analog output
    AO1: "AO1";
    AO2: "AO2";
    AO3: "AO3";
    AO4: "AO4";
      
  PUBLIC
    % AO Override
    AO1_Overridden : "AO1 Man. overr.";      
    AO2_Overridden : "AO2 Man. overr.";      
    AO3_Overridden : "AO3 Man. overr.";      
    AO4_Overridden : "AO4 Man. overr.";      
    
  PRIVATE
    Tmp;
    Tmp2;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
  
	TELEGRAM SetComTimeout NAMED "SetCommunicationTimeout" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(6);       % Modbus command "6" write single register
      DATA[2]  := RWORD(33);     % Start register
      DATA[4]  <- RWORD(DATA := ComTimeout;); 
      
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(6);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(33);
  
    TIMEOUT 300
  END;
	
  TELEGRAM SetAO1_6 NAMED "SetAO1-6" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(42);     % Start register
      DATA[4]  := RWORD(8);      % Number of registers to write
      DATA[6]  := BYTE(16);      % Numer of bytes of data, two for each AO
      DATA[7]  := RWORD(0);
      DATA[9]  <- RWORD(DATA :=  AO1 * 1000;);
      DATA[11] := RWORD(0);
      DATA[13] <- RWORD(DATA :=  AO2 * 1000;);
      DATA[15] := RWORD(0);
      DATA[17] <- RWORD(DATA :=  AO3 * 1000;);
      DATA[19] := RWORD(0);
      DATA[21] <- RWORD(DATA :=  AO4 * 1000;);

    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(42);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(8);

    TIMEOUT 300
  END;
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit
  
  TELEGRAM GetAO1_6Status NAMED "GetAO1-6Status" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(25);     % Start register
      DATA[4]  := RWORD(8);      % Number of registers to read
            
    ANSWER SIZE 21
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(16);      % Numer of bytes of data
      DATA[3]  -> RWORD(Tmp :=  DATA;);
      DATA[5]  -> RWORD(IF DATA < 32768 THEN AO1_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO1_Overridden := -1; ENDIF;);
      DATA[7]  -> RWORD(Tmp :=  DATA;);
      DATA[9]  -> RWORD(IF DATA < 32768 THEN AO2_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO2_Overridden := -1; ENDIF;);
      DATA[11] -> RWORD(Tmp :=  DATA;);
      DATA[13] -> RWORD(IF DATA < 32768 THEN AO3_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO3_Overridden := -1; ENDIF;);
      DATA[15] -> RWORD(Tmp :=  DATA;);
      DATA[17] -> RWORD(IF DATA < 32768 THEN AO4_Overridden := (DATA + Tmp*65536) / 1000; ELSE AO4_Overridden := -1; ENDIF;);

    TIMEOUT 300
  END;
END;

DEVICETYPE MxA12_UI NAMED "MxA12_UI" TYPEID 21481 IS  
  PARAMETER
    % Address of this unit
    Addr: "Address";
    
    % Universal input type
    UI1_Type: "UI1 Type";
    UI2_Type: "UI2 Type";
    UI3_Type: "UI3 Type";
    UI4_Type: "UI4 Type";
    UI5_Type: "UI5 Type";
    UI6_Type: "UI6 Type";
    UI7_Type: "UI7 Type";
    UI8_Type: "UI8 Type";
    
    % Resistor Range
    %UI1_Range: "UI1_Range ";
    %UI2_Range: "UI2_Range ";
    %UI3_Range: "UI3_Range ";
    %UI4_Range: "UI4_Range ";
    %UI5_Range: "UI5_Range ";
    %UI6_Range: "UI6_Range ";
    %UI7_Range: "UI7_Range ";
    %UI8_Range: "UI8_Range ";
      
  PUBLIC
    % Universal input value
    UI1 : "UI1";
    UI2 : "UI2";
    UI3 : "UI3";
    UI4 : "UI4";
    UI5 : "UI5";
    UI6 : "UI6";
    UI7 : "UI7";
    UI8 : "UI8";
   
    % Universal input status
    UI1_Status : "UI1 Status";
    UI2_Status : "UI2 Status";
    UI3_Status : "UI3 Status";
    UI4_Status : "UI4 Status";
    UI5_Status : "UI5 Status";
    UI6_Status : "UI6 Status";
    UI7_Status : "UI7 Status";
    UI8_Status : "UI8 Status";
          
  PRIVATE
    Tmp;
    UI1_Raw;
    UI2_Raw;
    UI3_Raw;
    UI4_Raw;
    UI5_Raw;
    UI6_Raw;
    UI7_Raw;
    UI8_Raw;
    
    % Used by group script
    Input;
    Raw;
    Type;
    Value;
    R2;
    R3;
    R5;
    R7;
    LNR;
    
  BAUDRATE 38400;
  CHECKSUM MODBUS SWAPPED;
    
  TELEGRAM SetUISettings NAMED "SetUISettings" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(16);      % Modbus command "16" write multiple registers
      DATA[2]  := RWORD(34);    % Start register
      DATA[4]  := RWORD(8);      % Number of registers to write
      DATA[6]  := BYTE(16);      % Numer of bytes of data, two for each DO
      DATA[7]  <- RWORD(IF UI1_Type > 3 THEN DATA := 0; ELSE DATA := UI1_Type * 64; ENDIF;);
      DATA[9]  <- RWORD(IF UI2_Type > 3 THEN DATA := 0; ELSE DATA := UI2_Type * 64; ENDIF;);
      DATA[11] <- RWORD(IF UI3_Type > 3 THEN DATA := 0; ELSE DATA := UI3_Type * 64; ENDIF;);
      DATA[13] <- RWORD(IF UI4_Type > 3 THEN DATA := 0; ELSE DATA := UI4_Type * 64; ENDIF;);
      DATA[15] <- RWORD(IF UI5_Type > 3 THEN DATA := 0; ELSE DATA := UI5_Type * 64; ENDIF;);
      DATA[17] <- RWORD(IF UI6_Type > 3 THEN DATA := 0; ELSE DATA := UI6_Type * 64; ENDIF;);
      DATA[19] <- RWORD(IF UI7_Type > 3 THEN DATA := 0; ELSE DATA := UI7_Type * 64; ENDIF;);
      DATA[21] <- RWORD(IF UI8_Type > 3 THEN DATA := 0; ELSE DATA := UI8_Type * 64; ENDIF;);
          
    ANSWER SIZE 8
      DATA[0] = BYTE(Addr);
      DATA[1] = BYTE(16);
      DATA[2] = BYTE(0);
      DATA[3] = BYTE(34);
      DATA[4] = BYTE(0);
      DATA[5] = BYTE(8);

    TIMEOUT 300
  END;
      
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Telegrams used for getting values from the unit
    
  TELEGRAM GetUI1_8 NAMED "GetUI1-8" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(1);      % Start register
      DATA[4]  := RWORD(16);     % Number of registers to read
            
    ANSWER SIZE 37
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(32);      % Numer of bytes of data
      
      DATA[3]  -> RWORD(Tmp     :=  DATA;);
      DATA[5]  -> RWORD(UI1_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[7]  -> RWORD(Tmp     :=  DATA;);
      DATA[9]  -> RWORD(UI2_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[11] -> RWORD(Tmp     :=  DATA;);
      DATA[13] -> RWORD(UI3_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[15] -> RWORD(Tmp     :=  DATA;);
      DATA[17] -> RWORD(UI4_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[19] -> RWORD(Tmp     :=  DATA;);
      DATA[21] -> RWORD(UI5_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[23] -> RWORD(Tmp     :=  DATA;);
      DATA[25] -> RWORD(UI6_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[27] -> RWORD(Tmp     :=  DATA;);
      DATA[29] -> RWORD(UI7_Raw := (DATA + Tmp*65536) / 1000;);
      DATA[31] -> RWORD(Tmp     :=  DATA;);
      DATA[33] -> RWORD(UI8_Raw := (DATA + Tmp*65536) / 1000;);
      
    TIMEOUT 300
  END;
  
  TELEGRAM GetUI1_8Status NAMED "GetUI1-8Status" IS
    QUESTION
      DATA[0]  := BYTE(Addr);    % Modbus unit address
      DATA[1]  := BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  := RWORD(17);     % Start register
      DATA[4]  := RWORD(8);      % Number of registers to read
            
    ANSWER SIZE 21
      DATA[0]  =  BYTE(Addr);    % Modbus unit address
      DATA[1]  =  BYTE(3);       % Modbus command "03h" read multiple registers
      DATA[2]  =  BYTE(16);      % Numer of bytes of data
      DATA[3]  -> RWORD(UI1_Status := DATA;);
      DATA[5]  -> RWORD(UI2_Status := DATA;);
      DATA[7]  -> RWORD(UI3_Status := DATA;);
      DATA[9]  -> RWORD(UI4_Status := DATA;);
      DATA[11] -> RWORD(UI5_Status := DATA;);
      DATA[13] -> RWORD(UI6_Status := DATA;);
      DATA[15] -> RWORD(UI7_Status := DATA;);
      DATA[17] -> RWORD(UI8_Status := DATA;);
      
    TIMEOUT 300
  END;
END; 


% Group script used to calulate vaues for universal inputs
GROUP All_UI OF MAX 4 DEVICE TYPEID 21481 SELECT ALL
  ITERATOR CalcValue
  ALIAS
  BEGIN
    IF Input = 1 THEN
      Type  := UI2_Type;
      Raw   := UI2_Raw;
    ELSIF Input = 2 THEN
      Type  := UI3_Type;
      Raw   := UI3_Raw;
    ELSIF Input = 3 THEN
      Type  := UI4_Type;
      Raw   := UI4_Raw;
    ELSIF Input = 4 THEN
      Type  := UI5_Type;
      Raw   := UI5_Raw;
    ELSIF Input = 5 THEN
      Type  := UI6_Type;
      Raw   := UI6_Raw;
    ELSIF Input = 6 THEN
      Type  := UI7_Type;
      Raw   := UI7_Raw;
    ELSIF Input = 7 THEN
      Type  := UI8_Type;
      Raw   := UI8_Raw;
    ELSE	
      Type  := UI1_Type;
      Raw   := UI1_Raw;
      Input := 0;
    ENDIF;
    
    IF Type <= 3 THEN % Raw resistance, Voltage, Current or DI
      Value := Raw;
    
    ELSIF Type = 4 THEN %Pt100 EN 50 751 alpha 0.00385
      Value := 3383.809524 - 0.08658008660 * (1758480889 - 2310000 * Raw)^0.5;
    ELSIF Type = 5 THEN %Pt100 alpha 0.00375
      Value := 3164.451827 - 8305.647840 * (0.169241 - 0.000240800 * Raw)^0.5;
    ELSIF Type = 6 THEN %Pt100 alpha 0.00392
      Value := 3392.940594 - 8527.911855 * (0.1817473668 - 0.00023452400 * Raw)^0.5;
    ELSIF Type = 7 THEN %Pt1000 EN 50 751 alpha 0.00385
      Value := 3383.809524 - 865.8008660 * (17.58480889 - 0.00231 * Raw)^0.5;
    ELSIF Type = 8 THEN %Pt1000 alpha 0.00375
      Value := 3164.451827 - 830.5647840 * (16.9241 - 0.002408 * Raw)^0.5;
    ELSIF Type = 9 THEN %Pt1000 alpha 0.00392
      Value := 3392.940594 - 852.7911855 * (18.17473668 - 0.00234524 * Raw)^0.5;
    ELSIF	Type = 10 THEN %Ni1000 DIN
      R5:= Raw*Raw*Raw*Raw*Raw;
      R7:= R5*Raw*Raw;
      Value := (-412.6) + (140.41 * (1 + (0.00764 * Raw))^0.5) - (0.0000000000000000625 * R5) - (0.00000000000000000000000125 * R7);
    ELSIF	Type = 11 THEN %Ni1000 LG
      R2:= Raw*Raw;
      R3:= R2*Raw;
      Value := (-300.0187) + (Raw * 0.3888) - (R2 * 0.00010355) + (R3 * 0.000000014749);
    ELSIF	Type = 12 THEN %QAC31/32 old
      R2:= Raw*Raw;
      R3:= R2*Raw;
      IF Raw <= 622.27 THEN
        Value :=  1840.822526461981 - (8.81283638032425 * Raw) + (0.01481833026842 * R2) - (0.000008693645718129028 * R3);
      ELSIF Raw <= 655.74 THEN
        Value :=  18284.57180623524 - (87.53497076730491 * Raw) + (0.14047361791540 * R2) - (0.00007556728104760220 * R3);
      ELSE
        Value :=  447598.5593294129 - (2034.707401563966 * Raw) + (3.08435262703205 * R2) - (0.00155918519608 * R3);      
      ENDIF;  
    ELSIF	Type = 13 THEN %NTC575 (QAC3132)
      R2:= Raw*Raw;
      R3:= R2*Raw;
      IF Raw <= 616.7 THEN
        Value :=  1984.368236149433 - (9.45847603610924 * Raw) + (0.01577267911992 * R2) - (0.000009153756833227248 * R3);
      ELSIF Raw <= 675.5 THEN
        Value :=  13500.31890121417 - (64.89024643188350 * Raw) + (0.10472492893027 * R2) - (0.00005674169841769381 * R3);
      ELSE
        Value :=  -8135.044676629710 + (25.40018648262130 * Raw) - (0.01986043031034 * R2);      
      ENDIF;  
    ELSIF	Type = 14 THEN %FWT1G
      Value := (-264.6311531847244) + (Raw * 0.13733939226662) - (Raw * Raw * 0.000008300189626466234);
    ELSIF	Type = 15 THEN %FOT35
      LNR:= LN(Raw);
      Value := 245.7686957352614 - (Raw * 0.0002180214076186565) + (Raw * Raw * 0.000000001160703041443256) + (0.07334532481221 * LNR * LNR * LNR) - (34.06632737942485 * LNR);
    ELSIF	Type = 16 THEN %TAC ECU
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.00114944558407 + (0.0002941176088004037 * LNR) - (0.0000000000002525998855897292 * LNR* LNR* LNR)));

    ELSIF	Type = 17 THEN %Satchwell DOT
      R2 := Raw*Raw;
      R3 := R2*Raw;
      IF Raw >= 7661 THEN
        Value :=  508885.1065949351 - (19.71706149035526 * Raw) + (0.001301247481832191 * R2) - (0.00000003594831664363352 * R3) - (3738912.809188366 / LN(Raw));
      ELSIF Raw >= 1193 THEN
        Value :=  (-128.4611061637296) - (0.007002012490937275 * Raw) + (0.0000006986512762901833 * R2) - (0.00000000006639391744752032 * R3) + (1529.490359465714 / LN(Raw));
      ELSE
        Value :=  (-339.6118638033802) + (0.09063945312481900 * Raw) - (0.00006415896542404209 * R2) + (0.00000001784096838726073 * R3) + (2639.015168861766 / LN(Raw));
      ENDIF;  
    ELSIF	Type = 18 THEN %Satchwell DW1204 DWS1202
      R2 := Raw*Raw;
      R3 := R2*Raw;
      IF Raw >= 2236 THEN
        Value :=  39382.90132075548 - (6.021252248143583 * Raw) + (0.0013733544102798 * R2) - (0.0000001313622917888568 * R3) - (241223.6906016618 / LN(Raw));
      ELSIF Raw >= 974 THEN
        Value :=  (-888.2657030489725) + (0.1056691176426888 * Raw) - (0.00002987131417113171 * R2) + (0.000000002522599122874649 * R3) + (6271.371860366971 / LN(Raw));
      ELSE
        Value :=  (-9517.677682528738) + (4.164299211339042 * Raw) - (0.002604874308355931 * R2) + (0.0000006794599871065049 * R3) + (50956.91507092444 / LN(Raw));
      ENDIF;  
    ELSIF	Type = 19 THEN %Satchwell DO2202
      R2 := Raw*Raw;
      R3 := R2*Raw;
      Value :=  (-1021.199118881201) + (0.04569968689660045 * Raw) + (0.00002069764420667956 * R2) - (0.00000000981645089002807 * R3) + (6869.504979681983 / LN(Raw));
    ELSIF	Type = 20 THEN %IVT
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001311184263438729 + (0.0002338997792885658 * LNR) + (0.0000001077046283506101 * LNR * LNR * LNR)));
    ELSIF	Type = 21 THEN %NIBE
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001387800349275742 + (0.0002400761437010071 * LNR) + (0.00000008613539226217632 * LNR * LNR * LNR)));
    ELSIF	Type = 22 THEN %KTY 10/7
      R2 := Raw*Raw;
      R3 := R2*Raw;
      Value :=  311.5439406854249 + (0.04844211701143084 * Raw) - (0.000002908837846165819 * R2) + (0.0000000001362467604839759 * R3) - (2848.566087438425 / LN(Raw));
    ELSIF	Type = 23 THEN %Bodendammen
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001466426327478712 + (0.0002385193263772018 * LNR) + (0.0000001006014722395608 * LNR * LNR * LNR)));
    ELSIF	Type = 24 THEN %T7043 Honywell
      LNR:= LN(Raw);
      Value := (-273.15) + (1 / (0.001705367599798446 + (0.0002527653342936799 * LNR) + (0.0000000005227580950721076 * LNR * LNR * LNR)));

    ELSE
      Value := Raw;
    ENDIF;  

    IF Input = 1 THEN
      UI2 := Value;
    ELSIF Input = 2 THEN
      UI3 := Value;
    ELSIF Input = 3 THEN
      UI4 := Value;
    ELSIF Input = 4 THEN
      UI5 := Value;
    ELSIF Input = 5 THEN
      UI6 := Value;
    ELSIF Input = 6 THEN
      UI7 := Value;
    ELSIF Input = 7 THEN
      UI8 := Value;
    ELSE	
      UI1 := Value;
    ENDIF;
    Input := Input +1;
  END;
END;  	


%Calls All_UI.CalcValue to calculate Universal input values
ROUTINE UpdateUI
BEGIN
  %One call for each input	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;		
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
  CALL All_UI.CalcValue;	
END;	
