## 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 ```pascal 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 ```pascal 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 ```pascal 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 ```pascal 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) ```pascal // === 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 ```pascal 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 ```pascal 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 ```pascal 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 ```pascal 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 ```pascal 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) ```pascal 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) ```pascal 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) ```pascal 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 ```pascal 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 ```pascal 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 ```pascal 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 ```pascal 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.