Procon MODMUX PM16DI

Detaljer

Typ
Drivrutin
Upplaggd av
Ove Jansson, Abelko Innovation
Version
2
Uppdaterad
2013-08-27
Skapad
2013-08-27
Kategori
IO enheter, Modbus
Visningar
2602

Beskrivning

Drivrutin till Procon MODMUX IO enhet

Bruksanvisning

Ladda in typdefinitionen enligt beskrivningen i manualen kapitel 18.2.

Datablad för modulerna hittar man på Procons hemsida: http://www.proconel.com/

Juridisk information

Alla skript tillhandahålls i befintligt skick och all användning sker på eget ansvar. Felaktig använding kan leda till skadad eller förstörd utrustning.

Skript kod

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Typdefinition för PROCON MODMUX modul PM16DI, PM16DI-110, PM15DI-220.
%
% Denna modul har 16 digitala ingångar.
% Datablad för modulerna hittar man på Procons hemsida: 
% http://www.proconel.com/modmux.htm
%
% NOTE! 
% For counting registers.
% Run telegram "Check overflow" to ENABLE the counting registers
% and check OVERFLOW in counters.
% As the counting values are saved as float, the counter value is 
% rewinded at 1 000 000 to avoid data loss due to significans (7 figures).
%
% To remember.
% When the filter time changes from <=10 to >10 ms the counter registers
% are alternated with the values in non-volatile memory. The same hapens 
% when filetr changes the other way.
% SET THE FILTER TIME ONCE AND FOR ALL !  
%
% Baudrate: 9600
%
% Original: 100209 PW
%
DEVICETYPE ProconPM16DI NAMED "Procon 16DI" TYPEID 21103 IS
  PARAMETER
    Id     : "Modbus address";
   %Mode   : "CNT Mode (0-2)"; Always set to 1 = Up Counting
   %MaxCnt : "Max Counter";
   %Filter : "In Filter (ms)";

  PUBLIC
    DI1    : "Status DI1";
    DI2    : "Status DI2";
    DI3    : "Status DI3";
    DI4    : "Status DI4";
    DI5    : "Status DI5";
    DI6    : "Status DI6";
    DI7    : "Status DI7";
    DI8    : "Status DI8";
    DI9    : "Status DI9";
    DI10   : "Status DI10";
    DI11   : "Status DI11";
    DI12   : "Status DI12";
    DI13   : "Status DI13";
    DI14   : "Status DI14";
    DI15   : "Status DI15";
    DI16   : "Status DI16";
 
  PRIVATE
    Tmp;
    
  BAUDRATE 9600;
  CHECKSUM MODBUS SWAPPED;

  TELEGRAM ReadInputs NAMED "Read DI Status" IS

    QUESTION
      DATA[0] := BYTE(Id);
      DATA[1] := HEX(04); % Command 4 Read Input data
      DATA[2] := RWORD(1); % Start register = 30002
      DATA[4] := RWORD(1); % Number of registers = 1, 16 bit for digital status

    ANSWER SIZE 7
      DATA[0] = BYTE(Id);
      DATA[1] = HEX(04);
      DATA[2] = BYTE(2);
      DATA[3] -> RWORD(
        IF (DATA & 1    ) THEN DI1 :=1; ELSE DI1 :=0; ENDIF;
        IF (DATA & 2    ) THEN DI2 :=1; ELSE DI2 :=0; ENDIF;
        IF (DATA & 4    ) THEN DI3 :=1; ELSE DI3 :=0; ENDIF;
        IF (DATA & 8    ) THEN DI4 :=1; ELSE DI4 :=0; ENDIF;
        IF (DATA & 16   ) THEN DI5 :=1; ELSE DI5 :=0; ENDIF;
        IF (DATA & 32   ) THEN DI6 :=1; ELSE DI6 :=0; ENDIF;
        IF (DATA & 64   ) THEN DI7 :=1; ELSE DI7 :=0; ENDIF;
        IF (DATA & 128  ) THEN DI8 :=1; ELSE DI8 :=0; ENDIF;
        IF (DATA & 256  ) THEN DI9 :=1; ELSE DI9 :=0; ENDIF;
        IF (DATA & 512  ) THEN DI10:=1; ELSE DI10:=0; ENDIF;
        IF (DATA & 1024 ) THEN DI11:=1; ELSE DI11:=0; ENDIF;
        IF (DATA & 2048 ) THEN DI12:=1; ELSE DI12:=0; ENDIF;
        IF (DATA & 4096 ) THEN DI13:=1; ELSE DI13:=0; ENDIF;
        IF (DATA & 8192 ) THEN DI14:=1; ELSE DI14:=0; ENDIF;
        IF (DATA & 16384) THEN DI15:=1; ELSE DI15:=0; ENDIF;
        IF (DATA & 32768) THEN DI16:=1; ELSE DI16:=0; ENDIF;
      );

    TIMEOUT 500

  END;

END;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Typdefinition för PROCON MODMUX modul PM16DI, PM16DI-110, PM15DI-220.
%
% Denna modul har 16 digitala ingångar.
% Datablad för modulerna hittar man på Procons hemsida: 
% http://www.proconel.com/modmux.htm
%
% For counting registers.
% Run telegram "Check overflow" to enable the counting registers.
% As the counting values are saved as float, the counter value is 
% rewinded at 1 000 000 to avoid data loss due to significans.
%
% To remember.
% When the filter time changes from <=10 to >10 ms the counter registers
% are alternated with the values in non-volatile memory. The same hapens 
% when filetr changes the other way.
% SET THE FILTER TIME ONCE AND FOR ALL !  
%
% Baudrate: 9600
%
% Original: 100209 PW
%
DEVICETYPE ProconPM16DICnt NAMED "Procon 16DI cnt" TYPEID 21104 IS
  PARAMETER
    Id     : "Modbus address";
   %Mode   : "Cnt Mode (0-2)"; Always set to 1 = Up Counting
   %MaxCnt : "Max Counter";
    Filter : "In Filter (ms)";

  PUBLIC
    DI1    : "Counter DI1";
    DI2    : "Counter DI2";
    DI3    : "Counter DI3";
    DI4    : "Counter DI4";
    DI5    : "Counter DI5";
    DI6    : "Counter DI6";
    DI7    : "Counter DI7";
    DI8    : "Counter DI8";
    DI9    : "Counter DI9";
    DI10   : "Counter DI10";
    DI11   : "Counter DI11";
    DI12   : "Counter DI12";
    DI13   : "Counter DI13";
    DI14   : "Counter DI14";
    DI15   : "Counter DI15";
    DI16   : "Counter DI16";

  PRIVATE
    Started;
    Updated;
    Tmp;
    OF1; OF2;  OF3;  OF4;  OF5;  OF6;  OF7;  OF8;
    OF9; OF10; OF11; OF12; OF13; OF14; OF15; OF16;
    CntUpdate;
    CntValue;
    SilenceCnt;
    
  BAUDRATE 9600;
  CHECKSUM MODBUS SWAPPED;

  TELEGRAM ReadInputs NAMED "Read DI Counters" IS

    QUESTION
      DATA[0] := BYTE(Id);
      DATA[1] := BYTE(3); % Command 3 Read Input data
      DATA[2] := RWORD(2); % Start register = 3
      DATA[4] := RWORD(32); % Number of registers = 32, 16 * counter register high and low

    ANSWER SIZE 69
      DATA[0] = BYTE(Id);
      DATA[1] = BYTE(3);
      DATA[2] = BYTE(64);
      DATA[3] -> RWORD(Tmp    := DATA * 65536;);
      DATA[5] -> RWORD(DI1 := DATA + Tmp;
                       IF (DI1 > 1000000) THEN OF1:=1; ENDIF;
                       );
      DATA[7] -> RWORD(Tmp    := DATA * 65536;);
      DATA[9] -> RWORD(DI2 := DATA + Tmp;
                       IF (DI2 > 1000000) THEN OF2:=1; ENDIF;
                       );
      DATA[11]-> RWORD(Tmp    := DATA * 65536;);
      DATA[13]-> RWORD(DI3 := DATA + Tmp;
                       IF (DI3 > 1000000) THEN OF3:=1; ENDIF;
                       );
      DATA[15]-> RWORD(Tmp    := DATA * 65536;);
      DATA[17]-> RWORD(DI4 := DATA + Tmp;
                       IF (DI4 > 1000000) THEN OF4:=1; ENDIF;
                       );
      DATA[19]-> RWORD(Tmp    := DATA * 65536;);
      DATA[21]-> RWORD(DI5 := DATA + Tmp;
                       IF (DI5 > 1000000) THEN OF5:=1; ENDIF;
                       );
      DATA[23]-> RWORD(Tmp    := DATA * 65536;);
      DATA[25]-> RWORD(DI6 := DATA + Tmp;
                       IF (DI6 > 1000000) THEN OF6:=1; ENDIF;
                       );
      DATA[27]-> RWORD(Tmp    := DATA * 65536;);
      DATA[29]-> RWORD(DI7 := DATA + Tmp;
                       IF (DI7 > 1000000) THEN OF7:=1; ENDIF;
                       );
      DATA[31]-> RWORD(Tmp    := DATA * 65536;);
      DATA[33]-> RWORD(DI8 := DATA + Tmp;
                       IF (DI8 > 1000000) THEN OF8:=1; ENDIF;
                       );
      DATA[35]-> RWORD(Tmp    := DATA * 65536;);
      DATA[37]-> RWORD(DI9 := DATA + Tmp;
                       IF (DI9 > 1000000) THEN OF9:=1; ENDIF;
                       );
      DATA[39]-> RWORD(Tmp    := DATA * 65536;);
      DATA[41]-> RWORD(DI10:= DATA + Tmp;
                       IF (DI10> 1000000) THEN OF10:=1; ENDIF;
                       );
      DATA[43]-> RWORD(Tmp    := DATA * 65536;);
      DATA[45]-> RWORD(DI11:= DATA + Tmp;
                       IF (DI11> 1000000) THEN OF11:=1; ENDIF;
                       );
      DATA[47]-> RWORD(Tmp    := DATA * 65536;);
      DATA[49]-> RWORD(DI12:= DATA + Tmp;
                       IF (DI12> 1000000) THEN OF12:=1; ENDIF;
                       );
      DATA[51]-> RWORD(Tmp    := DATA * 65536;);
      DATA[53]-> RWORD(DI13:= DATA + Tmp;
                       IF (DI13> 1000000) THEN OF13:=1; ENDIF;
                       );
      DATA[55]-> RWORD(Tmp    := DATA * 65536;);
      DATA[57]-> RWORD(DI14:= DATA + Tmp;
                       IF (DI14> 1000000) THEN OF14:=1; ENDIF;
                       );
      DATA[59]-> RWORD(Tmp    := DATA * 65536;);
      DATA[61]-> RWORD(DI15:= DATA + Tmp;
                       IF (DI15> 1000000) THEN OF15:=1; ENDIF;
                       );
      DATA[63]-> RWORD(Tmp    := DATA * 65536;);
      DATA[65]-> RWORD(DI16:= DATA + Tmp;
                       IF (DI16> 1000000) THEN OF16:=1; ENDIF;
                       Updated := 1;
                       );

    TIMEOUT 500

  END;

  % This telegram will reset the counters at 1 000 000 and set the input filter
  TELEGRAM CheckOverflow NAMED "Check overflow" IS
    QUESTION
      DATA[0] := BYTE(Id);
      DATA[1] := HEX(10); % Kommando 10 Write multiple registers
      DATA[2] <- RWORD(         % Register adress
        IF (Started = 0) THEN
          DATA      := 100;     % Counter Mode address, 40101 = Input filter
          CntUpdate := 0;
          Started   := 1;
        ELSIF OF1 THEN 
          DATA      := 2;       % Counter register address
          CntUpdate := 1;
          CntValue  := DI1 - 1000000;
          OF1       := 0;
        ELSIF OF2 THEN
          DATA      := 4;
          CntUpdate := 1;
          CntValue  := DI2 - 1000000;
          OF2       := 0;
        ELSIF OF3 THEN
          DATA      := 6;
          CntUpdate := 1;
          CntValue  := DI3 - 1000000;
          OF3       := 0;
        ELSIF OF4 THEN
          DATA      := 8;
          CntUpdate := 1;
          CntValue  := DI4 - 1000000;
          OF4       := 0;
        ELSIF OF5 THEN
          DATA      := 10;
          CntUpdate := 1;
          CntValue  := DI5 - 1000000;
          OF5       := 0;
        ELSIF OF6 THEN
          DATA      := 12;
          CntUpdate := 1;
          CntValue  := DI6 - 1000000;
          OF6       := 0;
        ELSIF OF7 THEN
          DATA      := 14;
          CntUpdate := 1;
          CntValue  := DI7 - 1000000;
          OF7       := 0;
        ELSIF OF8 THEN
          DATA      := 16;
          CntUpdate := 1;
          CntValue  := DI8 - 1000000;
          OF8       := 0;
        ELSIF OF9 THEN
          DATA      := 18;
          CntUpdate := 1;
          CntValue  := DI9 - 1000000;
          OF9       := 0;
        ELSIF OF10 THEN
          DATA      := 20;
          CntUpdate := 1;
          CntValue  := DI10 - 1000000;
          OF10      := 0;
        ELSIF OF11 THEN
          DATA      := 22;
          CntUpdate := 1;
          CntValue  := DI11 - 1000000;
          OF11      := 0;
        ELSIF OF12 THEN
          DATA      := 24;
          CntUpdate := 1;
          CntValue  := DI12 - 1000000;
          OF12      := 0;
        ELSIF OF13 THEN
          DATA      := 26;
          CntUpdate := 1;
          CntValue  := DI13 - 1000000;
          OF13      := 0;
        ELSIF OF14 THEN
          DATA      := 28;
          CntUpdate := 1;
          CntValue  := DI14 - 1000000;
          OF14      := 0;
        ELSIF OF15 THEN
          DATA      := 30;
          CntUpdate := 1;
          CntValue  := DI15 - 1000000;
          OF15      := 0;
        ELSIF OF16 THEN
          DATA      := 32;
          CntUpdate := 1;
          CntValue  := DI16 - 1000000;
          OF16      := 0;
        ELSE
          DATA      := 100;           % Counter Mode address, 40101 = Input filter
          CntUpdate := 0;
        ENDIF;
      );
      DATA[4] := RWORD(2);            % Number of registers
      DATA[6] := BYTE(4);             % Number of bytes
      DATA[7] <- RWORD(
        IF CntUpdate THEN DATA := 0;  % Set Counter high = 0
        ELSE              DATA := 1;  % Set Counter mode = 1 Up counting
        ENDIF;
        );
      DATA[9] <- RWORD(
        IF CntUpdate THEN DATA := CntValue;      % Set Counter low with overflow value
        ELSE              DATA := (Filter+9)/10; % Set Input filter (x10ms)
        ENDIF;
        SilenceCnt := 5;
        );

    ANSWER SIZE 8
      DATA[0] = BYTE(Id);
      DATA[1] = HEX(10);

    TIMEOUT 300

  END;

END;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
GROUP ProconCnt OF MAX 10 DEVICE TYPEID 21104 SELECT ALL

  ITERATOR CheckOF
  ALIAS

  BEGIN  
    IF (Updated) THEN
      SEND CheckOverflow;
      Updated := 0;
    ELSIF (SilenceCnt > 0) THEN
      SilenceCnt := SilenceCnt - 1;
      SILENCE CheckOverflow;
    ENDIF;
  END;

END;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ROUTINE ProconCounter
BEGIN
  CALL ProconCnt.CheckOF;
END;

Användarnas noteringar

Du måste vara inloggad för att göra en notering. Bli medlem eller logga in. Vi använder en moderator som godkänner noteringarna innan de visas.