Control y Programación
Capas de software del sistema
El sistema distribuye el control en cuatro capas de software que operan coordinadamente:
| Capa | Archivo | Tecnología | Función |
|---|---|---|---|
| Orquestador | rutina_maestra.py | Python / Raspberry Pi | Coordina todo el proceso |
| Control de campo | Proyecto CCW | PLC Micro850 / Ladder | Motor, sensores, plancha |
| Robótica | camisa.script / playera.script |
URScript | Trayectorias UR3 |
| Periféricos | Firmware ESP32 | C++ / Arduino | Pistón + Torreta |
rutina_maestra.py — Orquestador central
El archivo rutina_maestra.py es el cerebro del sistema. Implementa una máquina de estados explícita que coordina todos los subsistemas.
Librerías principales
from pymodbus.client import ModbusTcpClient # Comunicación PLC y UR3
import requests # API REST → Render/Firebase
import serial # Comunicación ESP32
import socket # Envío scripts al UR3
import tf_keras as keras # Modelo IA de clasificación
from PIL import Image # Procesamiento de imagen
Gestión de etapas
def cambiar_etapa(nueva_etapa: str):
global etapa_actual
etapa_actual = nueva_etapa
print(f"[ESTADO] Etapa actual -> {etapa_actual}")
def configurar_mascaras_sensores(s1: bool, s2: bool, s3: bool):
global sensor1_habilitado, sensor2_habilitado, sensor3_habilitado
sensor1_habilitado = s1
sensor2_habilitado = s2
sensor3_habilitado = s3
print(f"[MASCARAS] S1={'ON' if s1 else 'OFF'} | S2={'ON' if s2 else 'OFF'} | S3={'ON' if s3 else 'OFF'}")
Clasificación IA de prendas
def clasificar_prenda(imagen_path):
img = Image.open(imagen_path).resize((224, 224))
data = np.array(img, dtype=np.float32) / 127.5 - 1
prediction = modelo_prendas.predict(data[np.newaxis, ...])
clase_idx = np.argmax(prediction)
confianza = prediction[0][clase_idx]
return labels_prendas[clase_idx], confianza
# Retorna: ("Camisa", 0.97) o ("Playera", 0.94)
Envío de script URScript al robot
def enviar_script_ur3(ruta_script: str):
with open(ruta_script, "r") as f:
script = f.read()
sock = socket.socket()
sock.connect((ROBOT_IP, ROBOT_PORT)) # 192.168.3.71:30002
sock.sendall(script.encode())
sock.close()
Control del motor (PLC Micro850 vía pymodbus)
def motor_start():
with ModbusTcpClient(PLC_IP, port=PLC_PORT) as client:
client.write_coil(COIL_CMD_DIR_FWD, True, slave=PLC_UNIT_ID)
client.write_coil(COIL_CMD_START, True, slave=PLC_UNIT_ID)
print("[PLC] Motor iniciado")
def motor_stop():
with ModbusTcpClient(PLC_IP, port=PLC_PORT) as client:
client.write_coil(COIL_CMD_STOP, True, slave=PLC_UNIT_ID)
print("[PLC] Motor detenido")
URScript — Trayectorias del UR3
camisa.script (resumen)
Rutina de planchado para camisas de vestir. Define 7 waypoints con movimientos movej + cinemática inversa (get_inverse_kin).
def camisa():
set_tcp(p[0.0, 0.0, 0.0777, 0.0, 0.0, 0.0])
set_payload(0.1, [0.0, 0.0, 0.08])
set_tool_voltage(24)
modbus_add_signal("192.168.3.71", 255, 129, 3, "RX74", False)
modbus_add_signal("192.168.3.133", 255, 130, 3, "TX71", False)
while (True):
movej(get_inverse_kin(p[.062, .299, .603, -1.834, -.149, -.019], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.023, .321, .271, -1.863, -.037, .140], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.092, .279, .548, -1.786, -.042, -.080], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.083, .283, .262, -1.995, -.014, -.012], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.167, .265, .509, -1.935, .245, -.242], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.183, .239, .233, -2.204, .277, -.134], ...), a=1.396, v=1.047)
movej(get_inverse_kin(p[.015, .272, .692, -1.570, .003, .159], ...), a=1.396, v=1.047)
end
end
playera.script (resumen)
Rutina análoga para playeras con waypoints re-calibrados para la geometría diferente de este tipo de prenda.
Parámetros de movimiento
| Parámetro | Valor | Descripción |
|---|---|---|
a |
1.3962 rad/s² |
Aceleración articular |
v |
1.0471 rad/s |
Velocidad articular |
| TCP offset Z | 0.0777 m |
Distancia de la herramienta al flange |
| Payload | 0.1 kg |
Masa de la plancha |
PLC Micro850 — Connected Components Workbench
La lógica del PLC fue desarrollada en Connected Components Workbench (CCW) de Rockwell Automation, utilizando lenguaje Ladder. Las funciones principales son:
- Arranque y paro del motor de la banda (con dirección)
- Lectura de los tres sensores digitales (S1, S2, S3)
- Activación de la salida
000007para la plancha eléctrica - Respuesta a los comandos Modbus TCP desde la Raspberry Pi
La siguiente imagen muestra una parte del programa en lenguaje Ladder utilizado para controlar el movimiento del motor dentro del sistema de planchado automatizado. Esta lógica permite activar el motor, definir su dirección de giro y generar los pulsos necesarios para el movimiento.
En la primera línea se realiza la lectura del sensor de entrada, identificado como sensor1. Este sensor permite detectar la presencia de una prenda en el sistema. Cuando el sensor cambia de estado, la señal puede ser utilizada por el PLC para iniciar la secuencia de trabajo.
Posteriormente, se observa una lógica de arranque y paro del motor. El contacto CMD_START permite activar la bobina MOTOR_RUN, mientras que CMD_STOP funciona como condición de paro. Además, se utiliza un contacto auxiliar de MOTOR_RUN para mantener enclavado el motor una vez que fue iniciado, evitando que se apague inmediatamente al soltar la señal de arranque.
También se incluye la señal CMD_DIR_FWD, la cual controla la dirección de giro del motor mediante la salida digital _IO_EM_DO_01. Esta salida se encarga de enviar la señal de dirección al controlador del motor.
Finalmente, se utilizan temporizadores tipo TON para generar una señal intermitente llamada PULSE_BIT. Esta señal funciona como el pulso que permite mover el motor paso a paso. Al alternar el estado de PULSE_BIT, el PLC puede enviar pulsos continuos al driver del motor mientras la señal MOTOR_RUN permanezca activa.
Lógica Ladder para control de motor

Figura 1. Programa Ladder implementado en el PLC para controlar el arranque, paro, dirección y generación de pulsos del motor utilizado en el sistema de planchado automatizado.
Dashboard de monitoreo — dashboard_server.py
El archivo dashboard_server.py implementa un servidor Flask con Server-Sent Events (SSE) que permite monitorear la rutina maestra en tiempo real sin modificarla:
- Ejecuta
rutina_maestra.pycomo subproceso. - Lee su salida estándar e interpreta los
[ESTADO],[PLC],[IA],[MASCARAS]y[PC]tags. - Emite el estado actualizado a todos los clientes web conectados vía SSE.
- Expone endpoints REST (
/api/status,/api/start,/events).

Figura 2. Interfaz HMI para monitoreo del proceso de Planchado Express.
Recursos asociados
motor_sensor.zip
Código del sistema embebido basado en ESP32 para el control de actuadores (pistón y torreta).
Descarga: motor_sensor.zip
Este recurso contiene la implementación del control del ESP32, incluyendo la gestión de actuadores y la interacción con sensores. Se relaciona con ambas secciones ya que define tanto la arquitectura electrónica del sistema como la lógica de programación de los periféricos.
—