Introducción al lenguaje Ladder

El diagrama de contactos (Ladder Diagram, LD) es, sin duda, el lenguaje más extendido en la programación de PLC (Controladores Lógicos Programables). Su éxito radica en su parecido con los esquemas eléctricos de control por relés, lo que permite a electricistas e ingenieros de automatización realizar la transición al mundo programable de forma natural. La norma IEC 61131-3 estandariza este lenguaje, garantizando su compatibilidad entre fabricantes (Siemens, Rockwell, Schneider, etc.).

Un programa en Ladder se organiza visualmente como una escalera: dos barras verticales (fase izquierda y neutro/derecha) y entre ellas los peldaños (rungs). Cada peldaño implementa una operación lógica: cuando la combinación de contactos permite el paso de corriente (estado TRUE), se activan las bobinas o bloques funcionales conectados a la derecha.

Ejemplo industrial real: en una cinta transportadora, un sensor inductivo (contacto NA) detecta una caja y, si no hay una orden de parada (contacto NC del pulsador de emergencia), activa un motor (bobina). Esta lógica se representa con un solo peldaño de dos contactos en serie.

Elementos fundamentales del lenguaje Ladder

Los componentes gráficos se clasifican en contactos, bobinas y bloques funcionales. A continuación se describen los más habituales con su simbología normalizada IEC 60617.

Contactos: normalmente abiertos (NO) y normalmente cerrados (NC)

Los contactos representan entradas, marcas internas o estados del sistema. Su estado se evalúa en tiempo de ejecución.

  • —| |— Contacto NA (Normalmente Abierto): conduce si la variable asociada es TRUE (1 lógico). Ejemplo: X0 (entrada digital).
  • —|/|— Contacto NC (Normalmente Cerrado): conduce si la variable es FALSE (0). Útil para emergencias o condiciones inversas.

Ejemplo paso a paso: si un pulsador de marcha (X0) está presionado y un final de carrera (X1) NO está actuado, el contacto NC de X1 permitirá el paso. Esto se traduce en una condición AND con negación.

Bobinas (salidas y marcas auxiliares)

—( )— Bobina: se activa (TRUE) cuando el flujo de corriente en el peldaño alcanza su posición. Representa salidas físicas (Y0), marcas internas (M0) o incluso bobinas de enclavamiento. También existen bobinas especiales como SET y RESET (enclavamiento).

Aplicación industrial: en un motor con arranque/paro, la bobina Y1 se enclava mediante un contacto auxiliar del mismo Y1 (realimentación).

Temporizadores (Timers) y contadores (Counters)

Estos bloques funcionales se insertan como elementos complejos dentro del peldaño. Los más comunes:

  • TON (Timer ON-Delay): retardo a la conexión. Cuando la entrada se activa, comienza a contar el tiempo base (por ejemplo, 1 s). Al alcanzar el valor prefijado (PT), la salida Q se pone a TRUE.
  • TOF (Timer OFF-Delay): retardo a la desconexión.
  • CTU (Counter Up): contador ascendente. Incrementa cada flanco de entrada y activa la salida cuando alcanza el valor PV.

Datos técnicos: en la mayoría de PLCs, los temporizadores usan una base de tiempo de 1 ms, 10 ms o 100 ms, con rango de 0 a 65535 o valores superiores (dependiendo del fabricante).

Entorno de programación Ladder (CODESYS V3.5) con un peldaño (rung) que contiene contactos NA X0 y X1 en serie, una rama en paralelo con contacto NA X2, un bloque TON (tTimer) con constante PT#5s y una bobina Y0. Se muestran valores de simulación (X0=TRUE, X1=TRUE, X2=FALSE, Y0=FALSE), anotaciones numeradas y el flujo de energía activo.
Figura 2: Ejemplo de rung Ladder en CODESYS V3.5 con: contactos NA X0 y X1 en serie (rama principal), contacto NA X2 en paralelo (bypass), bloque TON (tTimer, PT:=T#5s) y bobina Y0 activa cuando el temporizador alcanza el tiempo de retardo. El flujo de energía activo se indica en ámbar; la salida Y0 permanece FALSE hasta que ET ≥ PT (5 segundos). Fuente: Elaboración propia. Licencia: CC BY-NC 4.0

Ejemplo completo: arranque/paro con enclavamiento

El clásico circuito de arranque/paro se implementa con un contacto NA de marcha (X0), un contacto NC de paro (X1) y la bobina del motor (Y0) con un contacto auxiliar NA de Y0 en paralelo a X0 para el enclavamiento.

     X0      X1        Y0
----| |------|/|-------( )----
    |                |
    |      Y0        |
    +------| |-------+
        

Esta estructura permite que, una vez pulsado X0, el motor se mantenga activo hasta que se pulse X1 o se desactive por otra condición.

Evaluación de peldaños y flujo de corriente

El PLC ejecuta cíclicamente el programa: lee entradas, evalúa la lógica de los peldaños de arriba abajo, y actualiza las salidas. En cada peldaño, el flujo de corriente se simula desde la barra izquierda hacia la derecha, recorriendo las ramificaciones en serie/paralelo.

Ejemplo de evaluación paso a paso: supongamos el peldaño anterior con X0=0, Y0=1 (ya enclavado) y X1=0. El flujo pasa por Y0 (cerrado) y X1 (NC cerrado), activando Y0. Si en un ciclo X1=1 (paro), el contacto NC se abre, interrumpe el flujo y Y0 se desactiva.

Para lógica más compleja, se utilizan ramas en paralelo (OR) y ramas en serie (AND). Los bloques funcionales (temporizadores, contadores) se evalúan como subrutinas que actualizan sus salidas internas.

🐍 Simulación de un rung Ladder en Python (con contactos y bobina)
# ladder_rung.py - Simula la evaluación de un peldaño Ladder con enclavamiento
# Se puede probar en Thonny y adaptar a Raspberry Pi (GPIO como entradas/salidas)

# Definición de variables (simulan entradas y salidas físicas)
# En un PLC real serían %I0.0, %Q0.0, etc.
entradas = {'X0': False,   # pulsador marcha (NA)
            'X1': False}   # pulsador paro  (NC)
salidas  = {'Y0': False}   # motor / bobina

# Realimentación: el estado de Y0 se usa como contacto auxiliar
def evaluar_peldano():
    # contacto NA de X0 (marcha)
    estado_marcha = entradas['X0']
    # contacto NA de Y0 (enclavamiento) - leemos el valor actual de salida
    estado_enclavamiento = salidas['Y0']
    # contacto NC de X1 (paro): conduce si X1 es False
    estado_paro = not entradas['X1']

    # La corriente pasa si (marcha OR enclavamiento) AND paro
    flujo = (estado_marcha or estado_enclavamiento) and estado_paro

    # Asignar a la bobina
    salidas['Y0'] = flujo
    print(f"Tras evaluar: Y0 = {salidas['Y0']}")

# Simulación de varios ciclos con cambios en entradas
print("--- Ciclo 1: X0=False, X1=False (reposo) ---")
evaluar_peldano()          # Y0=False

print("--- Ciclo 2: Pulsamos marcha (X0=True) ---")
entradas['X0'] = True
evaluar_peldano()          # Y0=True (se enclava)
entradas['X0'] = False      # simulamos que suelta el pulsador

print("--- Ciclo 3: Sin pulsar marcha, debería seguir activo ---")
evaluar_peldano()          # Y0=True (por enclavamiento)

print("--- Ciclo 4: Pulsamos paro (X1=True) ---")
entradas['X1'] = True
evaluar_peldano()          # Y0=False

print("--- Ciclo 5: Reposo tras paro ---")
entradas['X1'] = False
evaluar_peldano()          # Y0=False

Este código replica la lógica de un arranque/paro con enclavamiento. Al ejecutarlo se observa cómo se mantiene la salida tras liberar la marcha y cómo el paro la desactiva. Perfecto para entender el concepto de realimentación en Ladder.

Tendencias Actuales 2026

El lenguaje Ladder sigue siendo dominante en sectores como automoción, alimentación y tratamiento de aguas. Las nuevas versiones de IEC 61131-3 (edición 4, prevista 2026) incorporan mejoras en la representación de tipos de datos estructurados y bloques de seguridad (Safety) directamente en Ladder. Además, la integración con IIoT permite visualizar en tiempo real el estado de cada peldaño en paneles HMI remotos.

Aplicaciones con Raspberry Pi

Mediante librerías como python-ladder o SoftPLC (OpenPLC), podemos ejecutar programas Ladder en una Raspberry Pi. Se conectan los GPIO a sensores y actuadores, y el ciclo de scan se implementa en Python. Ejemplo: control de un semáforo con contactos y temporizadores.

Aplicaciones con Arduino

El entorno Arduino PLC IDE permite programar en Ladder sobre placas como Arduino Opta o Portenta. También existen proyectos como Ladderino que convierten diagramas Ladder a código C++ para Arduino Uno.

💼 Caso Práctico Industrial

Contexto: Un tanque se llena mediante una bomba (Y1). El proceso debe cumplir: si el nivel bajo (sensor X0=1) y no hay alarma de sobrellenado (X1=0, NC), la bomba arranca. Adicionalmente, un pulsador de marcha (X2) puede forzar el arranque manual, y un pulsador de paro (X3) detiene la bomba (prioridad). El programa Ladder implementado es:

     X0      X1      X3        Y1
----| |------|/|-----|/|-------( )----
    |                          |
    |      X2                  |
    +------| |-----------------+
    |                          |
    |      Y1                  |
    +------| |-----------------+

Pregunta: ¿En qué situación se activará Y1 a pesar de que X0=0 (nivel bajo no detectado)?

🍓 Raspberry Pi + GPIO

Contexto: En una Raspberry Pi, se conecta un pulsador al GPIO17 (entrada X0) y un LED al GPIO27 (salida Y0). Se ejecuta el siguiente código Python que emula un rung con un contacto NC para X0:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(27, GPIO.OUT)

while True:
    # contacto NC: conduce si entrada es False
    flujo = not GPIO.input(17)
    GPIO.output(27, flujo)

Pregunta: Si el pulsador NO está presionado (estado abierto), ¿cómo estará el LED?

🐍 Lógica en Python

Contexto: Se define una función que recibe tres valores booleanos (a, b, c) y devuelve el resultado de un peldaño con la siguiente estructura: (a OR b) AND (NOT c).

Pregunta: ¿Cuál de las siguientes expresiones Python implementa correctamente esa lógica?

Tabla 1: Comparativa de elementos Ladder vs. otros lenguajes IEC 61131-3
FunciónLadder (símbolo)IL (instrucción)ST (expresión)
Contacto NA—| |—LD X1X1
Contacto NC—|/|—LDN X1NOT X1
Bobina—( )—ST Y1Y1 := .
Serie (AND)contactos en serieAND X2AND
Paralelo (OR)contactos en paraleloOR X2OR
Temporizador TONbloque TONbloque funcionalTON(IN:=., PT:=.)

📚 Recursos Técnicos y Normativos 2026

Normativas y Estándares

Recursos Raspberry Pi y Python