Introduction to the Modicon PLC UDFB

Many PLC programmers have experience with Arduino

Many PLC programmers started their electronics journey by completing a microcontroller class. Your first program was likely the classic “hello world” or blinking an LED attached to an Arduino. Those skills provide an excellent foundation for seemingly unrelated programming environments including the Programmable Logic Controller (PLC).

We will leverage this prior knowledge by walking from the Arduino map( ) function to a similar Ladder Logic (LL) based map function. Inside the PLC, this map function will be implemented as a User Defined Function Block (UDFB). Our discussion is framed using the popular Schneider Electric Modicon PLC. The lesson is generally applicable to most LL programmed PLC, however the specific implementation details will be different.

The testbed for this application is shown in Figure 1. Here we see a Schneider TM221CE24T Modicon PLC driving a Banner K50 Pro Touch Button.

Figure 1: Schneider Modicon PLC driving a Banner K50 Pro Touch Button.

Apply Arduino skills to the PLC

Before delving into the PLC implementation, we first explore three fundamental concepts using the Arduino lens. This includes:

  • a review of the components of a function
  • and finally the concept of dot notation
  • the mathematics of the map( ) function

After reviewing these C programming concepts you will find that the fundamentals are directly applicable to the Modicon based UDFB. Perhaps you will agree that LL and C are closer than you originally thought. In the future you may find this expanded perspective provides a perfect foundation for PLC programming using structured text.

Components of a function

Recall that a function serves to encapsulate a collection of C statements. Perhaps you once programmed an Arduino function to blink an LED N time. Recall that the function had a name such as blinkLED. It likely had parameters such as N to indicate the number of times to blink the LED. You may have passed other parameters for the on-time and off-time for the LED. You may even have parameterized the I/O pin.

void LEDblink(int pin, int N, long msOnTime, long msOffTime) {
    pinMode(pin, OUTPUT);
    for (int i = 0; i < N; i++) {
        digitalWrite(pin, HIGH);
        digitalWrite(pin, LOW);

Tech Tip: While a C function can have one and only one return type, we can use indirect addressing to expand the number of terms. For indirect addressing, we pass the address of an array or structure to the function. Our function can access all elements within the array or structure. The total number of elements is limited by the memory and architecture of the associated microcontroller.

Structures and dot notation

Before we transition to the PLC we should explore dot notation as used in C programming. Please consider this code:

typedef struct {                    // Structure definition
    float minVoltage;
    float maxVoltage;
    float deviation;
} Status;

Status CellStatus;                 // instance of the structure

Observe that last line of code creates an instance of the Status structure. The structure contains the fields minVoltage, maxVoltage, and deviation. To access individual fields within the structure, we use dot notation. For example:

CellStatus.minVoltage = 13.8;
float maxVoltage = CellStatus.maxVoltage;

In each case we see the structure name followed by a dot followed by the field of interest.

Arduino map( ) function

We have one last concept to explore before addressing the PLC UDFB. Specifically, we explore the math operation of the map function from an Arduino perspective before implementing it in the PLC.

The Arduino map( ) function is an application of algebra relating to the equations of a line:

y = mx + b (slope-intercept form)

y – y_1 = m(x – x_1) (point-slope equation)

In Arduino, you likely used the map( ) function to scale an analog input from the Arduino’s Analog To Digital (ADC).

int rawADCval = analogRead(0);
int HumanReadableVoltage = map(rawADCval, 0, 1023, 0, 5); //Assume a 5 VDC ADC reference

In English, this says the ADC output of 0 to 1023 maps to 0 to 5 VDC. However, there is a big problem as only voltages 0, 1, 2, 3, 4, and 5 are allowed. This is a limitation of integer data types and will be momentarily rectified using type float.

The map( ) function itself is defined as:

long map(long x, long in_min, long in_max, long out_min, long out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

Close examination of the map( ) function shows that it implements the point slope equation:

y \ – y_1 = m(x\ – x_1)


m = \dfrac{out\_max - out\_min} {in\_max - in\_min}


y = \dfrac{out\_max - out\_min}{in\_max - in\_min} (x - in\_min) + out\_min;

Modify the Arduino map function for floating point

Personally, I prefer to construct a function that operates using floating point types. This is easily done by changing the function data type as shown below. This small change eliminates the previously mentioned integer math problem.

float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
float rawADCval = analogRead(0);
int HumanReadableVoltage = fmap(rawADCval, 0.0, 1023.0, 0.0, 5.0);

Introduction to the Modicon User Defined Function Block (UDFB)

At this point, we have reviewed fundamental programming concepts as related to the mapping (scaling) function including:

  • the parts of a function
  • names of function components
  • structures
  • limitations of data types
  • dot notation
  • point-slope equation

We are now ready to construct a ladder logic based UDFB for the Modicon PLC. The UDFB is presented in Figure 2. The UDFB definition consists of two parts. The UDFB name, Boolean inputs, and parameters are shown in the lower Figure 2. The ladder logic is presented in the upper part of Figure 2.

Figure 2: User Defined Function Block for the Modicon FMAP.

Enable (EN) and Enable Output (ENO) are used to hang the UDFB on a rung

As an obvious statement, all ladder logic elements are “hung on a rung” as shown in the Figure 3 rung #2 instantiation of the FMAP UDFB. This important operation is established (defined) in the lower part of figure 2. Here we see the enable (EN) and Enable-Output (ENO) pair. In Figure 2 rung # we see that the ENO is a copy of the EN signal. Stated another way, the ENO signal for the block will evaluate as true if the EN signal is present. In the future, this allows us to place many such blocks on the same rung with each downstream block receiving a copy of the enable signal.

Tech Tip: There are several different “hanging” input and output pairs associated with the UDFB.

  • This example is the traditional EN / ENO pair. The block will only function if it is enabled and the ENO is a direct copy of the EN signal.

  • The level sensitive pair includes an EN signal and a VALID. The block will only function when it is enabled. The VALID signal will be asserted when the UDFB has completed the designated operation. A Directional Control Value (DCV) is a good example. The UDFB will signal the DCV to toggle upon receipt of the EN signal. The VALID signal will be asserted sometime later when the monitored cylinder has moved to the proper position. A BUSY output signal is often included.

  • The edge sensitive UDFB contains a trigger (TRIG) and a DONE pair. Upon receipt of the TRIG input, the UDFB will perform its assigned task. The UDFB will pulse the DONE output when the task is complete. Like the level sensitive UDFB, the edge sensitive UFDB also features a BUSY output signal. In addition, it often features an ABORT or RESET input to undo the TRIG. As an example, consider a game such as Simon Says. An edge sensitive UDFB could be used for the computer playback. When complete, this could trigger another edge sensitive UDFB for the user playback.

The operation of this traditional UDFB is based on the EN signal.

The EN signal is used to enables the various UDFB math calculations. We see this in all rungs of Figure 2 with the EN contacts at the beginning of each rung. In English we say that the UDFB’s output will be updated if, and only if, it is enabled via the EN line. This can be a be confusing as there is an implicit memory operation such that the last value with be held when the EN signal is absent. This is one of the first things to test is a traditional UDFB is not updating.

Tech Tip: The implicit memory associated with a traditional UDFB can be a beneficial attribute. It allows a periodic pulse to momentarily update the UDFB output. For example, a UFB used in a process controller may be commanded to update and hold its output value on a Pulse Per Second (PPS) signal.

UDFB parameters

Figure 2 presents the parameters associated with the UDFB. The term “parameter” could loosely be interpreted as a memory structure associated with the UDFB. This is an important distinction for several reasons:

  • The parameters type acts as BOTH the input and output for all non-Boolean UDFB outputs. In this particular UDFB we use type float for all the line equation calculation.

  • The “parameters” are accessed via using the dot notation as shown in Figure 4.

  • When the UDFB is instantiated, each instantiation is associated with memory. Behind the scenes, this acts like the “Status CellStatus;” construct presented earlier in the article. This operation also explains how each UDFB has its own parameters and internal variable.

UDFB Math operation

Figure 2 rungs #1 and #2 show the UDFB implementation of the FMAP function we explored earlier in this article. Note that we are using two operand math operations. For example, delta output (D_OUT) is the difference between the OUT_MAX and OUT_MIN. Likewise D_IN = IN_MAX – IN_MIN. The slope (M) is calculated as D_OUT / D_IN. The remainder of the operations continue the slope intercept equation solving for Y for a given X input.

How to instantiate the UDFB

We started this article with an introduction to the Arduino. Specifically, we looked at the equation of a line, the parts of a function, and dot notation. At this point in our conversation, we have successfully compared a function to a UDFB. We have also seen similarities between the mechanics of a C function and a UDFB with the understanding that the UDFB takes liberties with the term parameter using it to describe both inputs and outputs. Finally, we have implied that each UDFB instantiation is associated with its own structure-like memory object. We are now ready to instantiate the UDFB and use dot notation.

The actual hung-on-a-rung instantiation of the FMAP UDFB is show in Figure 3 rung 2. The UDFB is supported by the operation block shown on rungs #0 and #1. For example. The first block on rung #1 loads the constant value 0.0 into %FMAP0.IN_MIN memory location. You will recognize the dot operator used to access member (variables) associated with the instantiated UDFB.

Given this notation and memory structure we can safely say that the Schneider’s Machine Expert handles the UDFB in the same way C++ handles an object. Both programming languages perform an encapsulation.

What is the purpose for the UDFB in this example?

The full purpose of this UDFB is to convert the Modicon PLC’s Analog to Digital Converter (ADC) value to a human readable value. On rung #0 of Figure 3, we see the raw value of the ADC has a count of 533. Recall that the Modicon ADC is configured to provide a full scale 0 to 10 VDC to 0 to 1000. On rung #3 we see an operation block immediately to the right of the UDFB. Note that the value has been scaled to a floating-point value of 5.33.

To be sure, this UDFB example is over designed. It is true that a simple divide by 10 operations block could have been used. However, suppose the voltage represents physical system pressure such that 1 to 7 VDC scales to 30 to 90 psi. In this situation, we should use two FMAP UDFBs. The first should convert the signal to a human readable format. The second can then map this human readable floating-point value into the corresponding psi. This two-block structure maximizes readability for future technicians. For example, using a voltmeter, the technician can read the real-world voltage on the face of the PLC. They can then see the corresponding value inside the PLC code.

Tech Tip: Many PLC programming environments allow a Function Block (UDF) and a User Defined Function Block (UDFB). These are similar except when it comes to encapsulation. Each instantiation of a UDFB has its own memory structure while a FB has none. As an example, understand that we would not be able to use the previously mentioned set-and-remember functionality if a FB was used.

Figure 3: The FMAP UFDB is hung on rung 2. The scale parameters are loaded on rung 1 using dot notation. Also, the raw ADC values are loaded on rung 1.

Tech Tip: Use great care when implementing a UDFB. Always remember the lifecycle of a PLC is measured in decades. Years from now, long after the originally programmer is gone, technicians and engineers will troubleshoot and modify the code. Clear documentation and singularity of purpose are essential attributes of a UDFB. Stated another way, program for clarity. Don’t be clever!


The User Defined Function Block (UDFB) is the PLC equivalent to the “C” function. Both provide a way of encapsulating commonly used code providing a relatively easy to read hierarchical code structure. This abstracts the lower levels allowing the programmer and future industrial technicians to easily follow the program flow. Both software constructs allow the programmer to save considerable time as they can choose robust and fully debugged software from their library.

Best Wishes,


About the Author

Aaron Dahlen, LCDR USCG (Ret.), serves as an application engineer at DigiKey. He has a unique electronics and automation foundation built over a 27-year military career as a technician and engineer which was further enhanced by 12 years of teaching (interwoven). With an MSEE degree from Minnesota State University, Mankato, Dahlen has taught in an ABET accredited EE program, served as the program coordinator for an EET program, and taught component-level repair to military electronics technicians. Dahlen has returned to his Northern Minnesota home and thoroughly enjoys researching and writing articles such as this. LinkedIn | Aaron Dahlen - Application Engineer - DigiKey

Return to the Industrial Control and Automation Index