<contentHeadername="Anjlab Code Box"version="3.5.17.3"modificationDateTime="2025-07-18T09:54:53.7808919"organization="Anjlab"author="Sergey A Glukhov">
<Comment>Comprehensive PLC Utility Library for CoDeSys</Comment>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> This function block implements a digital input debouncer using both TON and TOF timers. It filters signal noise on both rising and falling edges.</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtmlxmlns="http://www.w3.org/1999/xhtml">// Rising edge handling — start TON if input is TRUE and output is still FALSE
tonTimer(IN := inputSignal AND NOT debouncedOutput, PT := onDelay);
// Falling edge handling — start TOF if input is FALSE and output is still TRUE
tofTimer(IN := NOT inputSignal AND debouncedOutput, PT := offDelay);
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> One-cycle pulse on rising edge</xhtml>
</documentation>
</variable>
<variablename="fallingEdge">
<type>
<BOOL />
</type>
<documentation>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> One-cycle pulse on falling edge</xhtml>
</documentation>
</variable>
</outputVars>
<localVars>
<variablename="fbDebounceBool">
<type>
<derivedname="DebounceBool" />
</type>
</variable>
<variablename="prevDebounced">
<type>
<BOOL />
</type>
<initialValue>
<simpleValuevalue="FALSE" />
</initialValue>
<documentation>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> Previous state of debounced output</xhtml>
</documentation>
</variable>
</localVars>
<documentation>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> Uses DebounceBool internally to filter input signal, then detects rising and falling edges on filtered signal.</xhtml>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> Filtered output value </xhtml>
</documentation>
</variable>
</outputVars>
<localVars>
<variablename="isInitialized">
<type>
<BOOL />
</type>
</variable>
<variablename="buffer">
<type>
<array>
<dimensionlower="1"upper="1000" />
<baseType>
<WORD />
</baseType>
</array>
</type>
</variable>
<variablename="counter">
<type>
<UINT />
</type>
</variable>
<variablename="sum">
<type>
<DINT />
</type>
</variable>
</localVars>
<documentation>
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> This function stores up to 32 values in a buffer and outputs the average value. You can decide how many values to store to get the average number.</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtmlxmlns="http://www.w3.org/1999/xhtml">// limit the bufferSize
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> creates a PWM signal of a given frequency with a ratio offset. Each PWM cycle can be divided into 2 phases: Ton (on time) and Toff (off time).
The ratio is set from 0 to 1. For example, a ratio of 0.5 will divide the time of each PWM cycle into 50% for Ton and 50% for Toff .</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtmlxmlns="http://www.w3.org/1999/xhtml">// If the PWM frequency is 0, then we interrupt the execution of the FB
IF frequency <= 0.0 THEN
output := FALSE;
RETURN;
END_IF;
// Calculate how many milliseconds are required for one PWM cycle
tempValue := 1000.0 / frequency;
// Launching the signal generator
clock(pulseTime := REAL_TO_TIME(tempValue));
// We create a sustained pulse for the required time
<xhtmlxmlns="http://www.w3.org/1999/xhtml"> Creates PWM signal with specified Ton phase time. For example, we can set F to 100 times per second. This means one PWM cycle will be 10
milliseconds. Now if we set PW to T#5ms, we'll get equal time for Ton and Toff phases at 50%.</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtmlxmlns="http://www.w3.org/1999/xhtml">// If the PWM frequency is 0 or the time of one cycle is less than the time for the Ton phase, then we interrupt the execution of the FB
IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN