希殿电气技术(上海)有限公司(西门子经销商)

联系人 :康经理(销售工程师)发布


前几天发了一个提问怎么读写1200/1500DB数据块的求答案,没人回答,我查阅了相关的帮助,在博图中编写300/400PLC是支持DB_BLOCK数据类型的,而1200和1500不支持该类型.也就是说在博图中SCL编程针对不同系列的PLC是不一定通用的.这点需要大家注意.以下是博图中的模拟量批量转换的SCL程序给喜欢偷懒的提高销量的同行研究哈,若有什么BUG请告知.该程序通过仿真实验.

本程序比较适合连续AI地址的情况,DB块赋值也较为方便(可采用EXCEL编辑粘贴为原代码)

20170929修改一个BUG:即当通道超出范围报错时,该转换值会使用错误的值更正代码如下


FUNCTION_BLOCK "模拟量转换"

TITLE = 模拟量输入转换

{ S7_Optimized_Access := 'FALSE' }

AUTHOR : EBCLW

FAMILY : EBC

NAME : AI_OUT

VERSION : 1.0

//

// 模拟量输入量程批量转换

//

// Block Parameters

   VAR_INPUT 

      ADDRESS : Int := 512;   // 开始的PIW地址

      NUM : Int := 1;   // 仪表数量即多少个PIW地址

      DATA_NUM : DInt;   // 用于存放数据的量程 偏差设定

      VALUE_NUM : DInt;   // 存放输出结果

   END_VAR


   VAR 

      K1 : Real;

      K2 : Real;

   END_VAR


   VAR_TEMP 

      I : DInt;   // 循环变量

      IW_INT_VAL : Int;

      IW_VAL : Real;

      HI_VAL : Real;

      LI_VAL : Real;

      OF_VAL : Real;

      DIP_VAL : Byte;

      TEMP : Real;

   END_VAR



BEGIN

//###########################################################

//采用FC105相同的计算公式OUT = ((FLOAT (IN) -K1)/(K2-K1)) * (HI_LIM-LO_LIM) + LO_LIM

//增加一个修正偏差公式改为OUT = ((FLOAT (IN) -K1)/(K2-K1)) * (HI_LIM-LO_LIM) + LO_LIM + OFFSET

//循环批量转换循环体

//##########################################################

//参数DB块数据结构

(*

 H:REAL 量程上限设定值

 L:REAL 量程下限设定值

 OF:REAL 修正偏差设定值

 DIP:BYTE双极性设置

   :

   :

   :

*)

//输出参数DB块数据结构

(*

 VALUE:REAL 转换后输出值

 ERR:BYTE   错误值 通道值超出范围即输出0位为1

   :

   :

   :

*)



FOR #I := 1 TO #NUM BY 1 DO

   //读取IW地址以及数据块的参数

   //------------------------------------------

   #IW_INT_VAL := WORD_TO_INT(PEEK_WORD(area := 16#81, dbNumber := 0, byteOffset := #ADDRESS + (#I - 1) * 2));//数据有正负性,必须转换为INT格式

   #IW_VAL := DINT_TO_REAL(INT_TO_DINT(#IW_INT_VAL));

   #HI_VAL :=DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14));

   #LI_VAL := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 4));

   #OF_VAL := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 8));

   #DIP_VAL:=PEEK_BYTE(area := 16#84, dbNumber := #DATA_NUM, byteOffset := (#I - 1) * 14 + 12);

   //-------------------------------------------

    //判断是否是双极性

   //读取数据库参数判断是否是双极性,0为单极性,1为双极性并判断通道值是否溢出

   //-----------------------------------------------------

   IF #DIP_VAL>=16#1 THEN

       //双极性

       #K1 := -27648.0;

       #K2 := 27648.0;

       //读取IW数值通过数值判断数值是否异常若异常则将异常状态写入数据块,异常就给错误字0位写1

       

       IF #IW_INT_VAL <= -27649 OR #IW_INT_VAL >= 27649 THEN

           

           POKE_BOOL(area := 16#84,

                     dbNumber := #VALUE_NUM,

                     byteOffset := (#I - 1) * 6 + 4,

                     bitOffset := 0,

                     value := TRUE);

           //不在量程范围内则读取当前输出的值给TEMP变量

           #TEMP := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6));

           //不在量程范围内输出为0;

          // #TEMP := 0.0;

       ELSE

           POKE_BOOL(area := 16#84,

                     dbNumber := #VALUE_NUM,

                     byteOffset := (#I - 1) * 6 + 4,

                     bitOffset := 0,

                     value := FALSE);

           //若在量程范围内就做量程转换

           //#TEMP := (#IW_VAL - #K1) / (#K2 - #K1) * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;

           //算法优化

           #TEMP := (#IW_VAL +27648.0) /55296.0 * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;

       END_IF;

       

   ELSE

       //单极性

       #K1 := 0.0;

       #K2 := 27648.0;

       //读取IW数值通过数值判断数值是否异常若异常则将异常状态写入数据块,异常就给错误字0位写1

       IF (#IW_INT_VAL >= 27649) OR (#IW_INT_VAL<=-1) THEN

      // IF #IW_INT_VAL<=-1 THEN

           POKE_BOOL(area := 16#84,

                     dbNumber := #VALUE_NUM,

                     byteOffset := (#I - 1) * 6 + 4,

                     bitOffset := 0,

                     value := TRUE);

           //不在量程范围内则读取当前输出的值给TEMP变量

           #TEMP := DWORD_TO_REAL(PEEK_DWORD(area := 16#84, dbNumber := #VALUE_NUM, byteOffset := (#I - 1) * 6));

           //不在量程范围内输出为0;

          // #TEMP := 0.0;

       ELSE

           POKE_BOOL(area := 16#84,

                     dbNumber := #VALUE_NUM,

                     byteOffset := (#I - 1) * 6 + 4,

                     bitOffset := 0,

                     value := FALSE);

           //若在量程范围内就做量程转换

           //#TEMP := (#IW_VAL - #K1) / (#K2 - #K1) * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;

           //算法优化

           #TEMP := #IW_VAL / 27648.0 * (#HI_VAL - #LI_VAL) + #LI_VAL + #OF_VAL;


       END_IF;

 

   END_IF;

   //-------------------------------------------------------

   POKE(area := 16#84,

        

        dbNumber := #VALUE_NUM,

        

        byteOffset := (#I-1)*6,

        

        value := REAL_TO_DWORD(#TEMP));

   

END_FOR;





END_FUNCTION_BLOCK

模拟量输入参数DB块源代码BEGIN赋值代码很好的能在EXCEL中进行编辑,对于大批量的设置参数有很用的

--------------

DATA_BLOCK "模拟量输入参数"

{ S7_Optimized_Access := 'FALSE' }

VERSION : 0.1

NON_RETAIN

   STRUCT 

      CS : Array[0..10] of Struct

         H : Real;

         L : Real;

         OFF : Real;

         DIP : Byte;

      END_STRUCT;

   END_STRUCT;



BEGIN

   CS[0].H := 200.678;

   CS[1].H := 100.0;

   CS[2].H := 100.0;

   CS[3].H := 100.0;

   CS[4].H := 100.0;


END_DATA_BLOCK

-------------------------------------------

模拟量输出DB块源代码 源代码生成块后直接设置数组的数量即可


-----------------------------------

DATA_BLOCK "模拟量输出"

{ S7_Optimized_Access := 'FALSE' }

VERSION : 0.1

NON_RETAIN

   STRUCT 

      OUT : Array[0..10] of Struct

         VALUE : Real;

         ERR : Byte;

      END_STRUCT;

   END_STRUCT;