Cscape Programming Guide
1: // Bump test - apply step change Output_Value := Output_Value + PID_Tune_Bump_Size; IF Output_Value > 100.0 THEN Output_Value := 100.0; END_IF // Wait for process to settle (5 seconds) IF Timer1.Q THEN PID_Tune_Step := 2; Timer1.IN := FALSE; ELSE Timer1.PT := T#5s; Timer1.IN := TRUE; END_IF 2: // Calculate PID parameters using Ziegler-Nichols PID_Tune_Response_Time := Measure_Response_Time(Process_Value); PID_Tune_Ultimate_Gain := 4.0 * PID_Tune_Bump_Size / (3.14159 * PID_Tune_Response_Time); // Calculate gains PID_Tune_Kp := 0.6 * PID_Tune_Ultimate_Gain; PID_Tune_Ki := 2.0 * PID_Tune_Kp / PID_Tune_Response_Time; PID_Tune_Kd := PID_Tune_Kp * PID_Tune_Response_Time / 8.0; PID_Tune_Step := 0; PID_Tune_Enable := FALSE; Log_Enable := FALSE; END_CASE
// Open file (append mode) h_file := FileOpen(filename, 'a'); IF h_file > 0 THEN FileWrite(h_file, ADR(csv_string), LEN(csv_string)); FileClose(h_file); Write_To_Log := TRUE; ELSE Write_To_Log := FALSE; END_IF Create a ladder rung for user control: cscape programming
// Create CSV string csv_string := DINT_TO_STRING(index) + ',' + REAL_TO_STRING(pv) + ',' + REAL_TO_STRING(out_val) + '\r\n'; 1: // Bump test - apply step change
CASE PID_Tune_Step OF 0: // Idle PID_Tune_Active := FALSE; PID_Tune_Active : BOOL := FALSE
I'll help you develop a feature for (Horner Automation's IEC 61131-3 programming environment for XL series controllers). Since Cscape uses ladder logic, FBD, and structured text (ST), I'll outline a practical feature development approach. Example Feature: PID Auto-Tune with Trend Logging Let's create a feature that automatically tunes a PID loop and logs response data to the controller's SD card. 1. Memory Mapping (Variable Declaration) // PID Tuning Feature Variables VAR_GLOBAL PID_Tune_Enable : BOOL := FALSE; PID_Tune_Active : BOOL := FALSE; PID_Tune_Step : INT := 0; // 0=idle,1=bump test,2=calculate PID_Tune_Bump_Size : REAL := 10.0; // % output bump PID_Tune_Kp : REAL := 1.0; PID_Tune_Ki : REAL := 0.1; PID_Tune_Kd : REAL := 0.05; PID_Tune_Response_Time : REAL := 0.0; // seconds PID_Tune_Ultimate_Gain : REAL := 0.0; PID_Tune_Sample_Time : REAL := 0.1; // 100ms // Logging Log_Enable : BOOL := FALSE; Log_File_Name : STRING := "TUNE_LOG.CSV"; Log_Index : DINT := 0; Process_Value : REAL; // from analog input Setpoint : REAL := 50.0; Output_Value : REAL; END_VAR 2. Structured Text Routine (PID Tune Engine) // PID_TUNE routine (executes every scan or timed interrupt) IF PID_Tune_Enable AND NOT PID_Tune_Active THEN PID_Tune_Active := TRUE; PID_Tune_Step := 1; Log_Enable := TRUE; Log_Index := 0; END_IF
// Timer for sample interval IF Log_Enable AND Timer2.Q THEN Write_To_Log(Log_File_Name, Log_Index, Process_Value, Output_Value); Log_Index := Log_Index + 1; Timer2.IN := TRUE; // retrigger ELSE Timer2.PT := REAL_TO_TIME(PID_Tune_Sample_Time * 1000); Timer2.IN := Log_Enable; END_IF FUNCTION Write_To_Log : BOOL VAR_INPUT filename : STRING; index : DINT; pv : REAL; out_val : REAL; END_VAR VAR line_str : STRING(80); csv_string : STRING(80); h_file : DINT; END_VAR