Obsidean_VM/03-VM/44 - 98050 - Fiera/Especifica General.md

24 KiB

1. System Architecture

1.1 Call Structure

OB1
├── FC_Ttop_Run
│   ├── FC_Table_Motor_M316() → "DB Motor M316"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M317() → "DB Motor M317"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M318() → "DB Motor M318"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M319() → "DB Motor M319"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M328() → "DB Motor M328"(FB_Motors_Manage)  // Channel 1
│   ├── FC_Table_Motor_M329() → "DB Motor M329"(FB_Motors_Manage)  // Channel 2
│   ├── FC_Table_Motor_M330() → "DB Motor M330"(FB_Motors_Manage)  // Channel 3
│   ├── FC_Table_Motor_M331() → "DB Motor M331"(FB_Motors_Manage)  // Channel 4
│   ├── FC_Table_Motor_M332() → "DB Motor M332"(FB_Motors_Manage)  // Channel 5 (center)
│   ├── FC_Table_Motor_M333() → "DB Motor M333"(FB_Motors_Manage)  // Channel 6
│   ├── FC_Table_Motor_M334() → "DB Motor M334"(FB_Motors_Manage)  // Channel 7
│   ├── FC_Table_Motor_M335() → "DB Motor M335"(FB_Motors_Manage)  // Channel 8
│   ├── FC_Table_Motor_M336() → "DB Motor M336"(FB_Motors_Manage)  // Channel 9
│   ├── FC_Table_Motor_M340() → "DB Motor M340"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M341() → "DB Motor M341"(FB_Motors_Manage)
│   ├── FC_Table_Motor_M342() → "DB Motor M342"(FB_Motors_Manage)
│   └── FC_Table_Motor_M343() → "DB Motor M343"(FB_Motors_Manage)
└── FC_Table_Devices
    └── "DB Table"(FB_Table)

1.2 Component Mapping

  • M316, M317: Input feeders (left, right)
  • M318: Format change input feeders
  • M319: Input selector
  • M328-M336: Channels 1-9 (1=leftmost, 5=center/bypass, 9=rightmost)
  • M340: Output selector
  • M341, M342: Output feeders (left, right)
  • M343: Format change output feeders

2. Data Structures

2.1 Format Data Structure

TYPE T_Format_Data:
STRUCT
  Format_Number : Int;              // Format number (1 or 2)
  Accumulation_Side : Int;          // 1=Left (channels 1-4), 2=Right (channels 6-9)
  Bottle_Dimension_mm : Real;       // Bottle dimension in mm
  Max_Speed_mm_min : Real;          // Maximum speed in mm/min
  Target_Channels : Array[1..4] of Int;  // Channels to use for this format
END_STRUCT;

2.2 External Exchange Database

DB_ATable_Exchange:
STRUCT
  // === INPUT SIGNALS (from external systems) ===
  IN : STRUCT
    // From Ring/Divider
    Ring_Input_Product_Available : Bool;    // Product available at input
    Ring_Output_Request : Bool;             // Ring requests product output
    Ring_Empty_And_Auto : Bool;             // Ring empty and divider in auto
    Ring_Bypass_Speed_Request : Real;       // Requested bypass speed
    
    // Commands
    Load_Request : Bool;                    // Request to start loading
    Format_Change_Command : Bool;           // Format change command from HMI
    Unload_Enable : Bool;                   // Enable automatic unload after format change
    
    // System status
    System_Auto_Mode : Bool;                // System in automatic mode
    Emergency_Stop : Bool;                  // Emergency stop signal
  END_STRUCT;
  
  // === OUTPUT SIGNALS (to external systems) ===
  OUT : STRUCT
    // To Ring/Divider  
    Input_Request_Product : Bool;           // Table ready and requesting input
    Format_Change_Allowed : Bool;           // Loading complete and ring empty
    Output_Speed_Reference : Real;          // Speed reference for output motor
    Table_In_Bypass : Bool;                 // Table in bypass mode
    
    // Status
    Table_State : Int;                      // Current table state
    Current_Format : Int;                   // Currently stored format
    Table_Ready : Bool;                     // Table ready for operation
    Loading_Complete : Bool;                // Loading sequence complete
    Unloading_Complete : Bool;              // Unloading sequence complete
  END_STRUCT;
END_STRUCT;

2.3 Table States

CONST
  TABLE_STATE_STOPPED : Int := 0;
  TABLE_STATE_LOADING : Int := 1;
  TABLE_STATE_BYPASS : Int := 2;
  TABLE_STATE_UNLOADING : Int := 3;
  TABLE_STATE_ERROR : Int := 4;
END_CONST;

3. Main Function Block - FB_Table

3.1 Interface

FB_Table:
VAR_INPUT
  Enable : Bool;                           // Table enable
  Target_Format : Int;                     // Target format (1 or 2)
  Manual_Mode : Bool;                      // Manual operation mode
END_VAR

VAR_IN_OUT
  // Motor structure references (pointers)
  Motor_M316 : UDT_Motor_Manage;          // Input feeder left
  Motor_M317 : UDT_Motor_Manage;          // Input feeder right
  Motor_M318 : UDT_Motor_Manage;          // Format change input
  Motor_M319 : UDT_Motor_Manage;          // Input selector
  Motor_M328 : UDT_Motor_Manage;          // Channel 1
  Motor_M329 : UDT_Motor_Manage;          // Channel 2
  Motor_M330 : UDT_Motor_Manage;          // Channel 3
  Motor_M331 : UDT_Motor_Manage;          // Channel 4
  Motor_M332 : UDT_Motor_Manage;          // Channel 5 (center)
  Motor_M333 : UDT_Motor_Manage;          // Channel 6
  Motor_M334 : UDT_Motor_Manage;          // Channel 7
  Motor_M335 : UDT_Motor_Manage;          // Channel 8
  Motor_M336 : UDT_Motor_Manage;          // Channel 9
  Motor_M340 : UDT_Motor_Manage;          // Output selector
  Motor_M341 : UDT_Motor_Manage;          // Output feeder left
  Motor_M342 : UDT_Motor_Manage;          // Output feeder right
  Motor_M343 : UDT_Motor_Manage;          // Format change output
  
  Exchange : DB_ATable_Exchange;          // External communication
END_VAR

VAR_OUTPUT
  Table_State : Int;                      // Current state
  Error_Code : Word;                      // Error code
  Diagnostics : T_Table_Diagnostics;     // Diagnostic information
END_VAR

VAR_STAT
  // === COMMAND STRUCTURE (Read by FC motors) ===
  Status : STRUCT
    // Input feeders
    Input_Feeders_Enable : Bool;
    Input_Feeders_Speed_mm_min : Real;
    Input_Feeders_Stop_After_Bottle : Bool;
    
    // Output feeders  
    Output_Feeders_Enable : Bool;
    Output_Feeders_Speed_mm_min : Real;
    Output_Feeders_Stop_After_Bottle : Bool;
    
    // Input selector
    Input_Selector_Enable : Bool;
    Input_Selector_Target_Channel : Int;
    Input_Selector_Positioning_Mode : Bool;
    
    // Output selector
    Output_Selector_Enable : Bool;
    Output_Selector_Target_Channel : Int;
    Output_Selector_Positioning_Mode : Bool;
    
    // Channels
    Channel_Enable : Array[1..9] of Bool;
    Channel_Speed_mm_min : Array[1..9] of Real;
    
    // Format change motors
    Format_Change_Input_Enable : Bool;
    Format_Change_Input_Target_mm : Real;
    Format_Change_Output_Enable : Bool;
    Format_Change_Output_Target_mm : Real;
  END_STRUCT;
  
  // === INTERNAL LOGIC VARIABLES ===
  Current_State : Int;
  Previous_State : Int;
  Loading_Step : Int;
  Unloading_Step : Int;
  Current_Loading_Channel : Int;
  Current_Unloading_Channel : Int;
  
  // Format configuration
  Format_Data : Array[1..2] of T_Format_Data;
  Current_Format_Stored : Int;
  
  // Timers
  State_Timer : TON;
  Operation_Timeout : TON;
  
  // Area management instances
  Area_Input_Selector : FB_Area_Management;
  Area_Channel : Array[1..9] of FB_Area_Management;
  Area_Output_Selector : FB_Area_Management;
  
  // Virtual encoders for position tracking
  Encoder_M332 : FB_Virtual_Encoder;      // Center channel for bypass tracking
  Encoder_Input_Selector : FB_Virtual_Encoder;
  Encoder_Output_Selector : FB_Virtual_Encoder;
END_VAR

3.2 Main Logic (Pseudocode)

// === STATE MACHINE MANAGEMENT ===
CASE Current_State OF
  TABLE_STATE_STOPPED:
    IF Enable AND Exchange.IN.System_Auto_Mode THEN
      IF Exchange.IN.Load_Request THEN
        Current_State := TABLE_STATE_LOADING;
        Loading_Step := 1;
      ELSIF Exchange.IN.Ring_Output_Request AND (Current_Format_Stored > 0) THEN
        Current_State := TABLE_STATE_UNLOADING;
        Unloading_Step := 1;
      END_IF;
    END_IF;
    
  TABLE_STATE_LOADING:
    Execute_Loading_Sequence();
    IF Loading_Complete THEN
      Current_State := TABLE_STATE_BYPASS;
      Exchange.OUT.Loading_Complete := TRUE;
    END_IF;
    
  TABLE_STATE_BYPASS:
    Execute_Bypass_Mode();
    IF Exchange.IN.Format_Change_Command AND Exchange.IN.Ring_Empty_And_Auto THEN
      Current_State := TABLE_STATE_UNLOADING;
      Unloading_Step := 1;
    END_IF;
    
  TABLE_STATE_UNLOADING:
    Execute_Unloading_Sequence();
    IF Unloading_Complete THEN
      Current_State := TABLE_STATE_BYPASS;
      Exchange.OUT.Unloading_Complete := TRUE;
      Current_Format_Stored := 0;
    END_IF;
    
  TABLE_STATE_ERROR:
    Execute_Error_Recovery();
END_CASE;

// === UPDATE EXTERNAL SIGNALS ===
Exchange.OUT.Table_State := Current_State;
Exchange.OUT.Current_Format := Current_Format_Stored;
Exchange.OUT.Table_Ready := (Current_State <> TABLE_STATE_ERROR);
Exchange.OUT.Format_Change_Allowed := (Current_State = TABLE_STATE_BYPASS) AND 
                                      (Current_Format_Stored > 0) AND 
                                      Exchange.IN.Ring_Empty_And_Auto;

// === AREA MANAGEMENT UPDATES ===
FOR i := 1 TO 9 DO
  Area_Channel[i](
    Motor := Get_Channel_Motor_Reference(i),
    Enable := Status.Channel_Enable[i],
    Area_Length_mm := Get_Channel_Length(i),
    Bottle_Length_mm := Format_Data[Target_Format].Bottle_Dimension_mm
  );
END_FOR;

4. Loading Sequence Logic

4.1 Loading Sequence Steps

PROCEDURE Execute_Loading_Sequence:
VAR
  Target_Channels : Array[1..4] of Int;
  Current_Channel : Int;
  Channel_Index : Int;
BEGIN
  // Get target channels for current format
  Target_Channels := Get_Target_Channels_For_Format(Target_Format);
  
  CASE Loading_Step OF
    1: // Initialize loading
      Current_Loading_Channel := Get_Outermost_Channel(Target_Format);
      Channel_Index := 1;
      Position_Input_Selector(Target_Channels[Channel_Index]);
      Loading_Step := 2;
      
    2: // Wait for selector positioning
      IF Input_Selector_In_Position THEN
        Enable_Channel_Motors_For_Loading(Current_Loading_Channel);
        Enable_Input_Feeders();
        Loading_Step := 3;
      END_IF;
      
    3: // Load current channel
      IF Channel_Loading_Complete(Current_Loading_Channel) THEN
        Disable_Input_Feeders();
        Channel_Index := Channel_Index + 1;
        IF Channel_Index <= 4 THEN
          Current_Loading_Channel := Target_Channels[Channel_Index];
          Position_Input_Selector(Current_Loading_Channel);
          Loading_Step := 2;
        ELSE
          Loading_Step := 4; // All channels loaded
        END_IF;
      END_IF;
      
    4: // Loading complete
      Disable_All_Channel_Motors();
      Position_Selectors_To_Bypass();
      Current_Format_Stored := Target_Format;
      Loading_Complete := TRUE;
  END_CASE;
END_PROCEDURE;

FUNCTION Get_Target_Channels_For_Format(Format : Int) : Array[1..4] of Int:
BEGIN
  IF Format_Data[Format].Accumulation_Side = 1 THEN // Left side
    RETURN [1, 2, 3, 4]; // Load from outside to inside
  ELSE // Right side  
    RETURN [9, 8, 7, 6]; // Load from outside to inside
  END_IF;
END_FUNCTION;

FUNCTION Get_Outermost_Channel(Format : Int) : Int:
BEGIN
  IF Format_Data[Format].Accumulation_Side = 1 THEN
    RETURN 1; // Leftmost channel
  ELSE
    RETURN 9; // Rightmost channel  
  END_IF;
END_FUNCTION;

PROCEDURE Enable_Channel_Motors_For_Loading(Target_Channel : Int):
BEGIN
  // Enable all channels from center to target channel
  FOR i := 5 TO Target_Channel DO // or FROM Target_Channel TO 5
    Status.Channel_Enable[i] := TRUE;
    Status.Channel_Speed_mm_min[i] := Format_Data[Target_Format].Max_Speed_mm_min;
  END_FOR;
END_PROCEDURE;

5. Unloading Sequence Logic

5.1 Unloading Sequence Steps

PROCEDURE Execute_Unloading_Sequence:
VAR
  Stored_Channels : Array[1..4] of Int;
  Current_Channel : Int;
  Channel_Index : Int;
BEGIN
  // Get channels where current format is stored
  Stored_Channels := Get_Target_Channels_For_Format(Current_Format_Stored);
  
  CASE Unloading_Step OF
    1: // Initialize unloading - start from innermost channel
      Channel_Index := 4; // Start from innermost
      Current_Unloading_Channel := Stored_Channels[Channel_Index];
      Position_Output_Selector(Current_Unloading_Channel);
      Unloading_Step := 2;
      
    2: // Wait for selector positioning
      IF Output_Selector_In_Position THEN
        Enable_Channel_Motors_For_Unloading(Current_Unloading_Channel);
        Enable_Output_Feeders();
        Unloading_Step := 3;
      END_IF;
      
    3: // Unload current channel
      IF Channel_Unloading_Complete(Current_Unloading_Channel) THEN
        Disable_Output_Feeders();
        Channel_Index := Channel_Index - 1;
        IF Channel_Index >= 1 THEN
          Current_Unloading_Channel := Stored_Channels[Channel_Index];
          Position_Output_Selector(Current_Unloading_Channel);
          Unloading_Step := 2;
        ELSE
          Unloading_Step := 4; // All channels unloaded
        END_IF;
      END_IF;
      
    4: // Unloading complete
      Disable_All_Channel_Motors();
      Position_Selectors_To_Bypass();
      Unloading_Complete := TRUE;
  END_CASE;
END_PROCEDURE;

PROCEDURE Enable_Channel_Motors_For_Unloading(Target_Channel : Int):
BEGIN
  // Enable all channels from target channel to center
  FOR i := Target_Channel TO 5 DO // or FROM 5 TO Target_Channel
    Status.Channel_Enable[i] := TRUE;
    Status.Channel_Speed_mm_min[i] := Format_Data[Current_Format_Stored].Max_Speed_mm_min;
  END_FOR;
END_PROCEDURE;

6. Bypass Mode Logic

6.1 Bypass Operation

PROCEDURE Execute_Bypass_Mode:
BEGIN
  // Enable only center channel for bypass
  Status.Channel_Enable[5] := TRUE;
  Status.Channel_Speed_mm_min[5] := Exchange.IN.Ring_Bypass_Speed_Request;
  
  // Disable all other channels
  FOR i := 1 TO 9 DO
    IF i <> 5 THEN
      Status.Channel_Enable[i] := FALSE;
    END_IF;
  END_FOR;
  
  // Position selectors to bypass (channel 5)
  Status.Input_Selector_Target_Channel := 5;
  Status.Output_Selector_Target_Channel := 5;
  Status.Input_Selector_Enable := TRUE;
  Status.Output_Selector_Enable := TRUE;
  
  // Update external signals
  Exchange.OUT.Table_In_Bypass := TRUE;
  Exchange.OUT.Output_Speed_Reference := Exchange.IN.Ring_Bypass_Speed_Request;
  Exchange.OUT.Input_Request_Product := Exchange.IN.Ring_Input_Product_Available;
END_PROCEDURE;

7. Auxiliary Function Blocks

7.1 FB_Virtual_Encoder

FB_Virtual_Encoder:
VAR_IN_OUT
  Motor : UDT_Motor_Manage;               // Motor structure reference
END_VAR

VAR_INPUT
  Enable : Bool;                          // Enable calculation
  Ratio_Hz_to_mm_min : Real;             // Conversion factor Hz to mm/min
  Reset_Position : Bool;                  // Reset total position
END_VAR

VAR_OUTPUT
  Displacement_mm : Real;                 // Displacement since last call
  Current_Speed_mm_min : Real;           // Current speed in mm/min
  Total_Distance_mm : Real;              // Total accumulated distance
  Motor_Running : Bool;                   // Motor running status
END_VAR

VAR_STAT
  Last_Frequency_Hz : Real;
  Last_Scan_Time : Time;
  Position_Accumulated : Real;
END_VAR

// Pseudocode:
BEGIN
  IF Enable THEN
    Current_Frequency := Read_Motor_Frequency(Motor);
    Current_Time := Get_System_Time();
    
    IF First_Scan THEN
      Last_Frequency_Hz := Current_Frequency;
      Last_Scan_Time := Current_Time;
    ELSE
      Time_Delta := Current_Time - Last_Scan_Time;
      Avg_Frequency := (Current_Frequency + Last_Frequency_Hz) / 2;
      Speed_mm_min := Avg_Frequency * Ratio_Hz_to_mm_min;
      Displacement_mm := Speed_mm_min * Time_Delta_In_Minutes;
      
      IF NOT Reset_Position THEN
        Total_Distance_mm := Total_Distance_mm + Displacement_mm;
      ELSE
        Total_Distance_mm := 0;
      END_IF;
      
      Last_Frequency_Hz := Current_Frequency;
      Last_Scan_Time := Current_Time;
    END_IF;
    
    Current_Speed_mm_min := Current_Frequency * Ratio_Hz_to_mm_min;
    Motor_Running := Motor.STATUS_RUN;
  ELSE
    Displacement_mm := 0;
    Current_Speed_mm_min := 0;
  END_IF;
END_FUNCTION_BLOCK;

7.2 FB_Area_Management

FB_Area_Management:
VAR_IN_OUT
  Motor : UDT_Motor_Manage;               // Motor of this area
END_VAR

VAR_INPUT
  Enable : Bool;                          // Area enable
  Area_Length_mm : Real;                  // Total area length
  Bottle_Length_mm : Real;                // Bottle dimension
  Photocell_Pulse : Bool;                 // Entry photocell pulse
  Reset_Bottles : Bool;                   // Reset bottle tracking
END_VAR

VAR_OUTPUT
  First_Bottle_Position : Real;           // Position of first bottle
  Last_Bottle_Position : Real;            // Position of last bottle
  Area_Empty : Bool;                      // Area completely empty
  Bottles_In_Initial_Zone : Bool;         // Bottles in initial zone
  Bottles_In_Final_Zone : Bool;           // Bottles in final zone
  Bottle_Count : Int;                     // Number of bottles in area
END_VAR

VAR_STAT
  Virtual_Encoder : FB_Virtual_Encoder;
  Bottle_Positions : Array[1..50] of Real; // Track up to 50 bottles
  Active_Bottles : Int;
  Photocell_Pulse_Edge : R_TRIG;
END_VAR

// Pseudocode:
BEGIN
  Virtual_Encoder(
    Motor := Motor,
    Enable := Enable,
    Ratio_Hz_to_mm_min := Calculate_Area_Ratio()
  );
  
  // Detect new bottle entry
  Photocell_Pulse_Edge(CLK := Photocell_Pulse);
  IF Photocell_Pulse_Edge.Q THEN
    Add_New_Bottle_To_Tracking();
  END_IF;
  
  // Update all bottle positions
  FOR i := 1 TO Active_Bottles DO
    Bottle_Positions[i] := Bottle_Positions[i] - Virtual_Encoder.Displacement_mm;
    
    // Remove bottles that have exited the area
    IF Bottle_Positions[i] <= 0 THEN
      Remove_Bottle_From_Tracking(i);
    END_IF;
  END_FOR;
  
  // Calculate outputs
  IF Active_Bottles = 0 THEN
    Area_Empty := TRUE;
    First_Bottle_Position := 0;
    Last_Bottle_Position := 0;
  ELSE
    Area_Empty := FALSE;
    First_Bottle_Position := Find_Minimum_Position();
    Last_Bottle_Position := Find_Maximum_Position();
  END_IF;
  
  Bottles_In_Initial_Zone := Check_Bottles_In_Zone(Area_Length_mm * 0.8, Area_Length_mm);
  Bottles_In_Final_Zone := Check_Bottles_In_Zone(0, Area_Length_mm * 0.2);
  Bottle_Count := Active_Bottles;
END_FUNCTION_BLOCK;

8. Motor-Specific Function Examples

8.1 FC_Table_Motor_M316 (Input Feeder Left)

FC_Table_Motor_M316:
VAR_IN_OUT
  Motor : UDT_Motor_Manage;
  Table_Status : T_Table_Status_Commands;   // Reference to FB_Table.Status
END_VAR

// Pseudocode:
BEGIN
  // === MOTOR CONFIGURATION ===
  Motor.CFG_VFD := TRUE;
  Motor.CFG_PN := TRUE;
  Motor.CFG_Inverter_Type := Inverter_Type_MINIMOTOR;
  Motor.CFG_Min_Speed_Hz := 10;
  Motor.CFG_Max_Speed_Hz := 500;
  
  // === READ COMMANDS FROM TABLE LOGIC ===
  Motor.REQ_EN_Run := Table_Status.Input_Feeders_Enable;
  
  IF Table_Status.Input_Feeders_Enable THEN
    Motor.REQ_Speed_Fix_01 := TRUE;
    Motor.OUT_VFD_REQ_Speed_User := Convert_mm_min_to_User_Units(Table_Status.Input_Feeders_Speed_mm_min);
    
    // Feeder-specific logic: synchronized operation with M317
    Check_Synchronization_With_M317();
    
    // Stop after bottle detection if requested
    IF Table_Status.Input_Feeders_Stop_After_Bottle THEN
      Implement_Stop_After_Bottle_Logic();
    END_IF;
  ELSE
    Motor.REQ_Speed_Fix_01 := FALSE;
  END_IF;
  
  // === CALL MOTOR MANAGEMENT FB ===
  FB_Motors_Manage(Motor);
END_FUNCTION;

8.2 FC_Table_Motor_M319 (Input Selector)

FC_Table_Motor_M319:
VAR_IN_OUT
  Motor : UDT_Motor_Manage;
  Table_Status : T_Table_Status_Commands;
END_VAR

// Pseudocode:
BEGIN
  // === MOTOR CONFIGURATION ===
  Motor.CFG_VFD := TRUE;
  Motor.CFG_PN := TRUE;
  Motor.CFG_Inverter_Type := Inverter_Type_MINIMOTOR;
  
  // === POSITIONING MODE SETUP ===
  IF Table_Status.Input_Selector_Positioning_Mode THEN
    Setup_Positioning_Mode();
    Target_Position := Get_Position_For_Channel(Table_Status.Input_Selector_Target_Channel);
    Motor.REQ_Target_Position := Target_Position;
    Motor.REQ_Positioning_Enable := Table_Status.Input_Selector_Enable;
  ELSE
    Setup_Velocity_Mode();
    Motor.REQ_EN_Run := Table_Status.Input_Selector_Enable;
  END_IF;
  
  // === CALL MOTOR MANAGEMENT FB ===
  FB_Motors_Manage(Motor);
END_FUNCTION;

8.3 FC_Table_Motor_M332 (Center Channel - Bypass)

FC_Table_Motor_M332:
VAR_IN_OUT
  Motor : UDT_Motor_Manage;
  Table_Status : T_Table_Status_Commands;
END_VAR

// Pseudocode:
BEGIN
  // === MOTOR CONFIGURATION ===
  Motor.CFG_VFD := TRUE;
  Motor.CFG_PN := TRUE;
  Motor.CFG_Inverter_Type := Inverter_Type_G120C_SIEMENS;
  
  // === READ COMMANDS FROM TABLE LOGIC ===
  Motor.REQ_EN_Run := Table_Status.Channel_Enable[5];  // Channel 5 = center
  
  IF Table_Status.Channel_Enable[5] THEN
    Motor.REQ_Speed_Fix_01 := TRUE;
    Motor.OUT_VFD_REQ_Speed_User := Convert_mm_min_to_User_Units(Table_Status.Channel_Speed_mm_min[5]);
  ELSE
    Motor.REQ_Speed_Fix_01 := FALSE;
  END_IF;
  
  // === CALL MOTOR MANAGEMENT FB ===
  FB_Motors_Manage(Motor);
END_FUNCTION;

9. Error Handling

9.1 Basic Error Detection

PROCEDURE Check_Basic_Errors:
BEGIN
  Error_Code := 0;
  
  // Check motor inverter errors
  IF Motor_M316.Alarm_02 OR Motor_M317.Alarm_02 THEN
    Error_Code := Error_Code OR 16#0001; // Input feeders inverter error
  END_IF;
  
  IF Motor_M341.Alarm_02 OR Motor_M342.Alarm_02 THEN
    Error_Code := Error_Code OR 16#0002; // Output feeders inverter error
  END_IF;
  
  // Check selector positioning errors
  IF Motor_M319.Alarm_02 THEN
    Error_Code := Error_Code OR 16#0004; // Input selector error
  END_IF;
  
  IF Motor_M340.Alarm_02 THEN
    Error_Code := Error_Code OR 16#0008; // Output selector error
  END_IF;
  
  // Check channel motor errors
  FOR i := 1 TO 9 DO
    IF Get_Channel_Motor_Alarm(i) THEN
      Error_Code := Error_Code OR (16#0010 SHL i); // Channel motor error
    END_IF;
  END_FOR;
  
  // Transition to error state if errors detected
  IF Error_Code <> 0 THEN
    Current_State := TABLE_STATE_ERROR;
  END_IF;
END_PROCEDURE;

10. Configuration and Initialization

10.1 Format Configuration Example

PROCEDURE Initialize_Format_Data:
BEGIN
  // Format 1 - Left side accumulation
  Format_Data[1].Format_Number := 1;
  Format_Data[1].Accumulation_Side := 1;  // Left side
  Format_Data[1].Bottle_Dimension_mm := 85.0;
  Format_Data[1].Max_Speed_mm_min := 12000.0;
  Format_Data[1].Target_Channels := [1, 2, 3, 4];
  
  // Format 2 - Right side accumulation  
  Format_Data[2].Format_Number := 2;
  Format_Data[2].Accumulation_Side := 2;  // Right side
  Format_Data[2].Bottle_Dimension_mm := 65.0;
  Format_Data[2].Max_Speed_mm_min := 15000.0;
  Format_Data[2].Target_Channels := [9, 8, 7, 6];
END_PROCEDURE;

10.2 Area Configuration

PROCEDURE Initialize_Area_Management:
BEGIN
  // Configure each area with its specific dimensions
  Area_Input_Selector.Area_Length_mm := 500.0;
  Area_Output_Selector.Area_Length_mm := 500.0;
  
  FOR i := 1 TO 9 DO
    Area_Channel[i].Area_Length_mm := Get_Channel_Length(i);
  END_FOR;
END_PROCEDURE;

11. Integration Points

11.1 FC_Table_Devices Integration

FC_Table_Devices:
BEGIN
  // Call Table FB with all motor references and exchange data
  "DB Table"(
    Enable := System_Enable,
    Target_Format := HMI_Selected_Format,
    Manual_Mode := System_Manual_Mode,
    
    Motor_M316 := "DB Motor M316".Manage,
    Motor_M317 := "DB Motor M317".Manage,
    Motor_M318 := "DB Motor M318".Manage,
    Motor_M319 := "DB Motor M319".Manage,
    Motor_M328 := "DB Motor M328".Manage,
    Motor_M329 := "DB Motor M329".Manage,
    Motor_M330 := "DB Motor M330".Manage,
    Motor_M331 := "DB Motor M331".Manage,
    Motor_M332 := "DB Motor M332".Manage,
    Motor_M333 := "DB Motor M333".Manage,
    Motor_M334 := "DB Motor M334".Manage,
    Motor_M335 := "DB Motor M335".Manage,
    Motor_M336 := "DB Motor M336".Manage,
    Motor_M340 := "DB Motor M340".Manage,
    Motor_M341 := "DB Motor M341".Manage,
    Motor_M342 := "DB Motor M342".Manage,
    Motor_M343 := "DB Motor M343".Manage,
    
    Exchange := "DB ATable Exchange"
  );
  
  // Additional device coordination logic if needed
END_FUNCTION;

This specification provides a complete framework for implementing the table accumulation system while maintaining consistency with the existing motor management framework. The design allows for clear separation of concerns, easy debugging, and flexible implementation of motor-specific behaviors.