El modelo lineal de un motor eléctrico de DC consiste en 2 ecuaciones diferenciales acopladas: el modelo eléctrico y el modelo mecánico. Debido a que ambos modelos están relacionados podemos escribir un modelo general el cual nos permitirá obtener una función de transferencia. En este ejemplo encontraremos la función de transferencia que relacione voltaje (entrada) con posición angular (salida). Primero, observemos el diagrama del circuito equivalente de la armadura del motor y el diagrama de cuerpo libre de rotor:
Para obtener la ecuación diferencial para el modelo eléctrico consideramos la ley de voltajes de Kirchoff:
La fuerza contra-electromotriz se genera al iniciar el movimiento del rotor debido a que el campo magnético fijo del estator induce un voltaje en el devanado de la armadura (este voltaje es negativo con respecto al voltaje de entrada). La fcem es proporcional a la velocidad angular del rotor por lo que la constante Kb puede determinarse experimentalmente graficando el voltaje en las terminales del motor contra la velocidad angular del rotor (se verá que la relación no es realmente lineal en un intervalo grande pero puede usarse sólo la región lineal como una aproximación para el modelo).
Para obtener el modelo mecánico consideramos la segunda ley de Newton para movimiento angular:
Dónde J y b son el momento de inercia del rotor y el coeficiente de amortiguamiento por fricción respectivamente. Vemos que el torque es proporcional a la corriente en el motor. Asumiendo que no hay perdidas electromagnéticas, por fricción ni por calor, la potencia mecánica en el rotor debe igualar a la potencia eléctrica de manera que :
Por lo que el valor para el factor de fcem encontrado experimentalmente puede ser usado como valor para Kt. Observamos ahora que las ecuaciones (1) y (2) están relacionadas por la función de corriente.Para facilitar la sustitución obtendremos primero la transformada de Laplace de ambas ecuaciones:
Despejando I(s) de (4) y sustituyendo en (3) obtendremos el modelo unificado para el motor DC. Teniendo ya una sola ecuación obtenemos la función de transferencia posición/voltaje:
Ejecutando el siguiente código en Matlab asignando algunos valores a las constantes obtenemos su respuesta al escalón unitario en lazo cerrado:
J = 3.2284E-6;
b = 3.5077E-6;
K = 0.0274;
R = 4;
L = 2.75E-6;
s = tf('s');
P_motor = K/(s*((J*s+b)*(L*s+R)+K^2))
sys_cl = feedback(P_motor,1)
step(sys_cl)
Nota: Esto es lo que se conoce como identificación de sistema de caja blanca. Si no conocen ningún parámetro físico del motor, pueden usar el procedimiento de identificación de caja negra que describo aquí.
Referencias:
DC Motor Position: System Modeling, University of Michigan
DC Motor, MathWorks
DC Motor, How It Works? [video subtitulado en español], Learn Engineering
domingo, 3 de abril de 2016
domingo, 27 de marzo de 2016
martes, 22 de marzo de 2016
Configuración inicial en Debian
[Esta entrada es sólo un apunte personal para recordarme lo que debo de hacer depués de instalar Debian para configurarlo a mi gusto.]
1. Instalación y configuración de WiFi:
https://wiki.debian.org/es/WiFi
2. Configuración de GNOME:
Escribir "Retoques" o "Tweak" en el buscador de aplicaciones. Abrimos la aplicación para configurar GNOME. En la pestaña de "Ventanas" podemos agregar los botones de maximizar y minimizar
3. Instalación de códecs multimedia
En Debian no vienen configurados sudoers por defecto pero pueden encontrar un tutorial para instalarlos aquí.
5. Instalación fuentes de Windows
apt-get install ttf-mscorefonts-installer
6. Instalación de Cairo Dock
Para instalar el dock solo tenemos que abrir Synaptic y escribir "Cairo Dock" en el buscador. Instalamos doble click en el paquete y seguimos el procedimiento de instalación dando click en "Aplicar". Una vez instalado, presionamos Alt+F2 y escribimos "cairo dock" para iniciarlo. Después abrimos la aplicación de retoques como (el mismo del punto 2) y abrimos la pestaña "Aplicaciones al inicio". Damos click en el signo "+" y damos click en Cairo Dock. De esta manera el dock se iniciara automáticamente al iniciar sesión.
1. Instalación y configuración de WiFi:
https://wiki.debian.org/es/WiFi
2. Configuración de GNOME:
Escribir "Retoques" o "Tweak" en el buscador de aplicaciones. Abrimos la aplicación para configurar GNOME. En la pestaña de "Ventanas" podemos agregar los botones de maximizar y minimizar
3. Instalación de códecs multimedia
apt-get install libavcodec-extra
4. Habilitación de sudoEn Debian no vienen configurados sudoers por defecto pero pueden encontrar un tutorial para instalarlos aquí.
5. Instalación fuentes de Windows
apt-get install ttf-mscorefonts-installer
6. Instalación de Cairo Dock
Para instalar el dock solo tenemos que abrir Synaptic y escribir "Cairo Dock" en el buscador. Instalamos doble click en el paquete y seguimos el procedimiento de instalación dando click en "Aplicar". Una vez instalado, presionamos Alt+F2 y escribimos "cairo dock" para iniciarlo. Después abrimos la aplicación de retoques como (el mismo del punto 2) y abrimos la pestaña "Aplicaciones al inicio". Damos click en el signo "+" y damos click en Cairo Dock. De esta manera el dock se iniciara automáticamente al iniciar sesión.
martes, 1 de marzo de 2016
Programa de ejemplo en C para MicroBlaze
(Tarjeta de desarrollo Symbhia)
#include <xgpio.h>
XGpio LEDS;
XGpio SW;
u8 sws; // Variable tipo uint8
int i;
int main(){
//Inicialización
XGpio_Initialize(&LEDS,XPAR_GPIO_1_DEVICE_ID);
XGpio_Initialize(&SW,XPAR_GPIO_0_DEVICE_ID);
while(1){
//Lectura de switches
sws = XGpio_DiscreteRead(&SW,1); //(puntero de instancia,canal)
//Escritura de la variable sws en LEDS
XGpio_DiscreteWrite(&LEDS,1,sws); // (puntero de instancia,canal,dato)
}
return 0;
}
sábado, 20 de febrero de 2016
OpenCV en Python
Instalación de Anaconda en Linux:
Descargar instalador aquí y ejecutar con:
$ bash nombredelinstallador.sh
Instalación de OpenCV usando conda (en la terminal):
$ conda install opencv
Abrir Spyder:
$ spyder
Ejemplo. Cargar una imagen y mostrarla con matplotlib:
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('eco.jpg',0) #Cargar imagen
plt.imshow(img,cmap = 'gray') # Mostrar imagen
plt.xticks([]), plt.yticks([]) #Ocultar numeración en ejes
plt.title('Umberto Eco (1932-2016)')
Descargar instalador aquí y ejecutar con:
$ bash nombredelinstallador.sh
Instalación de OpenCV usando conda (en la terminal):
$ conda install opencv
Abrir Spyder:
$ spyder
Ejemplo. Cargar una imagen y mostrarla con matplotlib:
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('eco.jpg',0) #Cargar imagen
plt.imshow(img,cmap = 'gray') # Mostrar imagen
plt.xticks([]), plt.yticks([]) #Ocultar numeración en ejes
plt.title('Umberto Eco (1932-2016)')
jueves, 14 de enero de 2016
8 de Enero
Apenas corre la primera semana de este año y ya da mucho de qué hablar. Esta noche, después de un curioso suceso, me he propuesto volver a escribir frecuentemente pues me he terminado de convencer finalmente de que olvidamos lentamente la vida de una forma silenciosa. Pequeños detalles se pierden para siempre. Un beso en al lluvia, una carta hecha pedazos o un mensaje de texto hiriente. Olvidamos, convenientemente, que también hemos sido unos hijos de puta. Pero hablemos un poco del año pasado. Inicié 2014 con expectativas en el suelo, quebrado por dentro, emocionalmente abatido. No sabía que esperar de 2015 y fuera lo que fuera sabía que no estaba listo (y tenía razón). Doce meses después esperaba la llegada de otro año sentado en un viejo sillón en la terraza de la casa mi abuela con una extraña tranquilidad. Sabía que había sido un año memorable por todo lo bueno y lo malo. Académicamente ha sido quizá mi mejor año hasta ahora, pero emocionalmente fue un año que me dejó algunas cuantas heridas de guerra. Lastimé y fui lastimado, conocí verdaderamente a la filosofía y definí mi ética personal. Veo con todo esto a 2016 como el incierto año que es pero esta vez sintiéndome listo y armado para el mal tiempo. Si el hombre sólo puede definirse en la medida que se realiza, como decía Sartre, tengo el ánimo de ver cada día de este año como una página en blanco que no quiero dejar que pase en vano. O lo que quizá sea aún peor: olvidarlas después haberlas escrito como tantas hojas que el tiempo arranca de mi memoria.
viernes, 4 de diciembre de 2015
Implementación de un controlador PID discreto en un PIC18F2550
En esta entrada se utilizará el método desarrollado en la entrada anterior, por lo que saltarán algunos pasos durante el proceso. En esa entrada se implementó un controlador PID para una planta descrita por un doble integrador. En esta ocasión haremos una simulación de un controlador PID implementado en un PIC para controlar una planta construida con amplificadores operacionales. Si bien es posible construir un doble integrador físicamente, resulta impráctico debido a la saturación provocada por la acumulación continua. Para resolver esto, esta planta estará caracterizada por dos integradores con reset resistivo o integradores de ganancia controlada (que una forma elegante de llamar a un filtro pasa-bajas activo de un solo polo) [1]. Eligiendo los valores de resistencia y capacitancia de tal manera que cada integrador tenga ganancia unitaria, la función de transferencia de los 2 integradores nos queda:
Para controlar esta planta utilizaremos el siguiente controlador discreto a partir de la transformación backward Euler:
Dónde:
Obteniendo transformada inversa, la salida de control descrita como ecuación de diferencias nos queda:
Hacemos la siguiente sustitución de coeficientes:
Estos coeficientes pueden encontrarse manualmente siguiendo el procedimiento descrito aquí, o ejecutando éste programa de Matlab: [PID_Proteus.m]. Teniendo estos valores podemos realizar una verificación de la ecuación en Simulink:
Algo muy importante que se debe notar es que en esta simulación se está considerando la limitación física de la saturación de la salida del controlador real. Sin esta limitación la respuesta del controlador sería más rápida y con un sobreimpulso mucho menor. Sabiendo ahora que nuestra ecuación de diferencias es correcta podemos proceder a escribir el programa en el PIC en lenguaje C con el compilador MikroC. El programa completo se adjuntará más adelante. La función de control principal queda descrita como:
void pid(void) // Función para el controlador
{
e2=e1; e1=e0; u2=u1; u1=u0; // update de variables
y = ADC_Read(0); // Lectura analógica por AN0
yd = (double) y; // Conversión a double
vin = (yd/1023*5);
y = ADC_Read(1); // Lectura analógica por AN1
yd = (double) y; // Conversión a double
reff = (yd/1023*5);
e0 = reff - vin; // Error
u0 = ke0*e0 + ke1*e1 + ke2*e2 - ku1*u1 - ku2*u2; // Ecuación de diferencias
salida = (int) floor(((u0+5)/10)*1023);
if (salida > 1023) salida = 1023; // Saturación de DAC
if (salida <= 0) salida = 0;
DAC_Output(salida); // Enviar dato
}
Es muy importante que ésta función sea ejecutada dentro de una rutina de interrupción de manera que se tenga control del tiempo de muestreo Ts en exactamente 0.01 segundos para que el controlador funcione correctamente. Para la salida analógica del controlador se esta utilizando un DAC LTC1660 [2][3]. Compilando el programa y simulando en Proteus:
Nota: El relay en la simulación lo único que hace es evitar que la salida bipolar del DAC envíe un voltaje de saturación negativo al inicio [ver este programa].
Para controlar esta planta utilizaremos el siguiente controlador discreto a partir de la transformación backward Euler:
Dónde:
Obteniendo transformada inversa, la salida de control descrita como ecuación de diferencias nos queda:
Estos coeficientes pueden encontrarse manualmente siguiendo el procedimiento descrito aquí, o ejecutando éste programa de Matlab: [PID_Proteus.m]. Teniendo estos valores podemos realizar una verificación de la ecuación en Simulink:
Algo muy importante que se debe notar es que en esta simulación se está considerando la limitación física de la saturación de la salida del controlador real. Sin esta limitación la respuesta del controlador sería más rápida y con un sobreimpulso mucho menor. Sabiendo ahora que nuestra ecuación de diferencias es correcta podemos proceder a escribir el programa en el PIC en lenguaje C con el compilador MikroC. El programa completo se adjuntará más adelante. La función de control principal queda descrita como:
void pid(void) // Función para el controlador
{
e2=e1; e1=e0; u2=u1; u1=u0; // update de variables
y = ADC_Read(0); // Lectura analógica por AN0
yd = (double) y; // Conversión a double
vin = (yd/1023*5);
y = ADC_Read(1); // Lectura analógica por AN1
yd = (double) y; // Conversión a double
reff = (yd/1023*5);
e0 = reff - vin; // Error
u0 = ke0*e0 + ke1*e1 + ke2*e2 - ku1*u1 - ku2*u2; // Ecuación de diferencias
salida = (int) floor(((u0+5)/10)*1023);
if (salida > 1023) salida = 1023; // Saturación de DAC
if (salida <= 0) salida = 0;
DAC_Output(salida); // Enviar dato
}
Es muy importante que ésta función sea ejecutada dentro de una rutina de interrupción de manera que se tenga control del tiempo de muestreo Ts en exactamente 0.01 segundos para que el controlador funcione correctamente. Para la salida analógica del controlador se esta utilizando un DAC LTC1660 [2][3]. Compilando el programa y simulando en Proteus:
Nota: El relay en la simulación lo único que hace es evitar que la salida bipolar del DAC envíe un voltaje de saturación negativo al inicio [ver este programa].
lunes, 16 de noviembre de 2015
Implementación de un controlador PID discreto
Supongamos que queremos controlar el mismo modelo de una masa móvil sin fricción que habíamos tratado en esta entrada cuya función de transferencia es la siguiente:
Dados las ganancias del controlador PID que se habían considerado (recomiendo utilizar el app PID Tuning de Matlab si no tienes estos valores para la planta de tu interés) :
La función de transferencia en tiempo continuo de nuestro controlador nos queda:
En la práctica es recomendable utilizar un LPF en la etapa derivativa a modo de reducir el ruido. En este caso la FT es:
Dónde N representa la frecuencia de corte del filtro que suele ser de 100 radianes/s. Teniendo la función de transferencia de nuestro controlador, el proceso de implementación de este controlador en un sistema digital (PIC, Arduino, FPGA, etc) es el siguiente:
La ecuación de diferencias es la que describirá el algoritmo que deberemos implementar en algún lenguaje de programación o un lenguaje de descripción de hardware. Para realizar la transformación entre la FT en dominio de Laplace al dominio de Z debemos considerar las siguientes aproximaciones numéricas para la derivada:
De aquí es fácil notar que podemos representar a la variable s en terminos de z (dónde Ts es el periodo de muestreo) de las siguientes maneras:
Estas 2 transformaciones de la variable s tienen propiedades distintas. Mientras la transformación backward Euler es estable siempre que la FT en tiempo continuo sea estable, la transformación forward Euler no lo es en todos los casos. (Para más detalles consultar la sección 19.2.3.1 de "Pasive, Active and Digital Filters", Wai-Kai Chen [1]). Para este ejemplo utilizaremos la transformación forward Euler, por lo que nuestro controlador queda representado en tiempo discreto por la TF:
Para este ejemplo se sabe de antemano que este controlador es estable pero si se arriesga a utilizar foward Euler se recomienda verificar estabilidad (puede usarse sisotool de Matlab). Verificamos en Simulink que nuestro controlador funcione correctamente:
Ahora podemos proceder a la conversión de formatos de la FT. Para eso utilizamos el este programa de Matlab: PIDdiscreto.mat. Usando los datos que nos muestra el programa la FT nos queda:
Reordenando (click para agrandar):
Calculando transformada inversa:
Finalmente, verificamos que la ecuación de diferencias sea correcta en Simulink:
En una próxima entrada se implementará este controlador en un código en C para PIC y Arduino.
Dados las ganancias del controlador PID que se habían considerado (recomiendo utilizar el app PID Tuning de Matlab si no tienes estos valores para la planta de tu interés) :
La función de transferencia en tiempo continuo de nuestro controlador nos queda:
De aquí es fácil notar que podemos representar a la variable s en terminos de z (dónde Ts es el periodo de muestreo) de las siguientes maneras:
Estas 2 transformaciones de la variable s tienen propiedades distintas. Mientras la transformación backward Euler es estable siempre que la FT en tiempo continuo sea estable, la transformación forward Euler no lo es en todos los casos. (Para más detalles consultar la sección 19.2.3.1 de "Pasive, Active and Digital Filters", Wai-Kai Chen [1]). Para este ejemplo utilizaremos la transformación forward Euler, por lo que nuestro controlador queda representado en tiempo discreto por la TF:
Para este ejemplo se sabe de antemano que este controlador es estable pero si se arriesga a utilizar foward Euler se recomienda verificar estabilidad (puede usarse sisotool de Matlab). Verificamos en Simulink que nuestro controlador funcione correctamente:
Ahora podemos proceder a la conversión de formatos de la FT. Para eso utilizamos el este programa de Matlab: PIDdiscreto.mat. Usando los datos que nos muestra el programa la FT nos queda:
Calculando transformada inversa:
Finalmente, verificamos que la ecuación de diferencias sea correcta en Simulink:
En una próxima entrada se implementará este controlador en un código en C para PIC y Arduino.
domingo, 15 de noviembre de 2015
Temas de actualidad
Yo que soy un derechairo-liberal declarado tengo la sospecha que el atentado en París ha sido un evento de falsa bandera. De ser verdad podría ayudarnos a nosotros, ratas de ese laboratorio sociológico llamado Facebook, a decidirnos de que lado estar en esta batalla virtual. Pero ahora, ¿hasta que punto una bandera representa al Leviatán o representa al pueblo? Aún resolviendo eso queda otro problema, ¿a que pueblo se le debe mostrar empatía? A todos en el caso ideal, por supuesto. Pero esta solución genera otro problema; por más utopías que quieran sacarse de la manga, los seres humanos no podemos vivir sin fronteras (en todos los contextos posibles). Siempre he tenido como lema personal esta frase de Huygens, "El mundo es mi país, la ciencia mi religión", pero me he dado cuenta que en un contexto no político, esto no es verdad para mí. Existen muchos grupos sociales que respeto (siendo terriblemente sincero, otros no) más no puedo identificarme. Cargo en mi mente, como todos, fronteras invisibles definidas por reglas de pertenencia social. Y aquí una triste verdad. Aunque lo correcto sea mostrar empatía por la humanidad entera, la paradoja de la elección viene a arruinaros la paz. Elegir todo no es diferente a elegir nada.
miércoles, 11 de noviembre de 2015
Guanajuato
Suscribirse a:
Entradas (Atom)





























