Guía Completa: Identificación Empírica, caracterización y Control de un Motor
Guía Completa: Identificación Empírica y Control de motores para dar un ejemplo claro puede ser de un motor de 112V
Determinar la función de transferencia de un motor de imanes permanentes, asíncronos ó brushless es un proceso esencial para diseñar controladores precisos. A continuación, se detalla el protocolo experimental para caracterizar un motor de 112V fase-fase.
1. Caracterización Eléctrica: Resistencia e Inductancia
Para obtener la respuesta eléctrica, trabajamos con el modelo equivalente en corriente continua (marco de referencia $dq$). La función de transferencia de primer orden que buscamos es:
$$G_e(s) = \frac{I(s)}{V(s)} = \frac{1/R}{\tau_e s + 1}$$
Protocolo Experimental:
- Bloqueo del Rotor: Inmoviliza el eje para eliminar la fuerza contraelectromotriz ($BEMF$).
- Ensayo de Escalón: Aplica un voltaje de CC (ej. 5V) entre dos fases y registra la curva de corriente con un osciloscopio.
- Cálculos:
- Resistencia ($R$): Se obtiene mediante la Ley de Ohm en estado estable: $R = \frac{V_{aplicado}}{I_{final}}$.
- Constante de tiempo ($\tau_e$): Tiempo en el que la corriente alcanza el 63.2% de su valor máximo.
- Inductancia ($L$): Calculada como $L = \tau_e \cdot R$.
2. La Constante de Par ($K_t$) y Fuerza Contraelectromotriz ($K_e$)
En el sistema internacional, $K_t$ (N·m/A) es numéricamente igual a $K_e$ (V·s/rad). Para medirla, usamos el motor como generador.
Procedimiento:
- Gira el motor a una velocidad constante ($\Omega_m$) usando un motor externo o taladro.
- Mide el voltaje pico entre dos fases ($V_{L-L(pico)}$) en el osciloscopio. ó los RPM con un tacómetro
- Calcula la constante usando:
$$V_{fase} = \frac{V_{L-L(pico)}}{\sqrt{3}}$$
$$K_t = K_e = \frac{V_{fase}}{\Omega_m}$$
Donde $\Omega_m$ debe estar en $rad/s$ ($RPM \cdot \frac{2\pi}{60}$).
Para convertir los hercios ($Hz$) medidos en el osciloscopio a velocidad angular ($\omega_m$) en $rad/s$, debes usar la siguiente relación:
La relación entre la frecuencia eléctrica ($f_e$) y la velocidad mecánica es:
Donde:
$f_e$: Frecuencia eléctrica medida en el osciloscopio ($Hz$).
$P$: Número de pares de polos del motor (¡ojo!, no el total de polos, sino pares).
$\omega_m$: Velocidad angular mecánica en $rad/s$.
¿Cómo saber cuántos pares de polos ($P$) tienes?
Si no tienes la hoja de datos (datasheet), puedes obtener $P$ de forma empírica:
Marca el eje del motor.
Gira el motor exactamente una vuelta completa a mano.
Cuenta cuántos ciclos completos (senoides) aparecen en el osciloscopio durante esa vuelta.
El número de ciclos contados es igual a $P$.
Ejemplo: Si el motor tiene 8 polos (es decir, $P = 4$ pares de polos) y mides $100\text{ Hz}$ en el osciloscopio:
$$\omega_m = \frac{2\pi \cdot 100}{4} = 50\pi \approx 157.08\text{ rad/s}$$
def hz_a_rad_s(frecuencia_hz, pares_de_polos):
"""
Convierte la frecuencia eléctrica medida en Hz a velocidad angular mecánica.
"""
omega_m = (2 * np.pi * frecuencia_hz) / pares_de_polos
return omega_m
# Ejemplo de uso:
f_osc = 60 # Hz medidos
p_pairs = 4 # Pares de polos
velocidad = hz_a_rad_s(f_osc, p_pairs)
print(f"Velocidad: {velocidad:.2f} rad/s")
Relación con RPM
Si además quieres mostrar las RPM partiendo de la frecuencia eléctrica, la fórmula es:
Esta es la fórmula que suelen usar los variadores de frecuencia (VFD) para mostrar la velocidad en sus pantallas.
3. Caracterización Mecánica: Inercia ($J$) y Fricción ($B$)
La dinámica mecánica relaciona el torque con la velocidad angular:
$$G_m(s) = \frac{\Omega(s)}{T(s)} = \frac{1}{Js + B}$$
Método de Desaceleración (Spin-down):
- Medir Fricción ($B$): Haz girar el motor en vacío a velocidad constante ($\Omega_{ss}$) y mide la corriente ($I_{vacio}$).
$$B = \frac{K_t \cdot I_{vacio}}{\Omega_{ss}}$$
- Medir Inercia ($J$): Desconecta la alimentación súbitamente y mide el tiempo que tarda la velocidad en caer al 36.8% de su valor inicial. Este tiempo es la constante mecánica $\tau_m$.
$$J = \tau_m \cdot B$$
Es el método más preciso si no tienes sensores adicionales. Cuando cortas la energía, el motor se convierte en un generador. La frecuencia de ese voltaje es proporcional a la velocidad.
Procedimiento-1:
Conecta una sonda del osciloscopio entre dos fases del motor.
Configura el Trigger en modo «Normal» y con flanco descendente para capturar el momento exacto en que dejas de alimentar el motor.
Lleva el motor a una velocidad estable y corta el interruptor.
En la pantalla: Verás una señal senoidal que se «estira» (la frecuencia baja) y se «achica» (el voltaje baja).
Cálculo:
Mide la frecuencia inicial ($f_0$).
Calcula la frecuencia objetivo: $f_{target} = f_0 \cdot 0.368$.
Busca en la captura el punto donde los ciclos tienen esa frecuencia. El tiempo transcurrido desde el corte hasta ese punto es tu $\tau_m$.
Método de Grabación en Cámara Lenta (Smartphone)
Si solo tienes un tacómetro digital de mano y no tienes osciloscopio, usa la tecnología de tu bolsillo.
Coloca tu tacómetro de forma que se vea claramente el display. (en caso de tener un osciloscopio también puede repetir la medición anterior acompañado de esta prueba)
Pon tu móvil a grabar vídeo en cámara lenta (slow motion, típicamente 120 o 240 fps) apuntando al display del tacómetro.
Arranca el motor, llévalo a velocidad constante y corta la luz.
En la edición del vídeo:
Anota el timestamp exacto cuando el motor deja de recibir energía ($t_0$).
Anota el timestamp cuando el display muestra el valor: $RPM_{inicial} \cdot 0.368$.
La diferencia de tiempo, ajustada por la velocidad de la cámara lenta, es tu $\tau_m$.
4. La Función de Transferencia Completa
Combinando la parte eléctrica y mecánica, obtenemos la relación Voltaje a Velocidad:
$$G(s) = \frac{\Omega(s)}{V(s)} = \frac{K_t}{(Ls + R)(Js + B) + K_t^2}$$
5. Implementación y Simulación (Python)
El siguiente script permite validar el modelo teórico frente a datos reales capturados en un archivo CSV.
Python
1. Definición del Modelo Matemático
Esta función construye la función de transferencia basada en los parámetros físicos obtenidos. La ecuación representada es:
Python
import numpy as np
import control as ct
import matplotlib.pyplot as plt
import pandas as pd
def crear_modelo_motor(R, L, Kt, J, B):
num = [Kt]
den = [L*J, (L*B + R*J), (R*B + Kt**2)]
return ct.TransferFunction(num, den)
# Parámetros de ejemplo (42V)
R, L, Kt, J, B = 0.5, 0.001, 0.082, 0.00005, 0.0001
motor_tf = crear_modelo_motor(R, L, Kt, J, B)
2. Validación: Modelo Teórico vs. Datos Reales (CSV)
Función para cargar datos experimentales y compararlos visualmente con la respuesta del modelo ante un escalón de voltaje.
Python
def comparar_con_real(motor_tf, v_test, csv_path):
# Cargar datos desde archivo
data = pd.read_csv(csv_path)
t_real = data['tiempo'].values
v_real = data['velocidad'].values
# Simular modelo con la misma base de tiempo
t_sim, v_sim = ct.step_response(motor_tf * v_test, T=t_real)
plt.figure(figsize=(10, 5))
plt.plot(t_real, v_real, 'ro', label='Experimental', markersize=2)
plt.plot(t_sim, v_sim, 'b-', label='Modelo Teórico', linewidth=2)
plt.xlabel('Tiempo (s)')
plt.ylabel('Velocidad (rad/s)')
plt.legend()
plt.grid(True)
plt.show()
3. Diseño del Controlador PID
Configuración de un lazo cerrado con retroalimentación unitaria para controlar la velocidad.
Python
def diseñar_control_pid(motor_tf, Kp, Ki, Kd):
# Definición del controlador: C(s) = Kp + Ki/s + Kd*s
pid = ct.tf([Kd, Kp, Ki], [1, 0])
# Sistema en lazo cerrado (Feedback)
sistema_controlado = ct.feedback(pid * motor_tf, 1)
return sistema_controlado
# Ejemplo de sintonización
Kp, Ki, Kd = 2.0, 20.0, 0.05
lazo_cerrado = diseñar_control_pid(motor_tf, Kp, Ki, Kd)
4. Simulación de Perturbación de Carga
Para simular cómo el motor reacciona cuando se le aplica un freno (torque de carga), es más eficiente usar una representación en Espacio de Estados:
Python
def simular_rechazo_carga(R, L, Kt, J, B, Kp, Ki, Kd, ref_val, load_val, t_impact):
# Representación interna del motor (2 entradas: V y T_load)
A = [[-R/L, -Kt/L], [Kt/J, -B/J]]
B_mat = [[1/L, 0], [0, -1/J]]
C_mat = [[0, 1]]
D_mat = [[0, 0]]
motor_ss = ct.ss(A, B_mat, C_mat, D_mat)
# Interconexión con PID
pid = ct.tf([Kd, Kp, Ki], [1, 0])
sys_cl = ct.interconnect(
[motor_ss, pid],
connections=[[0, 0], [1, 0, -1]],
inplist=[(1,0), (0,1)], # [Referencia, Carga]
outlist=[(0,1)]
)
# Definición de señales
t = np.linspace(0, 4, 1000)
ref = np.ones_like(t) * ref_val
load = np.zeros_like(t)
load[t >= t_impact] = load_val
t_out, y_out = ct.input_output_response(sys_cl, t, [ref, load])
plt.plot(t_out, y_out[0])
plt.axvline(x=t_impact, color='r', linestyle='--', label='Impacto de Carga')
plt.title('Respuesta ante Carga Externa')
plt.legend()
plt.show() 6. Control de Lazo Cerrado (PID)
Para asegurar que el motor mantenga la velocidad deseada ante variaciones de carga, implementamos un diagrama de bloques con retroalimentación.
Componentes del Lazo:
- Error ($e$): Diferencia entre la velocidad deseada y la real.
- PID ($C(s)$): Calcula el voltaje necesario basándose en $K_p$, $K_i$ y $K_d$.
- Rechazo de Perturbaciones: El sistema compensa automáticamente si un torque de carga ($T_L$) frena el eje.
Resumen de Variables Obtenidas
Parámetro | Símbolo | Unidad | Método |
Resistencia | $R$ | $\Omega$ | Ley de Ohm (bloqueado) |
Inductancia | $L$ | $H$ | Constante de tiempo eléctrica |
Cte. de Par | $K_t$ | $N\cdot m/A$ | Ensayo como generador |
Inercia | $J$ | $kg\cdot m^2$ | Ensayo de spin-down |
Fricción | $B$ | $N\cdot m\cdot s/rad$ | Corriente en vacío |
Ahora que pasa si el motor que estamos usando es un motor de imanes permanente y el control que se usa es FOC
Cuando pasas de un control simple de voltaje a FOC (Field Oriented Control), la arquitectura cambia de un lazo simple a lazos anidados (Cascaded Control).
Lo fascinante es que el modelo de función de transferencia que obtuvimos ($R, L, K_t, J, B$) sigue siendo el corazón del sistema, pero ahora «vive» dentro de bloques separados. En FOC, el motor trifásico se «disfraza» de motor de corriente continua gracias a las transformadas de Clarke y Park.
Aquí tienes cómo se estructuran los bloques y cómo encaja tu modelo:
1. La Filosofía del FOC en Bloques
En FOC, dividimos la función de transferencia global en dos partes: el Lazo de Corriente (interno y rápido) y el Lazo de Velocidad (externo y lento).
Para tu modelo, el eje $q$ (cuadratura) es el que genera el torque y es el que sigue exactamente las ecuaciones que medimos.
El Diagrama de Bloques General:
Referencia de Velocidad ($\omega^*$) $\rightarrow$ Sumador.
Controlador PID de Velocidad $\rightarrow$ Su salida es la Corriente de referencia ($i_q^*$).
Controlador PID de Corriente ($i_q$) $\rightarrow$ Su salida es el Voltaje de referencia ($V_q^*$).
Transformadas (Park/Clarke) e Inversor $\rightarrow$ En el modelo de transferencia, se suelen considerar como una ganancia de $1$ o un pequeño retardo.
Planta Eléctrica ($G_e$) $\rightarrow$ Transforma $V_q$ en corriente $i_q$.
Constante de Par ($K_t$) $\rightarrow$ Transforma corriente en Torque ($T_e$).
Planta Mecánica ($G_m$) $\rightarrow$ Transforma Torque en Velocidad ($\omega$).
2. Las Funciones de Transferencia dentro del FOC
Si usas el modelo que calculamos, así se reparten las ecuaciones en los bloques del FOC:
A. Lazo Interno (Control de Corriente)
El controlador de corriente solo «ve» la parte eléctrica del motor. La función de transferencia de la planta para este lazo es:
Objetivo: Que la corriente real $i_q$ siga a $i_q^*$ lo más rápido posible.
Nota: En FOC, el voltaje de la BEMF ($K_e \cdot \omega$) se suele compensar mediante un «Feed-forward» para que no moleste al PID de corriente.
B. Lazo Externo (Control de Velocidad)
Para el controlador de velocidad, el lazo de corriente interno (si está bien sintonizado) se comporta como una ganancia casi unitaria. La planta que ve este controlador es la parte mecánica:
Objetivo: Que la velocidad $\omega$ siga a $\omega^*$ ajustando la demanda de corriente.
3. ¿Por qué es mejor este modelo que el anterior?
Al usar FOC con tu función de transferencia dividida en dos lazos:
Proteges el motor: Puedes limitar la corriente máxima ($i_q^*$) en la salida del PID de velocidad, evitando quemar el motor de 42V si se bloquea el eje.
Más ancho de banda: El lazo de corriente puede ejecutarse a frecuencias muy altas (ej. 10-20 kHz), mientras que el de velocidad puede ir más lento (1 kHz), haciendo el sistema mucho más estable.
Control de Torque directo: Como controlas $i_q$, estás controlando directamente el torque instantáneo.
Resumen del Diagrama de Funciones:
| Lazo | Entrada | Salida | Función de Transferencia de la Planta |
| Corriente ($q$) | $V_q$ (Voltaje) | $I_q$ (Amperios) | $1 / (Ls + R)$ |
| Velocidad | $I_q$ (Amperios) | $\omega$ (rad/s) | $K_t / (Js + B)$ |
Un detalle técnico «Pro»
En FOC también existe el eje $d$. Para un motor de imanes permanentes montados en superficie (como suele ser el de 42V), siempre fijamos la referencia de corriente $i_d^* = 0$ para maximizar la eficiencia. La función de transferencia del eje $d$ es idéntica a la del eje $q$ eléctrica ($1/(Ls+R)$), pero no produce movimiento.
¿Te gustaría que te ayude a escribir el código para sintonizar primero el lazo de corriente y luego el de velocidad? En control real, siempre se sintoniza de adentro hacia afu
Ahora veremos que pasa cuando el control es sensorless con el mismo FOC
En lugar de un encoder físico, añadimos un bloque matemático llamado Observador, que estima la posición y velocidad del rotor analizando las corrientes y voltajes.
Para un estudiante, la clave es entender que el lazo de control no cambia mucho, pero la retroalimentación ahora proviene de un cálculo, no de un cable.
El Mapa del Tesoro: Diagramas y Funciones de Transferencia
Aquí tienes el desglose detallado bloque por bloque para que puedas dibujar el diagrama completo:
Bloque 1: El Lazo de Velocidad (Externo)
Es el encargado de decidir cuánto torque (corriente $I_q$) necesitamos.
Entrada: $\omega_{ref}$ (Velocidad deseada) y $\hat{\omega}$ (Velocidad estimada por el observador).
Función de Transferencia ($C_v(s)$): Suele ser un PI: $K_{pv} + \frac{K_{iv}}{s}$.
Salida: $I_q^*$ (Referencia de corriente de cuadratura).
Bloque 2: El Lazo de Corriente $q$ (Interno)
Controla la fuerza que mueve el motor.
Entrada: $I_q^*$ y $I_q$ (Medida y transformada de las fases).
Función de Transferencia ($C_i(s)$): Un PI rápido: $K_{pi} + \frac{K_{ii}}{s}$.
Salida: $V_q^*$ (Voltaje de referencia en el eje $q$).
Bloque 3: El Modelo del Motor (La Planta)
Aquí es donde aplicas los parámetros que medimos ($R, L, K_t, J, B$). Se divide en dos partes:
Parte Eléctrica: $G_e(s) = \frac{1}{Ls + R}$. Convierte $V_q$ en $I_q$.
Parte Mecánica: $G_m(s) = \frac{1}{Js + B}$. Convierte el torque ($T_e = I_q \cdot K_t$) en velocidad $\omega$.
Bloque 4: El Observador (El bloque «Sensorless»)
Este bloque es la «caja negra» que reemplaza al sensor. En simulación, toma los valores de voltaje y corriente para adivinar dónde está el motor.
Entradas: $V_{\alpha\beta}$ (Voltajes aplicados) e $I_{\alpha\beta}$ (Corrientes medidas).
Función interna: Un estimador de Fuerza Contraelectromotriz (BEMF). Basado en el modelo: $e = V – Ri – L\frac{di}{dt}$.
Salidas: 1. $\hat{\theta}$ (Ángulo estimado): Se envía a los bloques de Transformada de Park/Clarke.
2. $\hat{\omega}$ (Velocidad estimada): Se envía al sumador inicial para cerrar el lazo de velocidad.
Interconexiones para Simulación (Paso a Paso)
Para que un estudiante pueda montarlo en Simulink o Python, estas son las conexiones exactas:
| Desde (Origen) | Hacia (Destino) | Señal transportada |
| Referencia de Usuario | Sumador de Velocidad (+) | $\omega^*$ (rad/s) |
| Observador ($\hat{\omega}$) | Sumador de Velocidad (-) | $\hat{\omega}$ (Feedback) |
| PID de Velocidad | Sumador de Corriente (+) | $I_q^*$ (Demanda de torque) |
| PID de Corriente $q$ | Bloque Eléctrico del Motor | $V_q$ (Voltaje inyectado) |
| Bloque Eléctrico | Bloque de Torque ($K_t$) | $I_q$ (Amperios reales) |
| Bloque de Torque | Bloque Mecánico ($1/(Js+B)$) | $T_e$ (Torque eléctrico) |
| Motor (Voltaje/Corriente) | Entrada del Observador | Datos para la estimación |
Resumen de Funciones de Transferencia para el Informe
Si el estudiante necesita presentar las ecuaciones de cada bloque en su estado estable:
Planta Eléctrica:
$$G_e(s) = \frac{I_q(s)}{V_q(s) – E(s)} = \frac{1}{Ls + R}$$(Donde $E$ es la BEMF que el control compensa).
Planta Mecánica:
$$G_m(s) = \frac{\Omega(s)}{T_e(s) – T_L(s)} = \frac{1}{Js + B}$$(Donde $T_L$ es el torque de carga).
Lazo Cerrado de Corriente (Simplificado): Si el PI está bien diseñado, se busca que $I_q/I_q^* \approx 1$ con un ancho de banda alto.
Un toque de realidad para el estudiante
En una simulación «ideal», el observador funciona perfecto. Pero en la vida real con un motor de 112V, a bajas velocidades la BEMF es tan pequeña que el observador «se queda ciego». Por eso, en el diagrama de bloques, a veces se añade un bloque de Arranque en Lazo Abierto (I-f start) antes de pasar al control sensorless.
Sintonizar un control FOC (Field Oriented Control) puede parecer magia negra, pero el método de Cancelación de Polos es la técnica de ingeniería más elegante para convertir un sistema complejo en uno predecible y dócil.
La idea es simple: usamos el cero del controlador PI para «anular» el pole (la lentitud natural) del motor. Esto nos permite decidir nosotros mismos qué tan rápido queremos que responda el sistema mediante un único parámetro: el ancho de banda ($\beta$).
1. Sintonización del Lazo de Corriente (Lazo Interno)
Este lazo es el más rápido y debe estar listo antes de tocar la velocidad. La planta eléctrica es $G_e(s) = \frac{1}{Ls + R}$.
El truco: Queremos que la relación entre $K_{pi}$ y $K_{ii}$ sea igual a la relación entre $L$ y $R$.
-
Define el Ancho de Banda ($\beta_i$): Elige una frecuencia en rad/s (típicamente entre $2000$ y $5000$ para un motor de 42V).
-
Calcula las Ganancias:
$$K_{pi} = \beta_i \cdot L$$$$K_{ii} = \beta_i \cdot R$$
¿Qué logramos? El lazo cerrado de corriente se convierte en una función de transferencia de primer orden perfecta: $\frac{I_q(s)}{I_q^*(s)} = \frac{\beta_i}{s + \beta_i}$. Sin oscilaciones, solo una subida limpia.
2. Sintonización del Lazo de Velocidad (Lazo Externo)
Aquí controlamos la parte mecánica: $G_m(s) = \frac{K_t}{Js + B}$. Para el controlador de velocidad, el lazo de corriente es tan rápido que lo vemos como una «ganancia de 1».
-
Define el Ancho de Banda ($\beta_\omega$): Regla de oro: Debe ser al menos 10 veces menor que el de corriente para evitar inestabilidad ($\beta_\omega \leq \beta_i / 10$).
-
Calcula las Ganancias:
$$K_{p\omega} = \frac{\beta_\omega \cdot J}{K_t}$$$$K_{i\omega} = \frac{\beta_\omega \cdot B}{K_t}$$
3. Código (Cálculo Automático)
Este script toma tus datos empíricos y genera las ganancias listas para usar en tu simulación o en tu microcontrolador.
Python
def sintonizar_foc_pmsm(R, L, J, B, Kt, f_corte_corriente_hz=500):
"""
Calcula ganancias PI mediante cancelación de polos.
f_corte_corriente_hz: Frecuencia deseada para el lazo de corriente (típicamente 500-1000Hz)
"""
# 1. Lazo de Corriente (Frecuencia a rad/s)
beta_i = 2 * np.pi * f_corte_corriente_hz
kpi = beta_i * L
kii = beta_i * R
# 2. Lazo de Velocidad (10 veces más lento para asegurar estabilidad)
beta_w = beta_i / 10
kpw = (beta_w * J) / Kt
kiw = (beta_w * B) / Kt
return (kpi, kii), (kpw, kiw)
# Ejemplo con tus datos de 112V
corriente_pi, velocidad_pi = sintonizar_foc_pmsm(0.5, 0.001, 0.00005, 0.0001, 0.082)
print(f"Lazo Corriente -> Kp: {corriente_pi[0]:.4f}, Ki: {corriente_pi[1]:.4f}")
print(f"Lazo Velocidad -> Kp: {velocidad_pi[0]:.4f}, Ki: {velocidad_pi[1]:.4f}")
Resumen para el Estudiante: ¿Por qué funciona?
Al diseñar el controlador así, el sistema resultante en lazo cerrado no es una ecuación de segundo orden con sobrepasos peligrosos, sino una serie de bloques que responden como filtros pasabajos:
-
Lazo de Corriente: Se comporta como $\frac{\beta_i}{s + \beta_i}$.
-
Lazo de Velocidad: Se comporta como $\frac{\beta_\omega}{s + \beta_\omega}$.
Esto garantiza que la simulación sea estable en estado estable y que el motor no sufra picos de corriente innecesarios durante los transitorios.
El último paso: La Discretización
Si el estudiante va a programar esto en un microcontrolador (C/C++), los valores de $K_i$ deben multiplicarse por el tiempo de muestreo ($T_s$) del PWM.