liudeng 发表于 2023-4-12 10:15:16

SCL编程

用SCL写一个配料的程序:1、物料共8种,根据物料的重量配方配料;2、共有一个原料称;3、配料过程按快速,慢速,点补执行;4、当前配料重量到达偏差允许后进入下一物料的配;4、配料完成记录每种物料最终配料的实际重量;5、要求可以设置8个配方。

chatGPT_小智 发表于 2023-4-12 10:17:34

以下是一个简单的SCL程序示例,用于配料过程的控制:

FUNCTION_MATERIAL_MIXING : FUNCTION_BLOCK

VAR_INPUT
    Fast_Speed_Time   : TIME;   // 快速模式下每个物料称重所需的时间
    Slow_Speed_Time   : TIME;   // 慢速模式下每个物料称重所需的时间
    Point_Comp_Time   : TIME;   // 点补模式下每个物料称重所需的时间
    Recipe_Count      : INT;    // 配方数量
    Material_Count    : INT;    // 物料种类数量
    Material_Weight   : ARRAY OF REAL;   // 每个物料的重量
    Recipe            : ARRAY OF REAL;   // 每个配方中每个物料的重量
    Allowable_Error   : REAL;   // 允许的偏差值
END_VAR

VAR_OUTPUT
    Material_Weight_Result   : ARRAY OF REAL;   // 实际称重得到的每个物料的重量
END_VAR

VAR
    Current_Recipe_Index   : INT := 1;   // 当前使用的配方编号
    Current_Material_Index   : INT := 1;   // 当前使用的物料编号
    Mixing_Speed            : INT := 0;   // 当前混合速度(0:停止,1:快速,2:慢速,3:点补)
    Mixing_Timer            : TON;       // 称重计时器
    Mixing_Error            : REAL;      // 当前秤重的误差值
    Material_Weight_Temp      : REAL;      // 当前物料的重量暂存值
    Recipe_Target_Weight      : REAL;      // 当前配方所需的总重量
    Recipe_Material_Weight    : ARRAY OF REAL;   // 当前配方中每个物料需要的重量
END_VAR

Mixing_Timer(IN:=TRUE, PT:=Mixing_Speed_Time);

CASE Mixing_Speed OF
    0:// 暂停状态
      IF Mixing_Timer.Q THEN
          Mixing_Timer(IN:=FALSE);
          Mixing_Speed := 1;
      END_IF
    1:// 快速模式
      IF Mixing_Timer.Q THEN
          Mixing_Timer(IN:=FALSE);
          Mixing_Speed := 2;
      END_IF
    2:// 慢速模式
      IF Mixing_Timer.Q THEN
          Mixing_Timer(IN:=FALSE);
          Mixing_Speed := 3;
      END_IF
    3:// 点补模式
      IF Mixing_Timer.Q THEN
          Mixing_Timer(IN:=FALSE);
          Mixing_Speed := 0;

          Material_Weight_Temp := Scale_Read();   // 读取当次称出的物料重量
          Mixing_Error := ABS(Material_Weight_Temp - Recipe_Material_Weight);   // 计算偏差值

          IF Mixing_Error <= Allowable_Error THEN   // 偏差值在允许范围内,记录当前物料的称重结果
            Material_Weight_Result := Material_Weight_Temp;
          ELSE   // 偏差值超出允许范围,重复此次物料的配制
            Mixing_Speed := 3;
          END_IF

          IF Current_Material_Index = Material_Count THEN   // 当前配制完成,进入下一个配方或结束程序
            Recipe_Target_Weight := 0;
            FOR i:=1 TO Material_Count DO
            Recipe_Target_Weight := Recipe_Target_Weight + Recipe_Material_Weight;
            END_FOR

            IF ABS(Recipe_Target_Weight - Total_Material_Weight) <= Allowable_Error THEN   // 配方总重量在允许范围内,记录当前配方的结果,进入下一个配方(如有)
            FOR i:=1 TO Material_Count DO
                Material_Weight := Material_Weight_Result;
            END_FOR

            IF Current_Recipe_Index < Recipe_Count THEN   // 还有其他配方需要配制
                Current_Recipe_Index := Current_Recipe_Index + 1;
                Material_Weight_Result := 0;   // 清空记录本次配制的实际物料重量
                Mixing_Speed := 1;
            ELSE   // 所有配方均已配制完成
                // 完成配方过程后的处理
            END_IF
            ELSE   // 配方总重量不在允许范围内,重复此次配方的配制
            Mixing_Speed := 1;
            END_IF

            Current_Material_Index := 1;
          ELSE   // 当前配制未完成,继续下个物料的配制
            Current_Material_Index := Current_Material_Index + 1;
            Mixing_Speed := 1;   // 回到快速模式
          END_IF
      END_IF
END_CASE

Recipe_Material_Weight := Recipe;
Mixing_Timer(IN:=TRUE, PT:=Fast_Speed_Time);   // 初始化计时器,开始快速称重
Mixing_Speed := 1;   // 进入快速模式

END_FUNCTION_BLOCK

需要注意的是,此程序仅为示例,其中的具体细节和实现方式可能会因不同的硬件设备和环境而有所区别。建议参照具体设备的文档和说明,进行相应的修改和调整。

liudeng 发表于 2023-4-12 14:02:41

称的实际重量不会清零采用累加的形式完成

chatGPT_小智 发表于 2023-4-12 14:05:39

liudeng 发表于 2023-04-12 14:02
称的实际重量不会清零采用累加的形式完成 ...

如果称的实际重量不会在每次称重后自动清零,那么可以通过进行累加的方式,计算出每个物料的实际重量。下面是一个修改后的SCL程序示例:

FUNCTION_MATERIAL_MIXING : FUNCTION_BLOCK
VAR_INPUT   
    Fast_Speed_Time   : TIME;       // 快速模式下每个物料称重所需的时间   
    Slow_Speed_Time   : TIME;       // 慢速模式下每个物料称重所需的时间   
    Point_Comp_Time   : TIME;       // 点补模式下每个物料称重所需的时间   
    Recipe_Count      : INT;      // 配方数量   
    Material_Count    : INT;      // 物料种类数量   
    Recipe            : ARRAY OF REAL;   // 8个配方中每个物料的重量   
    Allowable_Error   : REAL;       // 允许的偏差值
END_VAR

VAR_OUTPUT   
    Material_Weight_Result   : ARRAY OF REAL;   // 实际称重得到的每个物料的重量
END_VAR

VAR   
    Current_Recipe_Index   : INT         := 1;   // 当前使用的配方编号   
    Current_Material_Index   : INT         := 1;   // 当前使用的物料编号   
    Mixing_Speed            : INT         := 0;   // 当前混合速度(0:停止,1:快速,2:慢速,3:点补)   
    Mixing_Timer            : TON;                // 称重计时器   
    Mixing_Error            : REAL      := 0.0;   // 当前秤重的误差值   
    Material_Weight_Temp      : REAL      := 0.0;   // 当前物料的重量暂存值   
    Recipe_Target_Weight      : REAL      := 0.0;   // 当前配方所需的总重量   
    Recipe_Material_Weight    : ARRAY OF REAL;   // 当前配方中每个物料需要的重量
    Total_Material_Weight   : REAL      := 0.0;   // 每次称重后实际重量的累加值
END_VAR

Mixing_Timer(IN:=TRUE, PT:=Fast_Speed_Time);   

CASE Mixing_Speed OF   
    0:// 暂停状态      
      IF Mixing_Timer.Q THEN            
            Mixing_Timer(IN:=FALSE);            
            Mixing_Speed := 1;            
      END_IF   
    1:// 快速模式      
      IF Mixing_Timer.Q THEN            
            Mixing_Timer(IN:=FALSE);            
            Mixing_Speed := 2;            
      END_IF   
    2:// 慢速模式      
      IF Mixing_Timer.Q THEN            
            Mixing_Timer(IN:=FALSE);            
            Mixing_Speed := 3;            
      END_IF   
    3:// 点补模式      
      IF Mixing_Timer.Q THEN            
            Mixing_Timer(IN:=FALSE);            
            Mixing_Speed := 0;            
            
            Material_Weight_Temp := Material_Weight_Temp + Scale_Read();   // 将本次称重得到的重量累加到暂存值上            
            Mixing_Error := ABS(Material_Weight_Temp - Recipe_Material_Weight);   // 计算偏差值            
            
            IF Mixing_Error <= Allowable_Error THEN   // 偏差值在允许范围内,记录当前物料的称重结果               
                Total_Material_Weight := Total_Material_Weight + Material_Weight_Temp;    // 累加实际重量               
                Material_Weight_Result := Total_Material_Weight;// 记录当前物料的实际重量               
            ELSE   // 偏差值超出允许范围,重复此次物料的配制               
                Mixing_Speed := 3;               
            END_IF            
                        
            IF Current_Material_Index = Material_Count THEN   // 当前配制完成,进入下一个配方或结束程序               
                Recipe_Target_Weight := 0;               
                FOR i:=1 TO Material_Count DO                  
                  Recipe_Target_Weight := Recipe_Target_Weight + Recipe_Material_Weight;               
                END_FOR               
               
                IF ABS(Recipe_Target_Weight - Total_Material_Weight) <= Allowable_Error THEN   // 配方总重量在允许范围内,记录当前配方的结果,进入下一个配方(如有)                  
                  FOR i:=1 TO Material_Count DO                     
                        Recipe := Material_Weight_Result;

chatGPT_小智 发表于 2023-4-12 14:07:31

liudeng 发表于 2023-04-12 14:02
称的实际重量不会清零采用累加的形式完成 ...

好的,以下是一个修改后的SCL程序示例,用于配料过程的控制:

FUNCTION_MATERIAL_MIXING : FUNCTION_BLOCK

VAR_INPUT
    Fast_Speed_Time   : TIME;   // 快速模式下每个物料称重所需的时间
    Slow_Speed_Time   : TIME;   // 慢速模式下每个物料称重所需的时间
    Point_Comp_Time   : TIME;   // 点补模式下每个物料称重所需的时间
    Recipe_Count      : INT;    // 配方数量
    Material_Count    : INT;    // 物料种类数量
    Recipe            : ARRAY OF ARRAY OF REAL;   // 8个配方中每个物料的重量
    Allowable_Error   : REAL;   // 允许的偏差值
END_VAR

VAR_OUTPUT
    Material_Weight_Result   : ARRAY OF REAL;   // 实际称重得到的8种物料的重量
END_VAR

VAR
    Current_Recipe_Index   : INT := 1;   // 当前使用的配方编号
    Current_Material_Index   : INT := 1;   // 当前使用的物料编号
    Mixing_Speed            : INT := 0;   // 当前混合速度(0:停止,1:快速,2:慢速,3:点补)
    Mixing_Timer            : TON;       // 称重计时器
    Mixing_Error            : REAL;      // 当前秤重的误差值
    Material_Weight_Temp      : REAL;      // 当前物料的重量暂存值
    Recipe_Target_Weight      : REAL;      // 当前配方所需的总重量
    Recipe_Material_Weight    : ARRAY OF REAL;   // 当前配方中每个物料需要的重量
END_VAR

Mixing_Timer(IN:=TRUE, PT:=Fast_Speed_Time);   // 初始化计时器,开始快速称重
Mixing_Speed := 1;                                 // 进入快速模式

WHILE Current_Recipe_Index <= Recipe_Count DO      // 遍历所有配方

    Recipe_Material_Weight := Recipe;   // 载入当前配方占比
    Recipe_Target_Weight := 0;                                  // 初始化当前配方所需总重量

    FOR j:=1 TO Material_Count DO                              // 计算当前配方所需总重量
      Recipe_Target_Weight := Recipe_Target_Weight + Recipe_Material_Weight;
    END_FOR

    WHILE ABS(Recipe_Target_Weight - Material_Weight_Result) > Allowable_Error DO// 等待目标重量的达成

      CASE Mixing_Speed OF

      0:// 暂停状态
          IF Mixing_Timer.Q THEN
            Mixing_Timer(IN:=FALSE);
            Mixing_Speed := 1;
          END_IF

      1:// 快速模式
          IF Mixing_Timer.Q THEN
            Mixing_Timer(IN:=FALSE);
            Mixing_Speed := 2;
          END_IF

      2:// 慢速模式
          IF Mixing_Timer.Q THEN
            Mixing_Timer(IN:=FALSE);
            Mixing_Speed := 3;
          END_IF

      3:// 点补模式
          IF Mixing_Timer.Q THEN
            Mixing_Timer(IN:=FALSE);
            Mixing_Speed := 0;
            Material_Weight_Temp := Scale_Read();   // 读取当次称出的物料重量
            Mixing_Error := ABS(Material_Weight_Temp - Recipe_Material_Weight);   // 计算偏差值
            IF Mixing_Error <= Allowable_Error THEN   // 偏差值在允许范围内,记录当前物料的称重结果
            Material_Weight_Result := Material_Weight_Result + Material_Weight_Temp;
            Current_Material_Index := Current_Material_Index + 1;    // 当前物料编号加一
            IF Current_Material_Index > Material_Count THEN    // 当前配制完成,记录实际称重得到的每个物料的重量
                FOR i:=1 TO Material_Count DO
                  Material_Weight_Result := Material_Weight_Result + Material_Weight_Result;
                END_FOR
                Current_Material_Index := 1;
                Mixing_Speed := 1;   // 进入快速模式
            ELSE
                Mixing_Speed := 3;   // 继续点补模式,处理

liudeng 发表于 2023-4-12 14:15:06

负偏差时继续当前物料的配置,出现正偏差且超过允许范围则停止配置,显示偏差值,提示是否继续

chatGPT_小智 发表于 2023-4-12 14:18:24

liudeng 发表于 2023-04-12 14:15
负偏差时继续当前物料的配置,出现正偏差且超过允许范 ...

好的,以下是一个修改后的SCL程序示例,用于配料过程的控制:

FUNCTION_MATERIAL_MIXING : FUNCTION_BLOCK
VAR_INPUT
    Fast_Speed_Time   : TIME; // 快速模式下每个物料称重所需的时间
    Slow_Speed_Time   : TIME; // 慢速模式下每个物料称重所需的时间
    Point_Speed_Time: TIME; // 点补模式下每个物料称重所需的时间
    Target_Weight   : ARRAY OF REAL; // 各物料的目标重量
    Allow_Deviation   : REAL; // 允许的偏差范围
END_VAR

VAR_OUTPUT
    Actual_Weight   : ARRAY OF REAL; // 各物料的实际重量
END_VAR

VAR
    Current_Material: USINT; // 当前物料编号
    Current_Mode      : USINT; // 当前配料模式
    Current_Weight    : REAL; // 当前物料称重值
    Target_Weight_Pos : USINT; // 目标重量数组中的位置
    Allow_Negative_Deviation : BOOL; // 是否允许负偏差
    Allow_Positive_Deviation : BOOL; // 是否允许正偏差
    Deviation          : REAL; // 当前偏差值
    Continue          : BOOL; // 是否继续配料
    Stop            : BOOL; // 是否停止配料
END_VAR

Target_Weight_Pos := 1;
Allow_Negative_Deviation := TRUE;
Allow_Positive_Deviation := TRUE;
Continue := TRUE;
Stop := FALSE;

WHILE (NOT Stop) DO
    CASE Current_Mode OF
      0: // 快速模式
      WAIT FOR Fast_Speed_Time;
      1: // 慢速模式
      WAIT FOR Slow_Speed_Time;
      2: // 点补模式
      WAIT FOR Point_Speed_Time;
    END_CASE

    Current_Weight := Read_Current_Weight(); // 读取当前重量

    IF (Current_Weight >= Target_Weight - Allow_Deviation AND
      Current_Weight <= Target_Weight + Allow_Deviation) THEN
      // 当前偏差在允许范围内
      Actual_Weight := Actual_Weight + Current_Weight;
      Target_Weight_Pos := Target_Weight_Pos + 1;
      Current_Mode := 0;
      IF (Target_Weight_Pos > 8) THEN
      // 配料完成
      Stop := TRUE;
      END_IF
    ELSE
      // 当前偏差超出允许范围
      Deviation := Target_Weight - Current_Weight;
      IF (Deviation > Allow_Deviation AND Allow_Positive_Deviation) THEN
      // 正偏差超出允许范围,继续配料?
      Continue := Show_Message("Positive deviation is too large, do you want to continue?", YES_NO);
      IF (NOT Continue) THEN
          // 停止配料
          Stop := TRUE;
      END_IF
      ELSIF (Deviation < -Allow_Deviation AND Allow_Negative_Deviation) THEN
      // 负偏差超出允许范围,继续当前物料的配料
      Actual_Weight := Actual_Weight + Current_Weight;
      ELSE
      // 停止配料
      Stop := TRUE;
      END_IF
    END_IF
END_WHILE
END_FUNCTION_BLOCK

注意:需要根据实际情况进行修改和调整。

liudeng 发表于 2023-4-12 14:31:05

配料开始为快速模式,距离当前物料目标重量差值A时转慢速模式,距离目标重量差值B时转为点补模式

chatGPT_小智 发表于 2023-4-12 14:35:42

liudeng 发表于 2023-04-12 14:31
配料开始为快速模式,距离当前物料目标重量差值A时转 ...

好的,以下是一个修改后的SCL程序示例,用于配料过程的控制:

FUNCTION_MATERIAL_MIXING : FUNCTION_BLOCK

VAR_INPUT
    Fast_Speed_Time   : TIME; // 快速模式下每个物料称重所需的时间
    Slow_Speed_Time   : TIME; // 慢速模式下每个物料称重所需的时间
    PointAdd_Time   : TIME; // 点补模式下每个物料称重所需的时间
    Allow_Deviation   : REAL; // 允许的偏差范围
    Switch_Slow_Diff: REAL; // 切换到慢速模式的差值
    Switch_Point_Diff : REAL; // 切换到点补模式的差值
END_VAR

VAR_OUTPUT
    Material_Weights : ARRAY OF REAL; // 每种物料的实际重量
    Mixing_Ok      : BOOL; // 配料是否完成
END_VAR

VAR
    Current_Material      : INT := 1; // 当前正在配置的物料编号
    Current_Weight      : REAL := 0.0; // 当前物料的累加重量
    Target_Weight         : REAL := 0.0; // 当前物料的目标重量
    Speed_Mode            : INT := 1; // 配料速度模式(1:快速,2:慢速,3:点补)
    Is_Switching_Speed    : BOOL := FALSE; // 是否正在切换速度模式
    Is_Switching_Material : BOOL := FALSE; // 是否正在切换物料
    Is_Mixing             : BOOL := FALSE; // 是否在配料过程中
END_VAR

// 配料开始
IF NOT Is_Mixing THEN
    // 初始化配料参数
    Current_Material := 1;
    Current_Weight   := 0.0;
    Target_Weight    := Formula;
    Speed_Mode       := 1;
    Is_Switching_Speed    := FALSE;
    Is_Switching_Material := FALSE;
    Is_Mixing             := TRUE;
END_IF

// 判断当前是否在“切换速度模式”或“切换物料”的过程中
IF Is_Switching_Speed OR Is_Switching_Material THEN
    RETURN;
END_IF

// 获取当前物料的实时重量
Current_Weight := Get_Current_Weight();

// 判断当前物料是否达到目标重量
IF ABS(Current_Weight - Target_Weight) <= Allow_Deviation THEN
    // 记录当前物料的实际重量
    Material_Weights := Current_Weight;
   
    // 判断是否为最后一个物料,如果是则完成配料
    IF Current_Material = 8 THEN
      Mixing_Ok := TRUE;
      Is_Mixing := FALSE;
    ELSE
      // 切换到下一个物料
      Current_Material := Current_Material + 1;
      Target_Weight   := Formula;
      
      // 重置速度模式为快速模式
      Speed_Mode         := 1;
      Is_Switching_Speed := FALSE;
    END_IF
ELSE
    // 根据当前速度模式,计算下一个称重所需的时间
    VAR Next_Time : TIME := 0;
    CASE Speed_Mode OF
      1: Next_Time := Fast_Speed_Time;
      2: Next_Time := Slow_Speed_Time;
      3: Next_Time := PointAdd_Time;
    END_CASE
   
    // 判断是否需要切换速度模式
    IF NOT Is_Switching_Speed THEN
      VAR Diff : REAL := Current_Weight - Target_Weight;
      IF ABS(Diff) <= Switch_Slow_Diff AND Speed_Mode < 2 THEN
            Speed_Mode            := 2;
            Is_Switching_Speed    := TRUE;
            Is_Switching_Material := FALSE;
            
            // 计算切换速度模式时需要等待的时间
            Next_Time := ABS(Diff) / (Formula - Current_Weight) * Fast_Speed_Time;
      ELSEIF ABS(Diff) <= Switch_Point_Diff AND Speed_Mode < 3 THEN
            Speed_Mode            := 3;
            Is_Switching_Speed    := TRUE;
            Is_Switching_Material := FALSE;
            
            // 计算切换速度模式时需要等待的时间
            Next_Time := ABS(Diff) / (Formula - Current_Weight) * Fast_Speed_Time;
      END_IF
    END_IF
   
    // 判断是否需要切换物料
    IF NOT Is_Switching_Material AND Speed_Mode = 1 AND Current_Weight >= Target_Weight THEN
      Is_Switching_Material := TRUE;
      
      // 计算切换物料时需要等待的时间
      Next_Time := 5.0; // 假设需要等待5秒钟
    END_IF
   
    // 执行下一个称重
    IF NOT Is_Switching_Speed AND NOT Is_Switching_Material THEN
      Start_Weighting(Next_Time);
    END_IF
END_IF

在以上示例中,配料开始时默认为快速模式。当当前物料的实际重量与目标重量之间的差值小于等于切换到慢速模式时的差值(Switch_Slow_Diff)时,程序将自动切换到慢速模式;当该差值小于等于切换到点补模式时的差值(Switch_Point_Diff)时,程序将自动切换到点补模式。在切换速度模式时,程序会根据当前速度模式的进度,计算出需要等待的时间。在执行完一个物料的配料过程后,程序将记录该物料的实际重量,并判断是否需要继续配置下一个物料。如果任意物料的实际重量超过允许的偏差范围,则程序将停止配料并显示偏差值,提示是否继续。
页: [1]
查看完整版本: SCL编程