Introducción

Los lenguajes de programación de autómatas programables normalizados por el estándar IEC 61131-3 constituyen una base fundamental para el desarrollo de aplicaciones industriales, permitiendo flexibilidad y adaptación a distintos perfiles de programadores y tareas de automatización. Este estándar reconoce cinco lenguajes principales: Diagrama de Contactos (LD), Lista de Instrucciones (IL), Texto Estructurado (ST), Diagrama de Bloques de Funciones (FBD) y Gráfico de Funciones Secuenciales (SFC). Cada uno de ellos presenta características propias que los hacen más o menos adecuados para determinadas aplicaciones y entornos de programación.

Diagrama de Contactos (LD, Ladder Diagram)

El Diagrama de Contactos es uno de los lenguajes más difundidos en la industria, especialmente en el ámbito de la automatización eléctrica. Representa gráficamente los circuitos de control mediante elementos similares a los utilizados en esquemas eléctricos, como contactos, bobinas y temporizadores. Esta analogía facilita la comprensión y el diseño por parte de técnicos y electricistas, ya que pueden trasladar sus conocimientos previos de esquemas de relés al entorno PLC. Entre sus ventajas destacan la claridad visual, la fácil depuración y la rapidez para modificar circuitos sencillos. Se utiliza habitualmente en aplicaciones de control secuencial, arranques de motores, interbloqueos y sistemas de alarmas. Los entornos de programación suelen ofrecer editores gráficos basados en arrastrar y soltar, lo que agiliza el desarrollo.

3.5.1. Lista de Instrucciones (IL, Instruction List)

La Lista de Instrucciones es un lenguaje textual muy similar al ensamblador, donde cada línea representa una instrucción básica que ejecuta el autómata, como cargar, comparar, saltar o activar salidas. Su principal ventaja es la posibilidad de programar secuencias rápidas y compactas, con un control detallado sobre el flujo de ejecución. Es apropiado para programadores experimentados que requieran optimizar recursos, aunque resulta menos intuitivo que otros lenguajes para quienes no tienen experiencia en programación a bajo nivel. Su uso ha decaído en la industria, pero aún es útil en aplicaciones donde la eficiencia y el control son prioritarios, como en tareas de procesamiento rápido de señales o en sistemas embebidos.

Las instrucciones típicas de IL incluyen:

  • LD (Load): Carga un valor en el acumulador.
  • AND, OR, XOR: Operaciones lógicas con el acumulador.
  • ADD, SUB, MUL, DIV: Operaciones aritméticas.
  • ST (Store): Almacena el valor del acumulador en una variable.
  • JMP, JMPC, JMPCN: Saltos condicionales e incondicionales.

A continuación se muestra un ejemplo de código IL que implementa un temporizador simple:

// Temporizador en IL
LD  I0.0          // Cargar entrada de inicio
AND I0.1          // Y entrada de habilitación
JMPC START_TIMER  // Si ambas verdaderas, saltar a START_TIMER
JMP   END         // Si no, ir al final

START_TIMER:
LD  T1.Q          // Cargar salida del temporizador
JMPC TIMER_DONE   // Si temporizador ha terminado, saltar
LD  10            // Cargar tiempo de preset (10)
TON T1, PT        // Temporizador a la carta
JMP  END

TIMER_DONE:
ST  Q0.0          // Activar salida

END:
// Fin del programa
                

Aunque este lenguaje es potente, la tendencia actual es usar lenguajes más estructurados como ST o gráficos como FBD.

Captura de entorno de programación IEC 61131-3 mostrando los cinco lenguajes: LD (Diagrama de Escalera), FBD (Diagrama de Bloques de Función), ST (Texto Estructurado), IL (Lista de Instrucciones) y SFC (Diagrama de Funciones Secuencial).
Figura 1: Los cinco lenguajes de programación definidos por la norma IEC 61131-3, ilustrados con el mismo ejemplo de control de motor: ① LD (Diagrama de Escalera), ② FBD (Bloques de Función), ③ ST (Texto Estructurado), ④ IL (Lista de Instrucciones — eliminado en ed. 4) y ⑤ SFC (GRAFCET). Fuente: Elaboración propia. Licencia: CC BY-NC 4.0

Texto Estructurado (ST, Structured Text)

El Texto Estructurado es un lenguaje de alto nivel, similar a Pascal o C, que permite escribir algoritmos complejos mediante estructuras de control como bucles, condicionales y funciones. Su sintaxis facilita la programación de operaciones matemáticas, manipulación de cadenas y gestión de datos complejos. Entre sus ventajas destacan la potencia expresiva, la facilidad para modularizar el código y la adecuación para tareas complejas, como cálculos avanzados, gestión de recetas o comunicación con otros sistemas. Es ideal para ingenieros informáticos o programadores familiarizados con lenguajes convencionales. Los entornos de desarrollo suelen ofrecer editores de texto con resaltado de sintaxis y herramientas para la depuración paso a paso.

Diagrama de Bloques de Funciones (FBD, Function Block Diagram)

El Diagrama de Bloques de Funciones es un lenguaje gráfico en el que el programa se construye interconectando bloques funcionales, cada uno de los cuales realiza una tarea específica, como operaciones lógicas, temporizadores, contadores o cálculos matemáticos. Los bloques se conectan mediante líneas que representan el flujo de señales o datos. Ofrece una visión modular y facilita la reutilización de componentes, siendo muy adecuado para procesos continuos, automatización de plantas y sistemas que requieren integración de múltiples funciones. Su principal ventaja es la facilidad para diseñar y visualizar sistemas complejos mediante la composición de bloques. Los entornos de programación proporcionan bibliotecas de bloques estándar y personalizados, permitiendo arrastrar y conectar elementos de forma intuitiva.

Gráfico de Funciones Secuenciales (SFC, Sequential Function Chart)

El Gráfico de Funciones Secuenciales, también conocido como Funciones Lógicas, permite describir procesos secuenciales mediante etapas (steps) y transiciones (transitions). Cada etapa representa un estado del sistema y las transiciones definen las condiciones bajo las cuales se avanza de un estado a otro. Es particularmente útil para el control de procesos por lotes, secuencias de máquinas o sistemas en los que el orden de las operaciones es fundamental. Su ventaja principal es la claridad en la representación del flujo de procesos, facilitando el diseño, documentación y mantenimiento. Los entornos de desarrollo ofrecen herramientas gráficas para definir las etapas, asociar acciones y establecer condiciones de transición.

Elección y combinación de lenguajes

La elección del lenguaje más adecuado depende del tipo de aplicación, el perfil del programador y las características del proyecto. La IEC 61131-3 permite incluso combinar varios lenguajes dentro de un mismo proyecto, aprovechando las ventajas de cada uno. Los principales entornos de programación, como TIA Portal, Codesys o RSLogix, ofrecen soporte completo para estos lenguajes, permitiendo a los usuarios seleccionar el más conveniente en cada caso.

🐍 Ejemplo de código Python: Implementación de un PID en estilo Texto Estructurado (ST)
# ============================================================
# SIMULACIÓN DE UN ALGORITMO PID EN PYTHON (ESTILO ST)
# ============================================================
# Este programa implementa un controlador PID simple, similar
# a cómo se programaría en Texto Estructurado (ST) en un PLC.
#
# Se definen las variables (muchas de ellas persistentes, como
# en un PLC). El bucle principal simula el ciclo de escaneo.
#
# Ejecútalo en Thonny para ver cómo evoluciona la salida ante
# cambios en la consigna y en la variable de proceso.
# ============================================================

import time
import matplotlib.pyplot as plt
from collections import deque

# ------------------------------------------------------------
# 1. DEFINICIÓN DE VARIABLES (SIMULA MEMORIA DEL PLC)
# ------------------------------------------------------------
# Variables de entrada (desde sensores)
setpoint = 50.0          # Consigna (temperatura deseada, por ejemplo)
proceso = 20.0           # Variable de proceso (temperatura actual)
                          # En un PLC real, esto se leería de una entrada analógica

# Variables de salida (hacia actuador)
salida = 0.0             # Señal de control (por ejemplo, 0-100%)

# Parámetros del PID (ajustados manualmente)
Kp = 2.0                 # Ganancia proporcional
Ki = 0.5                 # Ganancia integral
Kd = 1.0                 # Ganancia derivativa

# Variables internas del PID (persistentes entre ciclos)
error_anterior = 0.0
integral = 0.0
derivada = 0.0
tiempo_anterior = time.time()

# Para registrar el comportamiento (no es parte del PID, solo para visualización)
historial_tiempo = []
historial_proceso = []
historial_salida = []
historial_setpoint = []

# ------------------------------------------------------------
# 2. FUNCIÓN PID (SIMULA UN BLOQUE FUNCIONAL EN ST)
# ------------------------------------------------------------
def calcular_pid(setpoint, proceso, dt):
    """Calcula la salida PID en función de la consigna y el proceso.
       Equivalente a un bloque funcional en FBD o ST.
       Utiliza variables persistentes: error_anterior, integral.
       Se llama en cada ciclo de escaneo.
    """
    global error_anterior, integral
    
    # Error actual
    error = setpoint - proceso
    
    # Término proporcional
    P = Kp * error
    
    # Término integral (acumulación con anti-windup simple)
    integral += error * dt
    I = Ki * integral
    
    # Término derivativo (usamos diferencia finita)
    if dt > 0:
        derivada = (error - error_anterior) / dt
    else:
        derivada = 0
    D = Kd * derivada
    
    # Salida total
    salida = P + I + D
    
    # Saturación de la salida (ej. 0-100%)
    if salida > 100:
        salida = 100
        # Anti-windup: no acumular si estamos saturados
        integral -= error * dt
    elif salida < 0:
        salida = 0
        integral -= error * dt
    
    # Actualizar error anterior para el próximo ciclo
    error_anterior = error
    
    return salida

# ------------------------------------------------------------
# 3. SIMULACIÓN DE UN PROCESO SIMPLE (PLANTA)
# ------------------------------------------------------------
def simular_planta(salida_control):
    """Simula la respuesta de una planta térmica simple.
       En un PLC real, la planta sería el sistema físico.
    """
    global proceso
    # Modelo muy simple: la temperatura cambia según la salida de control
    # con una inercia y tiempo muerto
    proceso = proceso + (salida_control - proceso) * 0.05
    return proceso

# ------------------------------------------------------------
# 4. CICLO PRINCIPAL (SIMULA EL CICLO DE ESCANEO DEL PLC)
# ------------------------------------------------------------
def ciclo_principal(duracion_total=60, dt_ciclo=0.1):
    """Ejecuta el control PID durante 'duracion_total' segundos,
       con un tiempo de ciclo de 'dt_ciclo' segundos.
    """
    global tiempo_anterior, setpoint, proceso, salida
    
    print("🎛️ INICIO DE SIMULACIÓN PID")
    print("="*50)
    
    # Número de ciclos
    num_ciclos = int(duracion_total / dt_ciclo)
    
    for i in range(num_ciclos):
        # Tomar tiempo actual para cálculo de dt
        tiempo_actual = i * dt_ciclo
        
        # Calcular dt (en un PLC real, esto sería el tiempo de ciclo)
        dt = dt_ciclo
        
        # 1. Leer entradas (simulado)
        # Aquí podríamos cambiar la consigna en cierto momento
        if tiempo_actual > 20 and tiempo_actual < 40:
            setpoint = 70.0   # Cambio de consigna
        else:
            setpoint = 50.0
        
        # 2. Ejecutar PID
        salida = calcular_pid(setpoint, proceso, dt)
        
        # 3. Actualizar planta con la salida de control
        proceso = simular_planta(salida)
        
        # 4. Registrar datos para gráfica
        historial_tiempo.append(tiempo_actual)
        historial_proceso.append(proceso)
        historial_salida.append(salida)
        historial_setpoint.append(setpoint)
        
        # Mostrar cada cierto tiempo
        if i % 100 == 0:
            print(f"Tiempo: {tiempo_actual:.1f}s | SP: {setpoint:.1f} | PV: {proceso:.2f} | Salida: {salida:.2f}")
        
        # Esperar para simular el tiempo de ciclo (solo para no saturar)
        # En un PLC real no hay sleep, es continuo.
        time.sleep(dt * 0.01)  # Reducido para que la simulación sea rápida
    
    print("="*50)
    print("✅ SIMULACIÓN FINALIZADA")
    
    # Opcional: mostrar gráfica
    plt.figure(figsize=(10,5))
    plt.plot(historial_tiempo, historial_setpoint, 'r--', label='Setpoint')
    plt.plot(historial_tiempo, historial_proceso, 'b-', label='Proceso')
    plt.plot(historial_tiempo, historial_salida, 'g-', label='Salida PID')
    plt.xlabel('Tiempo (s)')
    plt.ylabel('Valor')
    plt.legend()
    plt.title('Simulación de control PID')
    plt.grid(True)
    plt.show()

# ------------------------------------------------------------
# 5. PUNTO DE ENTRADA PRINCIPAL
# ------------------------------------------------------------
if __name__ == "__main__":
    ciclo_principal(duracion_total=60, dt_ciclo=0.1)

Este código implementa un controlador PID en Python, simulando la estructura que se usaría en Texto Estructurado (ST) dentro de un PLC. Se definen variables persistentes (como la integral), se calcula la salida en cada ciclo y se actualiza la planta. Ejecútalo en Thonny para ver la evolución de las variables y la gráfica final.

Tendencias Actuales 2026

La evolución de los lenguajes de programación de PLC apunta hacia una mayor integración con entornos de desarrollo basados en la web y la nube. Plataformas como Codesys WebVisu y Siemens Openness permiten programar y visualizar procesos desde cualquier lugar. Además, la norma IEC 61131-3 está siendo ampliada para incluir conceptos de programación orientada a objetos y soporte para inteligencia artificial en el borde (edge computing).

Aplicaciones con Raspberry Pi

La Raspberry Pi puede programarse en Python para simular cualquiera de los lenguajes IEC 61131-3. Por ejemplo, se pueden crear librerías que emulen bloques funcionales (FBD) o implementar máquinas de estados (SFC) para controlar robots o procesos. Es una excelente plataforma para aprender y prototipar antes de implementar en PLC industriales.

Aplicaciones con Arduino

Arduino, con su lenguaje basado en C++, puede asimilarse al Texto Estructurado (ST). Es posible programar algoritmos complejos (como PID) y utilizar la plataforma para controlar pequeños automatismos, siendo una alternativa de bajo coste para formación y prototipado rápido.

💼 Caso Práctico Industrial

Contexto: Una planta de producción necesita programar un algoritmo de control de temperatura muy preciso que requiere cálculos matemáticos complejos y la implementación de un filtro digital. El equipo de programación está formado por ingenieros informáticos con experiencia en lenguajes de alto nivel.

Problema: ¿Qué lenguaje de la norma IEC 61131-3 sería el más adecuado para esta tarea?

Pregunta: Selecciona la opción correcta:

🍓 Caso Práctico Raspberry Pi

Contexto: Estás programando una Raspberry Pi para controlar un pequeño robot. Necesitas implementar una máquina de estados para el comportamiento del robot (buscar objeto, acercarse, agarrar, retroceder).

Problema: ¿Qué lenguaje de programación (de los IEC 61131-3) es conceptualmente más similar a la implementación de una máquina de estados en Python?

Pregunta: Elige la opción más adecuada:

🐍 Caso Práctico Python

Contexto: En el código del PID en Python, se utiliza una variable `integral` que se acumula en cada ciclo. Para evitar que este valor crezca indefinidamente cuando la salida está saturada, se implementa una técnica llamada anti-windup.

Problema: ¿En qué parte del código se aplica el anti-windup?

Pregunta: Selecciona la opción correcta:

📚 Recursos Técnicos y Normativos 2026

Normativas y Estándares

  • IEC 61131-3 - Norma de lenguajes de programación.
  • PLCopen - Organización para la estandarización.

Recursos Raspberry Pi y Python