Operaciones aritméticas en automatización: del cálculo simple al algoritmo complejo
Las operaciones aritméticas dotan a los PLC de la capacidad de procesar señales, calcular variables de proceso, ejecutar algoritmos de control y tomar decisiones basadas en magnitudes numéricas. Desde la simple suma de contadores hasta la implementación de un PID o el cálculo de raíces cuadradas en sistemas de caudal, estas operaciones son esenciales en la ingeniería de automatización.
Según la norma IEC 61131-3, las operaciones aritméticas están disponibles en todos los lenguajes: en ST (Textos Estructurados) se escriben como expresiones matemáticas; en FBD y Ladder se usan bloques específicos (ADD, SUB, MUL, DIV, etc.). La elección depende de la complejidad y la claridad deseada.
Aplicación industrial: en una estación de mezclado, se leen caudales de dos componentes (señales analógicas), se suman, se compara el total con un setpoint, y se calcula la raíz cuadrada del caudal para linealizar la respuesta de una válvula. Todo ello se ejecuta en cada ciclo de scan.
Operaciones aritméticas básicas: ADD, SUB, MUL, DIV
Las operaciones fundamentales se implementan con instrucciones directas:
- ADD (suma):
resultado := A + B;en ST. En FBD, bloque con dos entradas y una salida. - SUB (resta):
resultado := A - B; - MUL (multiplicación):
resultado := A * B; - DIV (división):
resultado := A / B;¡Ojo con la división por cero! Siempre debe validarse que el divisor no sea cero antes de ejecutar la operación.
Ejemplo en ST:
// Suma de dos entradas analógicas escaladas
total := (analog_in_1 + analog_in_2) * 0.01; // escalado simple
// Prevención de división por cero
IF divisor <> 0 THEN
resultado := dividendo / divisor;
ELSE
resultado := 0;
error_div := TRUE;
END_IF
Datos técnicos: Los PLC trabajan con tipos de datos enteros (INT, DINT) y reales (REAL). Es crucial respetar los rangos para evitar desbordamientos. En Siemens S7-1500, un INT va de -32768 a 32767; un DINT de -2³¹ a 2³¹-1; un REAL tiene precisión de 6 dígitos decimales.
Operaciones avanzadas: potencias, raíces, trigonometría y logaritmos
Los PLC modernos incorporan funciones matemáticas complejas, accesibles generalmente en ST o como bloques en librerías:
- POW (potencia):
y := A ** B;oPOW(A, B). Ejemplo: cálculo de energía en un motor (potencia = par * velocidad²). - SQRT (raíz cuadrada):
y := SQRT(A);. Útil para linealizar señales de caudalímetros (caudal ∝ √ΔP). - SIN, COS, TAN: funciones trigonométricas (ángulos en radianes). Aplicaciones en robótica, mesas rotativas, cinemática.
- LOG, LN, EXP: logaritmos y exponenciales. Usados en modelos de procesos químicos, control de pH, etc.
- ABS (valor absoluto):
y := ABS(A);para trabajar con magnitudes siempre positivas.
Ejemplo en ST (cálculo de caudal a partir de presión diferencial):
// Sensor de presión diferencial (0-1000 mbar)
dp_real := INT_TO_REAL(dp_raw) * 0.1; // convertir a mbar
IF dp_real >= 0.0 THEN
caudal := SQRT(dp_real) * K_factor; // caudal en L/min
ELSE
caudal := 0.0;
END_IF
Comparaciones: la base de las decisiones
Las instrucciones de comparación permiten evaluar condiciones numéricas y activar salidas lógicas:
- EQ (equal, ==) : verdadero si A = B.
- NE (not equal, <>) : verdadero si A ≠ B.
- GT (greater than, >) : A > B.
- LT (less than, <) : A < B.
- GE (greater or equal, >=) : A ≥ B.
- LE (less or equal, <=) : A ≤ B.
Aplicación típica: control de temperatura con histéresis:
IF temp > (setpoint + histeresis/2) THEN
calefaccion := FALSE;
refrigeracion := TRUE;
ELSIF temp < (setpoint - histeresis/2) THEN
calefaccion := TRUE;
refrigeracion := FALSE;
END_IF
Conversión de tipos de datos
Los PLC manejan diferentes formatos: BOOL, BYTE, WORD, INT, DINT, REAL, TIME, etc. Para operar entre ellos es necesario convertir explícitamente usando funciones como:
- INT_TO_REAL : entero a real.
- REAL_TO_INT : real a entero (trunca).
- WORD_TO_DINT : palabra a doble entero.
Las conversiones implícitas pueden dar lugar a errores de compilación o comportamientos inesperados. Es buena práctica hacerlas explícitas.
Ejemplo:
velocidad_real := INT_TO_REAL(velocidad_raw) * 0.01; // escalado velocidad_entera := REAL_TO_INT(velocidad_real); // truncamiento
# plc_arithmetic.py - Simula operaciones aritméticas básicas y avanzadas
# Puede ejecutarse en Thonny y usarse con GPIO para leer sensores reales
import math
class PLCArithmetic:
"""Simula un PLC con memoria y operaciones aritméticas."""
def __init__(self):
# Áreas de memoria (simulan %I, %Q, %M, %DB)
self.inputs = {'vel_raw': 0, 'caudal_raw': 0} # enteros de sensores
self.outputs = {'alarma': False, 'display_sum': 0.0, 'display_cuad': 0.0}
self.marks = {'vel_real': 0.0, 'caudal_real': 0.0, 'suma': 0.0,
'vel_cuadrado': 0.0, 'caudal_limite': 50.0}
def leer_sensores(self, vel, caudal):
"""Simula la lectura de entradas analógicas (raw values 0-27648)."""
self.inputs['vel_raw'] = vel
self.inputs['caudal_raw'] = caudal
def escalar(self, raw, factor=0.01):
"""Convierte raw a real (simula INT_TO_REAL y escalado)."""
return float(raw) * factor
def ciclo_calculo(self):
"""Ejecuta las operaciones aritméticas en cada ciclo de scan."""
# Conversiones
self.marks['vel_real'] = self.escalar(self.inputs['vel_raw'])
self.marks['caudal_real'] = self.escalar(self.inputs['caudal_raw'])
# Suma
self.marks['suma'] = self.marks['vel_real'] + self.marks['caudal_real']
# Cuadrado de la velocidad
self.marks['vel_cuadrado'] = self.marks['vel_real'] ** 2
# Comparación: caudal > límite?
if self.marks['caudal_real'] > self.marks['caudal_limite']:
self.outputs['alarma'] = True
else:
self.outputs['alarma'] = False
# Raíz cuadrada del caudal (solo si es positivo)
if self.marks['caudal_real'] >= 0:
self.outputs['display_cuad'] = math.sqrt(self.marks['caudal_real'])
else:
self.outputs['display_cuad'] = 0.0
# Potencia (caudal^1.5) - ejemplo avanzado
self.outputs['display_pot'] = math.pow(self.marks['caudal_real'], 1.5)
# Salida a display (HMI simulado)
self.outputs['display_sum'] = self.marks['suma']
def mostrar_estado(self):
print(f"vel={self.marks['vel_real']:.2f} caudal={self.marks['caudal_real']:.2f} "
f"suma={self.marks['suma']:.2f} vel²={self.marks['vel_cuadrado']:.2f} "
f"alarma={self.outputs['alarma']} √caudal={self.outputs['display_cuad']:.2f}")
# --- Simulación de varios ciclos ---
plc = PLCArithmetic()
# Simulamos lecturas de sensores (valores raw)
for ciclo in range(1, 6):
# Valores raw: 1000, 2000, . (representan 10.0, 20.0 .)
plc.leer_sensores(vel=1000*ciclo, caudal=2000*ciclo)
plc.ciclo_calculo()
print(f"Ciclo {ciclo}: ", end="")
plc.mostrar_estado()
# Salida esperada: alarma se activa cuando caudal_real > 50
# (caudal_raw 2000 → 20.0, 4000 → 40.0, 6000 → 60.0 → alarma True)
Este código simula las operaciones aritméticas básicas y avanzadas (suma, cuadrado, comparación, raíz cuadrada, potencia) sobre valores escalados. Se puede probar en Thonny y luego adaptar a Raspberry Pi con sensores reales usando GPIO o ADC.
Los PLC actuales incorporan coprocesadores matemáticos que aceleran operaciones en coma flotante, permitiendo ejecutar algoritmos complejos (como filtros de Kalman o transformadas rápidas) en tiempo real. Además, la norma IEC 61131-3 edición 4 incluye nuevas funciones como raíces n-ésimas, logaritmos en cualquier base y operaciones con números complejos para aplicaciones de robótica avanzada.
Con Python y librerías como math, podemos implementar todas las operaciones aritméticas vistas. Además, usando RPi.GPIO y convertidores ADC (MCP3008), podemos leer sensores analógicos, escalar, calcular raíces cuadradas y activar salidas. Es una excelente plataforma para prototipar algoritmos antes de pasarlos a un PLC.
En Arduino, las operaciones aritméticas se escriben directamente en C++. Para raíces cuadradas se usa sqrt() (requiere math.h), para potencias pow(). El Arduino PLC IDE ofrece bloques gráficos para estas operaciones, facilitando la programación según IEC 61131-3.
- ✅ Comprender activamente cada línea de código generada
- ✅ Personalizar la solución según tus necesidades específicas
- ✅ Iterar y refinar el código hasta dominar la lógica
- ✅ Desarrollar habilidades de comunicación técnica con IA
📋 Instrucciones de Uso:
- Copia el prompt completo del recuadro superior.
- Personaliza los campos entre corchetes [CAMPO] con tu información específica.
- Pega el prompt en una nueva conversación con tu IA favorita.
- Itera y refina: Pide aclaraciones, modificaciones o añade requisitos adicionales.
- Prueba el código en Thonny primero, luego en tu Raspberry Pi y ajusta según resultados.
💼 Caso Práctico Industrial: Celda robotizada
Contexto: En una celda robotizada se miden la velocidad de una cinta (en m/s) y el caudal de un líquido (en L/min) mediante sensores analógicos (valores raw 0-27648). Se necesita programar en FBD/ST:
- Calcular la suma total de litros transportados en un ciclo (caudal * tiempo_ciclo).
- Calcular el cuadrado de la velocidad media.
- Comparar si el caudal supera los 50 L/min; si es así, activar una alarma.
Se dispone de un temporizador TON que genera un pulso de 1 segundo para medir tiempo.
Pregunta: ¿Qué secuencia de operaciones es la correcta para obtener la suma total de litros en un ciclo (caudal * tiempo)?
🍓 Raspberry Pi + Python
Contexto: En una Raspberry Pi, se ha escrito un script que lee un sensor analógico de temperatura (0-1023) a través de un ADC MCP3008. Se quiere convertir a grados Celsius (°C) usando la fórmula: temperatura = (raw * 3.3 / 1023 - 0.5) * 100. Luego se compara si supera los 30°C para activar un LED.
Pregunta: ¿Qué operaciones aritméticas intervienen en el escalado?
🐍 Conversión de tipos en Python
Contexto: En un PLC, se tiene una variable entera valor_raw (INT) que representa una lectura de sensor. Se desea calcular su raíz cuadrada y almacenarla en una variable real.
Pregunta: ¿Cuál de las siguientes opciones en Python sería equivalente a raiz := SQRT(INT_TO_REAL(valor_raw))?
| Operación | ST (PLC) | Python | Observaciones |
|---|---|---|---|
| Suma | a + b | a + b | |
| Multiplicación | a * b | a * b | |
| División | a / b | a / b | En ST, si a y b son enteros, resultado entero; en Python es float. |
| Potencia | a ** b o POW(a,b) | a ** b o pow(a,b) | |
| Raíz cuadrada | SQRT(a) | math.sqrt(a) | |
| Logaritmo | LN(a), LOG(a) | math.log(a), math.log10(a) | |
| Conversión INT->REAL | INT_TO_REAL(a) | float(a) |
📚 Recursos Técnicos y Normativos 2026
Normativas y Estándares
- IEC 61131-3:2013 + enmiendas 2025 - Programmable controllers — Part 3: Programming languages (aritmética y funciones)
- PLCopen - Librerías matemáticas para control de movimiento