Fixed ramp generator and tests
This commit is contained in:
@@ -116,13 +116,13 @@
|
|||||||
</Hides>
|
</Hides>
|
||||||
</DataType>
|
</DataType>
|
||||||
</DataTypes>
|
</DataTypes>
|
||||||
<Project ProjectGUID="{775BE4FD-89CE-48D5-8E68-5C84AF95981A}" Target64Bit="true" ShowHideConfigurations="#x6">
|
<Project ProjectGUID="{775BE4FD-89CE-48D5-8E68-5C84AF95981A}" TargetNetId="5.167.199.178.1.1" Target64Bit="true" ShowHideConfigurations="#x6">
|
||||||
<System>
|
<System>
|
||||||
<Settings MaxCpus="2"/>
|
<Settings MaxCpus="2"/>
|
||||||
<Licenses>
|
<Licenses>
|
||||||
<Target>
|
<Target>
|
||||||
<ManualSelect>{9FD32FC8-0CF9-4C5B-95FB-F35423496A77}</ManualSelect>
|
<ManualSelect>{9FD32FC8-0CF9-4C5B-95FB-F35423496A77}</ManualSelect>
|
||||||
<LicenseDevice DongleHardwareId="2" DongleDevice="#x71010002" DongleLevel="92" DongleSystemId="{F4D452BD-01EA-8CE8-F538-CCB335BD88CC}" DongleSerialNumber="000btjb7" DongleCacheLicense="false"/>
|
<LicenseDevice Disabled="true" DongleHardwareId="2" DongleDevice="#x71010002" DongleLevel="92" DongleSerialNumber="000btjb7" DongleCacheLicense="false"/>
|
||||||
</Target>
|
</Target>
|
||||||
</Licenses>
|
</Licenses>
|
||||||
<Tasks>
|
<Tasks>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
</System>
|
</System>
|
||||||
<Plc>
|
<Plc>
|
||||||
<Project GUID="{4E62D9E7-436C-457D-8DC4-82D2FEF91C96}" Name="BasicComponents" PrjFilePath="BasicComponents\BasicComponents.plcproj" TmcFilePath="BasicComponents\BasicComponents.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" CopyTmcToTarget="true" CopyTpyToTarget="false" SymbolicMapping="true">
|
<Project GUID="{4E62D9E7-436C-457D-8DC4-82D2FEF91C96}" Name="BasicComponents" PrjFilePath="BasicComponents\BasicComponents.plcproj" TmcFilePath="BasicComponents\BasicComponents.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" CopyTmcToTarget="true" CopyTpyToTarget="false" SymbolicMapping="true">
|
||||||
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{26169BD6-1E5A-D1C1-C99A-F9225BAE6710}" TmcPath="BasicComponents\BasicComponents.tmc">
|
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{2FCBDB60-54F0-F883-C574-3EE85CA8FA87}" TmcPath="BasicComponents\BasicComponents.tmc">
|
||||||
<Name>BasicComponents Instance</Name>
|
<Name>BasicComponents Instance</Name>
|
||||||
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
|
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
|
||||||
<Vars VarGrpType="2" AreaNo="1">
|
<Vars VarGrpType="2" AreaNo="1">
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
<Compile Include="POUs\Components\Controller\FB_PID.TcPOU">
|
<Compile Include="POUs\Components\Controller\FB_PID.TcPOU">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="POUs\Components\Controller\FB_RampGen.TcPOU">
|
<Compile Include="POUs\Components\Controller\FB_RampGenerator.TcPOU">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="POUs\Components\EventListener\FB_EventListener.TcPOU">
|
<Compile Include="POUs\Components\EventListener\FB_EventListener.TcPOU">
|
||||||
@@ -107,9 +107,6 @@
|
|||||||
<Compile Include="POUs\Components\Utilities\FB_Blinker.TcPOU">
|
<Compile Include="POUs\Components\Utilities\FB_Blinker.TcPOU">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="POUs\Components\Utilities\FB_RampGenerator.TcPOU">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="POUs\Components\Utilities\FB_ReleaseSignal.TcPOU">
|
<Compile Include="POUs\Components\Utilities\FB_ReleaseSignal.TcPOU">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -154,9 +151,6 @@
|
|||||||
<Compile Include="POUs\HMI\Datentypen\ST_HMI_INTERLOCK.TcDUT">
|
<Compile Include="POUs\HMI\Datentypen\ST_HMI_INTERLOCK.TcDUT">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="POUs\HMI\Datentypen\ST_HMI_ORP_SENSOR_DATA.TcDUT">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="POUs\HMI\Datentypen\ST_HMI_VALVE_DATA.TcDUT">
|
<Compile Include="POUs\HMI\Datentypen\ST_HMI_VALVE_DATA.TcDUT">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TcPlcObject Version="1.1.0.1">
|
|
||||||
<POU Name="FB_RampGen" Id="{61136989-8ee2-49fa-af2b-1b579e85353f}" SpecialFunc="None">
|
|
||||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_RampGen
|
|
||||||
VAR_INPUT
|
|
||||||
rTarget : REAL; // Zielwert
|
|
||||||
rRiseRate : REAL; // Steigung positiv [Einheit/s]
|
|
||||||
rFallRate : REAL; // Steigung negativ [Einheit/s]
|
|
||||||
xEnable : BOOL;
|
|
||||||
xHold : BOOL; // Rampe einfrieren
|
|
||||||
xReset : BOOL; // Ausgang sofort auf Ziel setzen
|
|
||||||
END_VAR
|
|
||||||
|
|
||||||
VAR_OUTPUT
|
|
||||||
rOut : REAL; // Rampenausgang
|
|
||||||
xBusy : BOOL; // TRUE solange Rampe läuft
|
|
||||||
END_VAR
|
|
||||||
|
|
||||||
VAR
|
|
||||||
_xFirstCycle : BOOL := TRUE;
|
|
||||||
_rT : REAL := 0.0;
|
|
||||||
_rDiff : REAL := 0.0;
|
|
||||||
_rStep : REAL := 0.0;
|
|
||||||
END_VAR]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[IF _xFirstCycle THEN
|
|
||||||
_xFirstCycle := FALSE;
|
|
||||||
|
|
||||||
// Task-Zeit in Sekunden (100 ns Ticks)
|
|
||||||
_rT := LREAL_TO_REAL(
|
|
||||||
UDINT_TO_LREAL(_TaskInfo[GETCURTASKINDEXEX()].CycleTime) * 1E-7
|
|
||||||
);
|
|
||||||
|
|
||||||
rOut := rTarget;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
IF NOT xEnable THEN
|
|
||||||
rOut := rTarget;
|
|
||||||
xBusy := FALSE;
|
|
||||||
RETURN;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
IF xReset THEN
|
|
||||||
rOut := rTarget;
|
|
||||||
xBusy := FALSE;
|
|
||||||
RETURN;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
IF xHold THEN
|
|
||||||
xBusy := (ABS(rTarget - rOut) > 0.0);
|
|
||||||
RETURN;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
_rDiff := rTarget - rOut;
|
|
||||||
|
|
||||||
|
|
||||||
IF _rDiff > 0 THEN
|
|
||||||
// Aufwärtsrampe
|
|
||||||
_rStep := rRiseRate * _rT;
|
|
||||||
|
|
||||||
IF _rStep > _rDiff THEN
|
|
||||||
rOut := rTarget;
|
|
||||||
ELSE
|
|
||||||
rOut := rOut + _rStep;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
ELSIF _rDiff < 0 THEN
|
|
||||||
// Abwärtsrampe
|
|
||||||
_rStep := rFallRate * _rT;
|
|
||||||
|
|
||||||
IF _rStep > ABS(_rDiff) THEN
|
|
||||||
rOut := rTarget;
|
|
||||||
ELSE
|
|
||||||
rOut := rOut - _rStep;
|
|
||||||
END_IF
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
xBusy := (ABS(rTarget - rOut) > 0.0);]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</POU>
|
|
||||||
</TcPlcObject>
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TcPlcObject Version="1.1.0.1">
|
||||||
|
<POU Name="FB_RampGenerator" Id="{61136989-8ee2-49fa-af2b-1b579e85353f}" SpecialFunc="None">
|
||||||
|
<Declaration><![CDATA[FUNCTION_BLOCK FB_RampGenerator
|
||||||
|
VAR_INPUT
|
||||||
|
xEnable : BOOL; // Output equals input
|
||||||
|
xHold : BOOL := FALSE; // Freeze current value
|
||||||
|
rTarget : REAL; // Targetvalue
|
||||||
|
rRiseRate : REAL; // Positive rise rate in units/s
|
||||||
|
rFallRate : REAL; // Negative rise rate in units/s (only positive values)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
rOut : REAL; // Generated ramp output
|
||||||
|
xBusy : BOOL; // TRUE until target value reached
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
_xFirstCycle : BOOL := TRUE;
|
||||||
|
_rT : REAL := 0.0; // Task cycle time
|
||||||
|
_rDiff : REAL := 0.0;
|
||||||
|
_rStep : REAL := 0.0;
|
||||||
|
|
||||||
|
// Output buffer
|
||||||
|
_rOut : REAL;
|
||||||
|
END_VAR]]></Declaration>
|
||||||
|
<Implementation>
|
||||||
|
<ST><![CDATA[IF _xFirstCycle THEN
|
||||||
|
_xFirstCycle := FALSE;
|
||||||
|
|
||||||
|
// Get cycle time
|
||||||
|
_rT := LREAL_TO_REAL(UDINT_TO_LREAL(_TaskInfo[GETCURTASKINDEXEX()].CycleTime) * 1E-7);
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// If not enabled output equals input
|
||||||
|
IF (NOT xEnable) THEN
|
||||||
|
_rOut := rTarget;
|
||||||
|
rOut := _rOut;
|
||||||
|
xBusy := FALSE;
|
||||||
|
RETURN;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Freezes the ramp at the current value
|
||||||
|
IF xHold THEN
|
||||||
|
xBusy := (ABS(rTarget - _rOut) > 0.0);
|
||||||
|
RETURN;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Calculate diff to target
|
||||||
|
_rDiff := rTarget - _rOut;
|
||||||
|
|
||||||
|
// Check if we need to ramp up or down
|
||||||
|
IF _rDiff > 0 THEN
|
||||||
|
// Ramp up
|
||||||
|
_rStep := ABS(rRiseRate) * _rT;
|
||||||
|
|
||||||
|
// Clamp to target value
|
||||||
|
IF _rStep > _rDiff THEN
|
||||||
|
_rOut := rTarget;
|
||||||
|
ELSE
|
||||||
|
_rOut := _rOut + _rStep;
|
||||||
|
END_IF
|
||||||
|
ELSIF _rDiff < 0 THEN
|
||||||
|
// Ramp down
|
||||||
|
_rStep := ABS(rFallRate) * _rT;
|
||||||
|
|
||||||
|
// Clamp to target value
|
||||||
|
IF _rStep > ABS(_rDiff) THEN
|
||||||
|
_rOut := rTarget;
|
||||||
|
ELSE
|
||||||
|
_rOut := _rOut - _rStep;
|
||||||
|
END_IF
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Handle busy flag
|
||||||
|
xBusy := (ABS(rTarget - _rOut) > 0.0);
|
||||||
|
|
||||||
|
// Copy internals to outputs
|
||||||
|
rOut := _rOut;]]></ST>
|
||||||
|
</Implementation>
|
||||||
|
<Method Name="M_SetStart" Id="{f7326067-d944-49e6-a19b-12711f9b3f19}">
|
||||||
|
<Declaration><![CDATA[METHOD M_SetStart
|
||||||
|
VAR_INPUT
|
||||||
|
rStartValue : REAL;
|
||||||
|
END_VAR
|
||||||
|
]]></Declaration>
|
||||||
|
<Implementation>
|
||||||
|
<ST><![CDATA[_rOut := rStartValue;
|
||||||
|
rOut := _rOut;]]></ST>
|
||||||
|
</Implementation>
|
||||||
|
</Method>
|
||||||
|
</POU>
|
||||||
|
</TcPlcObject>
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TcPlcObject Version="1.1.0.1">
|
|
||||||
<POU Name="FB_RampGenerator" Id="{eab75824-fb3c-460a-af65-da2b006c5dc1}" SpecialFunc="None">
|
|
||||||
<Declaration><![CDATA[// Must only be called once per cycle!
|
|
||||||
// Otherwise the Interpolation is wrong
|
|
||||||
{attribute 'analysis' := '-56'}
|
|
||||||
FUNCTION_BLOCK FB_RampGenerator
|
|
||||||
VAR_INPUT
|
|
||||||
// Current target value
|
|
||||||
rTarget : REAL;
|
|
||||||
|
|
||||||
// Minimum target value
|
|
||||||
rTargetMin : REAL;
|
|
||||||
|
|
||||||
// Maximum target value
|
|
||||||
rTargetMax : REAL;
|
|
||||||
|
|
||||||
// Ramp up time (min to max)
|
|
||||||
timRampUp : TIME;
|
|
||||||
|
|
||||||
// Ramp down time (max to min)
|
|
||||||
timRampDown : TIME;
|
|
||||||
END_VAR
|
|
||||||
VAR_OUTPUT
|
|
||||||
rSetpoint : REAL := 0;
|
|
||||||
|
|
||||||
// Indicates that the target value has been reached
|
|
||||||
xInTarget : BOOL;
|
|
||||||
END_VAR
|
|
||||||
VAR
|
|
||||||
// Cycle time in ms
|
|
||||||
_rCycleTime : REAL;
|
|
||||||
|
|
||||||
// Ramp up speed per cycle
|
|
||||||
// Units per ms
|
|
||||||
_rRampUpSpeed : REAL;
|
|
||||||
|
|
||||||
// Ramp down speed per cycle
|
|
||||||
// Units per ms
|
|
||||||
_rRampDownSpeed : REAL;
|
|
||||||
|
|
||||||
// Distance left to go
|
|
||||||
_rDistanceToGo : REAL;
|
|
||||||
|
|
||||||
// First cycle
|
|
||||||
_xFirstCycle : BOOL := TRUE;
|
|
||||||
|
|
||||||
_fbGetCurTaskIdx : GETCURTASKINDEX;
|
|
||||||
END_VAR
|
|
||||||
]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[// Get task cycle time during first cycle
|
|
||||||
// Does not work in FB_init and also not with {attribute 'call_after_init'}
|
|
||||||
IF _xFirstCycle THEN
|
|
||||||
_xFirstCycle := FALSE;
|
|
||||||
// Get current task cycle time
|
|
||||||
_fbGetCurTaskIdx();
|
|
||||||
// Convert 100ns to 1ms
|
|
||||||
_rCycleTime := UDINT_TO_REAL(TwinCAT_SystemInfoVarList._TaskInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
// Clamp setpoint to min max values
|
|
||||||
{analysis -37}
|
|
||||||
rTarget := MAX(rTarget, rTargetMin);
|
|
||||||
rTarget := MIN(rTarget, rTargetMax);
|
|
||||||
{analysis +37}
|
|
||||||
|
|
||||||
// Calculate change rates
|
|
||||||
// TIME datatype is handled internally like a UDINT (32-bit). This leads to a resolution in milliseconds.
|
|
||||||
// [_rRampUpSpeed] = units per cycle
|
|
||||||
IF timRampUp <> T#0S THEN
|
|
||||||
_rRampUpSpeed := (rTargetMax - rTargetMin) * (_rCycleTime / TIME_TO_REAL(timRampUp));
|
|
||||||
ELSE
|
|
||||||
_rRampUpSpeed := rTargetMax;
|
|
||||||
END_IF
|
|
||||||
IF timRampDown <> T#0S THEN
|
|
||||||
_rRampDownSpeed := -(rTargetMax - rTargetMin) * (_rCycleTime / TIME_TO_REAL(timRampDown));
|
|
||||||
ELSE
|
|
||||||
_rRampDownSpeed := -rTargetMax;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate distance left to go
|
|
||||||
_rDistanceToGo := rTarget - rSetpoint;
|
|
||||||
|
|
||||||
// Calculate new setpoint
|
|
||||||
IF (_rDistanceToGo > 0.0) THEN
|
|
||||||
IF (_rDistanceToGo > _rRampUpSpeed) THEN
|
|
||||||
rSetpoint := rSetpoint + _rRampUpSpeed;
|
|
||||||
ELSE
|
|
||||||
rSetpoint := rTarget;
|
|
||||||
END_IF
|
|
||||||
ELSIF (_rDistanceToGo < 0.0) THEN
|
|
||||||
IF (_rDistanceToGo < _rRampDownSpeed) THEN
|
|
||||||
rSetpoint := rSetpoint + _rRampDownSpeed;
|
|
||||||
ELSE
|
|
||||||
rSetpoint := rTarget;
|
|
||||||
END_IF
|
|
||||||
ELSE
|
|
||||||
rSetpoint := rTarget;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
// Check if we are in range of target range
|
|
||||||
IF ABS(rSetpoint-rTarget) <= 0.001 THEN
|
|
||||||
xInTarget := TRUE;
|
|
||||||
ELSE
|
|
||||||
xInTarget := FALSE;
|
|
||||||
END_IF ]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
<Property Name="CycleTime" Id="{12c00f80-a9cf-4d1b-ac68-3c3e59228015}">
|
|
||||||
<Declaration><![CDATA[PROPERTY CycleTime : REAL]]></Declaration>
|
|
||||||
<Get Name="Get" Id="{06853e5f-48e3-4643-ae4f-e23a07d71695}">
|
|
||||||
<Declaration><![CDATA[VAR
|
|
||||||
END_VAR
|
|
||||||
]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[CycleTime := _rCycleTime;]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Get>
|
|
||||||
</Property>
|
|
||||||
<Method Name="SetStart" Id="{06f2b416-7cfb-4f46-94e3-4002d92fc703}">
|
|
||||||
<Declaration><![CDATA[METHOD SetStart
|
|
||||||
VAR_INPUT
|
|
||||||
rStartpoint : REAL;
|
|
||||||
END_VAR
|
|
||||||
]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[rSetpoint := rStartpoint;]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Method>
|
|
||||||
</POU>
|
|
||||||
</TcPlcObject>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TcPlcObject Version="1.1.0.1">
|
|
||||||
<DUT Name="ST_HMI_ORP_SENSOR_DATA" Id="{5591496f-c48a-4039-866c-f9454b697632}">
|
|
||||||
<Declaration><![CDATA[TYPE ST_HMI_ORP_SENSOR_DATA :
|
|
||||||
STRUCT
|
|
||||||
// PH sensor value
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
rValuePH : REAL;
|
|
||||||
|
|
||||||
// Temperature sensor value
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
rValueTemp : REAL;
|
|
||||||
|
|
||||||
// Redox potential sensor data
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
rValueORP : REAL;
|
|
||||||
|
|
||||||
// Sensor lifetime left
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
rValueDLI : REAL;
|
|
||||||
|
|
||||||
// Reflects the current status of the ORP input data (read only)
|
|
||||||
// 1 = Ok; 2 = Error
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
iStatus : INT := 0;
|
|
||||||
|
|
||||||
// Instance name (read only)
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
sName : STRING(80);
|
|
||||||
|
|
||||||
// true = Object ist used by the program and can be actuated by the HMI
|
|
||||||
// false = Object is NOT used by the program and should NOT be used by the HMI
|
|
||||||
// (read only)
|
|
||||||
{attribute 'OPC.UA.DA' := '1'}
|
|
||||||
{attribute 'OPC.UA.DA.Access' := '1'}
|
|
||||||
xUsed : BOOL := TRUE;
|
|
||||||
END_STRUCT
|
|
||||||
END_TYPE
|
|
||||||
]]></Declaration>
|
|
||||||
</DUT>
|
|
||||||
</TcPlcObject>
|
|
||||||
@@ -3,17 +3,6 @@
|
|||||||
<POU Name="FB_RampGeneratorTest" Id="{883a6789-24bc-434e-bdcd-11047d9142bc}" SpecialFunc="None">
|
<POU Name="FB_RampGeneratorTest" Id="{883a6789-24bc-434e-bdcd-11047d9142bc}" SpecialFunc="None">
|
||||||
<Declaration><![CDATA[FUNCTION_BLOCK FB_RampGeneratorTest EXTENDS TcUnit.FB_TestSuite
|
<Declaration><![CDATA[FUNCTION_BLOCK FB_RampGeneratorTest EXTENDS TcUnit.FB_TestSuite
|
||||||
VAR
|
VAR
|
||||||
// variables for max clamp test
|
|
||||||
_fbRMPMaxClamp : FB_RampGenerator;
|
|
||||||
_fbDelayMaxClamp : TON;
|
|
||||||
_fbDelayMaxClampBuffer : TON;
|
|
||||||
|
|
||||||
// variables for min clamp test
|
|
||||||
_fbRMPMinClamp : FB_RampGenerator;
|
|
||||||
_fbDelayMinClamp : TON;
|
|
||||||
_fbDelayMinClampBuffer : TON;
|
|
||||||
_xInitMinClamp : BOOL := FALSE;
|
|
||||||
|
|
||||||
// variables for ramp down timing test
|
// variables for ramp down timing test
|
||||||
_fbRMPRampDownTime : FB_RampGenerator;
|
_fbRMPRampDownTime : FB_RampGenerator;
|
||||||
_fbDelayRampDownTime : TON;
|
_fbDelayRampDownTime : TON;
|
||||||
@@ -43,11 +32,7 @@ END_VAR
|
|||||||
]]></Declaration>
|
]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[// test for correct cycle time and it's readout
|
<ST><![CDATA[// test for correct cycle time and it's readout
|
||||||
TestCycleTimeReadout();
|
// TestCycleTimeReadout();
|
||||||
|
|
||||||
// test clamping
|
|
||||||
TestMaxClamping();
|
|
||||||
TestMinClamping();
|
|
||||||
|
|
||||||
// test ramp up/down
|
// test ramp up/down
|
||||||
TestRampUpTime();
|
TestRampUpTime();
|
||||||
@@ -59,55 +44,17 @@ TestRampDownContinuity();
|
|||||||
TestInTargetResultUp();
|
TestInTargetResultUp();
|
||||||
TestInTargetResultDown();]]></ST>
|
TestInTargetResultDown();]]></ST>
|
||||||
</Implementation>
|
</Implementation>
|
||||||
<Method Name="TestCycleTimeReadout" Id="{adf8238e-e5ed-478c-ac22-37930b46e697}">
|
|
||||||
<Declaration><![CDATA[{warning disable C0394}
|
|
||||||
METHOD TestCycleTimeReadout
|
|
||||||
VAR
|
|
||||||
// ramp generator instance
|
|
||||||
_fbRampGen : FB_RampGenerator;
|
|
||||||
|
|
||||||
// task index instance
|
|
||||||
_fbGetCurTaskIdx : GETCURTASKINDEX;
|
|
||||||
END_VAR
|
|
||||||
]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[TEST('TestCycleTimeReadout');
|
|
||||||
|
|
||||||
// read current cycle time and abort test in case of cycletime not 10 ms.
|
|
||||||
_fbGetCurTaskIdx();
|
|
||||||
IF ((UDINT_TO_REAL(TwinCAT_SystemInfoVarList._TASKInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5) - 10.0) > 0.001 THEN
|
|
||||||
AssertTrue(FALSE, 'Project cycle time not set to 10ms!');
|
|
||||||
ELSE
|
|
||||||
_fbRampGen(
|
|
||||||
rTarget:= 0.0,
|
|
||||||
rTargetMin:= 0.0,
|
|
||||||
rTargetMax:= 100.0,
|
|
||||||
timRampUp:= T#5S,
|
|
||||||
timRampDown:= T#5S,
|
|
||||||
rSetpoint=> ,
|
|
||||||
xInTarget=> );
|
|
||||||
|
|
||||||
// Project should be set to 10ms cycle time for this test to work
|
|
||||||
AssertEquals_REAL(Expected := 10.0, Actual := _fbRampGen.CycleTime, Delta := 0.01, 'Cycle time is not equal to project cycle time (10ms)');
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
TEST_FINISHED();]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Method>
|
|
||||||
<Method Name="TestInTargetResultDown" Id="{d659dd70-b87c-48f4-9d7b-df95aaef8540}">
|
<Method Name="TestInTargetResultDown" Id="{d659dd70-b87c-48f4-9d7b-df95aaef8540}">
|
||||||
<Declaration><![CDATA[{warning disable C0394}
|
<Declaration><![CDATA[{warning disable C0394}
|
||||||
METHOD TestInTargetResultDown
|
METHOD TestInTargetResultDown
|
||||||
VAR
|
VAR
|
||||||
// in target result
|
|
||||||
_xInTarget : BOOL;
|
|
||||||
|
|
||||||
// current ramp setpoint
|
// current ramp setpoint
|
||||||
_rSetpoint : REAL;
|
_rSetpoint : REAL;
|
||||||
END_VAR
|
END_VAR
|
||||||
|
|
||||||
VAR CONSTANT
|
VAR CONSTANT
|
||||||
// delay until in target should be reached
|
// delay until in target should be reached
|
||||||
timDelay : TIME := T#990MS;
|
timDelay : TIME := T#500MS;
|
||||||
END_VAR]]></Declaration>
|
END_VAR]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[TEST('TestInTargetResultDown');
|
<ST><![CDATA[TEST('TestInTargetResultDown');
|
||||||
@@ -117,19 +64,18 @@ _fbDelayInTargetResultDown(IN := TRUE, PT := timDelay);
|
|||||||
|
|
||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPInTargetResultDown(
|
_fbRMPInTargetResultDown(
|
||||||
|
xEnable := TRUE,
|
||||||
rTarget := -1,
|
rTarget := -1,
|
||||||
rTargetMin := -1,
|
rRiseRate := 2,
|
||||||
rTargetMax := 1,
|
rFallRate := 2,
|
||||||
timRampUp := T#2S,
|
rOut => _rSetpoint,
|
||||||
timRampDown := T#2S,
|
xBusy =>);
|
||||||
rSetpoint => _rSetpoint,
|
|
||||||
xInTarget => _xInTarget);
|
|
||||||
|
|
||||||
// check for whether InTarget is reached at the specified time
|
// check for whether InTarget is reached at the specified time
|
||||||
IF NOT _fbDelayInTargetResultDown.Q THEN
|
IF NOT _fbDelayInTargetResultDown.Q THEN
|
||||||
AssertFalse(_xInTarget, 'InTarget reached earlier then expected.');
|
AssertTrue(_fbRMPInTargetResultDown.xBusy, 'InTarget reached earlier then expected.');
|
||||||
ELSE
|
ELSE
|
||||||
AssertTrue(_xInTarget, 'InTarget not reached in time.');
|
AssertFalse(_fbRMPInTargetResultDown.xBusy, 'InTarget not reached in time.');
|
||||||
TEST_FINISHED();
|
TEST_FINISHED();
|
||||||
END_IF]]></ST>
|
END_IF]]></ST>
|
||||||
</Implementation>
|
</Implementation>
|
||||||
@@ -138,16 +84,13 @@ END_IF]]></ST>
|
|||||||
<Declaration><![CDATA[{warning disable C0394}
|
<Declaration><![CDATA[{warning disable C0394}
|
||||||
METHOD TestInTargetResultUp
|
METHOD TestInTargetResultUp
|
||||||
VAR
|
VAR
|
||||||
// in target result
|
|
||||||
_xInTarget : BOOL;
|
|
||||||
|
|
||||||
// current ramp setpoint
|
// current ramp setpoint
|
||||||
_rSetpoint : REAL;
|
_rSetpoint : REAL;
|
||||||
END_VAR
|
END_VAR
|
||||||
|
|
||||||
VAR CONSTANT
|
VAR CONSTANT
|
||||||
// delay until in target should be reached
|
// delay until in target should be reached
|
||||||
timDelay : TIME := T#740MS;
|
timDelay : TIME := T#500MS;
|
||||||
END_VAR]]></Declaration>
|
END_VAR]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[TEST('TestInTargetResultUp');
|
<ST><![CDATA[TEST('TestInTargetResultUp');
|
||||||
@@ -157,130 +100,19 @@ _fbDelayInTargetResultUp(IN := TRUE, PT := timDelay);
|
|||||||
|
|
||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPInTargetResultUp(
|
_fbRMPInTargetResultUp(
|
||||||
|
xEnable := TRUE,
|
||||||
rTarget := 1,
|
rTarget := 1,
|
||||||
rTargetMin := -1,
|
rRiseRate := 2,
|
||||||
rTargetMax := 1,
|
rFallRate := 2,
|
||||||
timRampUp := T#1S500MS,
|
rOut => _rSetpoint,
|
||||||
timRampDown := T#1S500MS,
|
xBusy => );
|
||||||
rSetpoint => _rSetpoint,
|
|
||||||
xInTarget => _xInTarget);
|
|
||||||
|
|
||||||
// check for whether InTarget is reached at the specified time
|
// check for whether InTarget is reached at the specified time
|
||||||
IF NOT _fbDelayInTargetResultUp.Q THEN
|
IF (NOT _fbDelayInTargetResultUp.Q) THEN
|
||||||
AssertFalse(_xInTarget, 'InTarget reached earlier then expected.');
|
AssertTrue(_fbRMPInTargetResultUp.xBusy, 'InTarget reached earlier then expected.');
|
||||||
ELSE
|
ELSE
|
||||||
AssertTrue(_xInTarget, 'InTarget not reached in time.');
|
AssertFalse(_fbRMPInTargetResultUp.xBusy, 'InTarget not reached in time.');
|
||||||
TEST_FINISHED();
|
TEST_FINISHED();
|
||||||
END_IF]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Method>
|
|
||||||
<Method Name="TestMaxClamping" Id="{65cd0699-a59f-4537-9fbd-e53ee8fb2124}">
|
|
||||||
<Declaration><![CDATA[{warning disable C0394}
|
|
||||||
METHOD TestMaxClamping
|
|
||||||
VAR
|
|
||||||
// current ramp setpoint
|
|
||||||
_rSetpoint : REAL;
|
|
||||||
END_VAR
|
|
||||||
|
|
||||||
VAR CONSTANT
|
|
||||||
// expected clamped value
|
|
||||||
rExpected : REAL := 5;
|
|
||||||
|
|
||||||
// delta for assertion
|
|
||||||
rDelta : REAL := 0.0001;
|
|
||||||
|
|
||||||
// delay until clamping is reached
|
|
||||||
timDelayRamp : TIME := T#500MS;
|
|
||||||
|
|
||||||
// delay to check for value changes after clamping
|
|
||||||
timDelay : TIME := T#1S;
|
|
||||||
END_VAR]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[TEST('TestMaxClamping');
|
|
||||||
|
|
||||||
// timer until until clamping is reach + timeBuffer afterwards to check whether is stays clamped or not
|
|
||||||
_fbDelayMaxClamp(IN := TRUE, PT := timDelayRamp);
|
|
||||||
_fbDelayMaxClampBuffer(IN := TRUE, PT := timDelay);
|
|
||||||
|
|
||||||
// run RampGenerator
|
|
||||||
_fbRMPMaxClamp(
|
|
||||||
rTarget := 10,
|
|
||||||
rTargetMin := 0,
|
|
||||||
rTargetMax := 5,
|
|
||||||
timRampUp := T#500MS,
|
|
||||||
timRampDown := T#500MS,
|
|
||||||
rSetpoint => _rSetpoint,
|
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check for clamping
|
|
||||||
IF NOT _fbDelayMaxClamp.Q THEN
|
|
||||||
// too early
|
|
||||||
AssertTrue(_rSetpoint < rExpected,'Clamped value reached before expected time');
|
|
||||||
ELSE
|
|
||||||
// after expected rampTime
|
|
||||||
IF NOT _fbDelayMaxClampBuffer.Q THEN
|
|
||||||
AssertEquals_REAL(Expected := rExpected, Actual := _rSetpoint, Delta := rDelta, 'Value did not stay on or did not reach MaxTarget');
|
|
||||||
ELSE
|
|
||||||
TEST_FINISHED();
|
|
||||||
END_IF
|
|
||||||
END_IF]]></ST>
|
|
||||||
</Implementation>
|
|
||||||
</Method>
|
|
||||||
<Method Name="TestMinClamping" Id="{e7c98271-509c-4227-870c-3cb3245da266}">
|
|
||||||
<Declaration><![CDATA[{warning disable C0394}
|
|
||||||
METHOD TestMinClamping
|
|
||||||
VAR
|
|
||||||
// current ramp setpoint
|
|
||||||
_rSetpoint : REAL;
|
|
||||||
END_VAR
|
|
||||||
|
|
||||||
VAR CONSTANT
|
|
||||||
// expected clamped value
|
|
||||||
rExpected : REAL := 5;
|
|
||||||
|
|
||||||
// delta for assertion
|
|
||||||
rDelta : REAL := 0.0001;
|
|
||||||
|
|
||||||
// delay until clamping is reached
|
|
||||||
timDelayRamp : TIME := T#500MS;
|
|
||||||
|
|
||||||
// delay to check for value changes after clamping
|
|
||||||
timDelay : TIME := T#1S;
|
|
||||||
END_VAR]]></Declaration>
|
|
||||||
<Implementation>
|
|
||||||
<ST><![CDATA[TEST('TestMinClamping');
|
|
||||||
|
|
||||||
// init start at top cap
|
|
||||||
IF NOT _xInitMinClamp THEN
|
|
||||||
_fbRMPMinClamp.SetStart(10);
|
|
||||||
_xInitMinClamp := TRUE;
|
|
||||||
END_IF
|
|
||||||
|
|
||||||
// timer until until clamping is reach + timeBuffer afterwards to check whether is stays clamped or not
|
|
||||||
_fbDelayMinClamp(IN := TRUE, PT := timDelayRamp);
|
|
||||||
_fbDelayMinClampBuffer(IN := TRUE, PT := timDelay);
|
|
||||||
|
|
||||||
// run RampGenerator
|
|
||||||
_fbRMPMinClamp(
|
|
||||||
rTarget := 0,
|
|
||||||
rTargetMin := 5,
|
|
||||||
rTargetMax := 10,
|
|
||||||
timRampUp := T#500MS,
|
|
||||||
timRampDown := T#500MS,
|
|
||||||
rSetpoint => _rSetpoint,
|
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check for clamping
|
|
||||||
IF NOT _fbDelayMinClamp.Q THEN
|
|
||||||
// too early
|
|
||||||
AssertTrue(_rSetpoint >= (rExpected - rDelta), 'Clamped value reached before expected time');
|
|
||||||
ELSE
|
|
||||||
// after expected rampTime
|
|
||||||
IF NOT _fbDelayMinClampBuffer.Q THEN
|
|
||||||
AssertEquals_REAL(Expected := rExpected, Actual := _rSetpoint, Delta := rDelta, 'Value did not stay on or did not reach MinTarget');
|
|
||||||
ELSE
|
|
||||||
TEST_FINISHED();
|
|
||||||
END_IF
|
|
||||||
END_IF]]></ST>
|
END_IF]]></ST>
|
||||||
</Implementation>
|
</Implementation>
|
||||||
</Method>
|
</Method>
|
||||||
@@ -297,31 +129,30 @@ END_VAR
|
|||||||
|
|
||||||
VAR CONSTANT
|
VAR CONSTANT
|
||||||
// expected final value
|
// expected final value
|
||||||
rExpected : REAL := -9.4564;
|
rExpected : REAL := -0.8;
|
||||||
|
|
||||||
// delta for assertion
|
// delta for assertion
|
||||||
rDelta : REAL := 0.0001;
|
rDelta : REAL := 0.0001;
|
||||||
|
|
||||||
// delay until final value is reached
|
// delay until final value is reached
|
||||||
timDelay : TIME := T#470MS;
|
timDelay : TIME := T#790MS;
|
||||||
END_VAR]]></Declaration>
|
END_VAR]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[TEST('TestRampDownContinuity');
|
<ST><![CDATA[TEST('TestRampDownContinuity');
|
||||||
|
|
||||||
// ramp timer, calc speed & calc next expected ramp step
|
// ramp timer, calc speed & calc next expected ramp step
|
||||||
_fbDelayRampDownContinuity(IN := TRUE, PT := timDelay);
|
_fbDelayRampDownContinuity(IN := TRUE, PT := timDelay);
|
||||||
_rMyRampSpeed := 20 * (10 / TIME_TO_REAL(T#1S));
|
_rMyRampSpeed := 0.01;
|
||||||
_rNextExpectedDown := _rNextExpectedDown - _rMyRampSpeed;
|
_rNextExpectedDown := _rNextExpectedDown - _rMyRampSpeed;
|
||||||
|
|
||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPRampDownContinuity(
|
_fbRMPRampDownContinuity(
|
||||||
rTarget := -9.4564,
|
xEnable := TRUE,
|
||||||
rTargetMin := -10,
|
rTarget := -1,
|
||||||
rTargetMax := 10,
|
rRiseRate := 1,
|
||||||
timRampUp := T#1S,
|
rFallRate := 1,
|
||||||
timRampDown := T#1S,
|
rOut => _rSetpoint,
|
||||||
rSetpoint => _rSetpoint,
|
xBusy =>);
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check for current expected value
|
// check for current expected value
|
||||||
IF NOT _fbDelayRampDownContinuity.Q THEN
|
IF NOT _fbDelayRampDownContinuity.Q THEN
|
||||||
@@ -360,12 +191,10 @@ _fbDelayRampDownTime(IN := TRUE, PT := timDelay);
|
|||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPRampDownTime(
|
_fbRMPRampDownTime(
|
||||||
rTarget := -7.4367,
|
rTarget := -7.4367,
|
||||||
rTargetMin := -10,
|
rRiseRate := 20,
|
||||||
rTargetMax := 10,
|
rFallRate := 100,
|
||||||
timRampUp := T#500MS,
|
rOut => _rSetpoint,
|
||||||
timRampDown := T#100MS,
|
xBusy =>);
|
||||||
rSetpoint => _rSetpoint,
|
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check whether final value is reach on time or before
|
// check whether final value is reach on time or before
|
||||||
IF NOT _fbDelayRampDownTime.Q THEN
|
IF NOT _fbDelayRampDownTime.Q THEN
|
||||||
@@ -390,31 +219,30 @@ END_VAR
|
|||||||
|
|
||||||
VAR CONSTANT
|
VAR CONSTANT
|
||||||
// expected final value
|
// expected final value
|
||||||
rExpected : REAL := 8.673;
|
rExpected : REAL := 0.8;
|
||||||
|
|
||||||
// delta for assertions
|
// delta for assertions
|
||||||
rDelta : REAL := 0.0001;
|
rDelta : REAL := 0.0001;
|
||||||
|
|
||||||
// delay until final value is reached
|
// delay until final value is reached
|
||||||
timDelay : TIME := T#860MS;
|
timDelay : TIME := T#790MS;
|
||||||
END_VAR]]></Declaration>
|
END_VAR]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[TEST('TestRampUpContinuity');
|
<ST><![CDATA[TEST('TestRampUpContinuity');
|
||||||
|
|
||||||
// ramp timer, calc speed & calc next expected ramp step
|
// ramp timer, calc speed & calc next expected ramp step
|
||||||
_fbDelayRampUpContinuity(IN := TRUE, PT := timDelay);
|
_fbDelayRampUpContinuity(IN := TRUE, PT := timDelay);
|
||||||
_rMyRampSpeed := 16.567 * (10 / TIME_TO_REAL(T#1S650MS));
|
_rMyRampSpeed := 0.01;
|
||||||
_rNextExpectedUp := _rNextExpectedUp + _rMyRampSpeed;
|
_rNextExpectedUp := _rNextExpectedUp + _rMyRampSpeed;
|
||||||
|
|
||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPRampUpContinuity(
|
_fbRMPRampUpContinuity(
|
||||||
rTarget := 8.673,
|
xEnable := TRUE,
|
||||||
rTargetMin := -7,
|
rTarget := 2,
|
||||||
rTargetMax := 9.567,
|
rRiseRate := 1,
|
||||||
timRampUp := T#1S650MS,
|
rFallRate := 1,
|
||||||
timRampDown := T#1S,
|
rOut => _rSetpoint,
|
||||||
rSetpoint => _rSetpoint,
|
xBusy =>);
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check for current expected value
|
// check for current expected value
|
||||||
IF NOT _fbDelayRampUpContinuity.Q THEN
|
IF NOT _fbDelayRampUpContinuity.Q THEN
|
||||||
@@ -436,13 +264,13 @@ END_VAR
|
|||||||
|
|
||||||
VAR CONSTANT
|
VAR CONSTANT
|
||||||
// expected final value
|
// expected final value
|
||||||
rExpected : REAL := 8.3456;
|
rExpected : REAL := 0.55;
|
||||||
|
|
||||||
// delta for assertions
|
// delta for assertions
|
||||||
rDelta : REAL := 0.0001;
|
rDelta : REAL := 0.0001;
|
||||||
|
|
||||||
// delay until final value is reached
|
// delay until final value is reached
|
||||||
timDelay : TIME := T#440MS;
|
timDelay : TIME := T#550MS;
|
||||||
END_VAR]]></Declaration>
|
END_VAR]]></Declaration>
|
||||||
<Implementation>
|
<Implementation>
|
||||||
<ST><![CDATA[TEST('TestRampUpTime');
|
<ST><![CDATA[TEST('TestRampUpTime');
|
||||||
@@ -452,13 +280,12 @@ _fbDelayRampUpTime(IN := TRUE, PT := timDelay);
|
|||||||
|
|
||||||
// run RampGenerator
|
// run RampGenerator
|
||||||
_fbRMPRampUpTime(
|
_fbRMPRampUpTime(
|
||||||
rTarget := 8.3456,
|
rTarget := 0.55,
|
||||||
rTargetMin := -10,
|
xEnable := TRUE,
|
||||||
rTargetMax := 10,
|
rRiseRate := 1,
|
||||||
timRampUp := T#1S70MS,
|
rFallRate := 100,
|
||||||
timRampDown := T#100MS,
|
rOut => _rSetpoint,
|
||||||
rSetpoint => _rSetpoint,
|
xBusy =>);
|
||||||
xInTarget =>);
|
|
||||||
|
|
||||||
// check whether final value is reach on time or before
|
// check whether final value is reach on time or before
|
||||||
IF NOT _fbDelayRampUpTime.Q THEN
|
IF NOT _fbDelayRampUpTime.Q THEN
|
||||||
|
|||||||
Reference in New Issue
Block a user