Memoria PFC-4

Anuncio
Software para la simulación del comportamiento del
conjunto Motor DC - Encoder
TITULACIÓ: Enginyeria en Automàtica i Electrònica Industrial.
AUTOR: Jacob Pié Vallvé.
DIRECTOR: Esteban del Castillo Pérez.
DATA: Juny / 2012
Índice
1
Memoria Descriptiva ........................................................................................... 4
1.1
Introducción ................................................................................................. 5
1.2
Objetivo ....................................................................................................... 5
1.3
Descripción de la Planta .............................................................................. 6
1.4
Modelado de la Planta................................................................................ 16
1.4.1 Modelo del Motor de corriente continua ................................................ 16
1.4.2 Análisis del modelo obtenido del Motor de corriente continua ............. 20
1.4.3 Excitación PWM y sus efectos ............................................................... 23
1.4.4 Conjunto Excitación PWM + motor DC ................................................ 29
1.4.5 El control PID......................................................................................... 32
1.4.6 Lazo de Control ...................................................................................... 35
1.4.7 Sintonización Controlador PID .............................................................. 36
1.4.8 Errores del sistema ................................................................................. 39
1.5
Emulador de la Planta ................................................................................ 42
1.6
Software de simulación de la Planta .......................................................... 47
1.6.1 Descripción del Software ....................................................................... 48
1.6.2 Librería Q5.h .......................................................................................... 49
1.6.3 Librería k1.h ........................................................................................... 54
1.7
2
Anexo A ............................................................................................................ 65
2.1
3
Modo de Uso .............................................................................................. 60
El motor de corriente continua................................................................... 66
Anexo B............................................................................................................. 72
3.1
Código Librería Q5.h ................................................................................. 73
3.2
Código Librería K1.h ................................................................................. 74
Proyecto final de carrera
Página 2
4
5
Anexo C............................................................................................................. 78
4.1
Librería 8259.h ........................................................................................... 79
4.2
Librería Ini_IRQ.h ..................................................................................... 80
4.3
Librería PID.h ............................................................................................ 81
4.4
Librería Printer.h ........................................................................................ 82
4.5
Librería PWM.h ......................................................................................... 84
4.6
Librería Timer.h ......................................................................................... 84
4.7
Librería Main.c .......................................................................................... 86
4.8
Librería Ini_IRQ.c ..................................................................................... 90
4.9
Librería PID.c ............................................................................................ 94
4.10
Librería PWM.c ......................................................................................... 96
4.11
Librería Timer.c ......................................................................................... 98
Anexo D: Referencias ..................................................................................... 103
Proyecto final de carrera
Página 3
1
Memoria Descriptiva
Proyecto final de carrera
Página 4
Memoria descriptiva
1
Memoria Descriptiva
1.1
Introducción
Dentro del marco de asignaturas que se imparten en el plan de estudios de primer
ciclo de la Ingeniería Técnica Industrial en Electrónica Industrial se encuentra la asignatura
Informática Industrial II.
En esta asignatura se forma al alumnado para que obtenga los conocimientos de
hardware y software necesarios para la elaboración de software de control en un PC.
Dentro de los créditos de la asignatura, se realizan unas prácticas en los laboratorios
habilitados, donde se ejercitan los conocimientos adquiridos. Estas prácticas consisten en
implementar un control de velocidad y de posición del eje de un motor de corriente
continua, a través del interfaz del puerto paralelo de un PC bajo el sistema operativo MSDOS, utilizando como lenguaje de programación el lenguaje C.
Para el desarrollo de las prácticas se dispone de una “planta”, la cual está formada
por un motor de corriente continua, un encoder relativo y un circuito electrónico que
realiza la función de interface entre el puerto paralelo del PC y el conjunto motor-encoder.
Desafortunadamente, esta planta sólo está disponible en los laboratorios habilitados para la
asignatura. Para facilitar el desarrollo de las prácticas, el profesor titular de la asignatura
realizo un circuito electrónico que emulaba la planta en cuestión, de esta manera el
alumnado podía avanzar en el desarrollo de las practicas fuera de la universidad.
Desgraciadamente, a causa de la tendencia en los últimos años en la utilización de
ordenadores portátiles para el desarrollo individual de las prácticas por parte del alumnado,
surge el problema de que estos nuevos equipos raramente tengan accesible externamente el
puerto paralelo, aunque este esté implementado la placa base como PC compatible, con lo
que comporte que el emulador pierda su funcionalidad.
Para desarrollar la parte teórica de este proyecto se ha utilizado como referencia
bibliográfica el libro escrito por el sr Esteban del Castillo – Control de Procesos, donde
describe la implementación de una plataforma hardware/software aplicada al conjunto
motor dc-encoder.
1.2
Objetivo
El objetivo del presente proyecto es implementar un simulador software a base de
librerías basadas en lenguaje de programación C que simule el comportamiento de la
“planta” disponible en los laboratorios de la asignatura.
Proyecto final de carrera
Página 5
Memoria descriptiva
1.3
Descripción de la Planta
La “planta” utilizada en los laboratorios de la asignatura está formada por 3 piezas
bien diferenciadas:
-
Motor de corriente continua
Encoder relativo
Placa electrónica interface puerto paralelo – PC
Figura 1. “Planta” utilizada en los Laboratorios
1.3.1.1 Motor de corriente continua
La máquina motriz utilizada es un motor de corriente continua de imanes
permanentes del fabricante Maxon, de la serie F2140, concretamente el modelo 2140.93758.236-050. Obtener el modelo concreto del motor es interesante para poder realizar un
estudio de la planta, obteniendo dados particulares de su comportamiento de su hoja de
características.
Cabe destacar el tipo de motor utilizado es un motor de corriente continua de
imanes permanentes. Este tipo de motores están clasificados como máquinas especiales
Proyecto final de carrera
Página 6
Memoria descriptiva
dentro del campo de las máquinas eléctricas, este hecho nos dificultara su estudio, ya que
gran parte de simuladores de circuitos eléctricos no contempla este tipo de motores, sólo
los motores de excitación independiente.
En la figura nº 2 mostramos las principales especificaciones del motor, donde
podremos observar los datos necesarios para su posterior modelado, pudiendo de esta
manera comprobar que el modelo realizado se aproxima a la realidad.
Figura 2. Características principales motor dc
De la hoja de características podemos obtener los datos para el modelado del motor
los cuales son los siguientes:
Resistencia óhmica en bornes armadura (Ra)
Inductancia en bornes armadura (La)
Constante de tiempo mecánica (τm)
Inercia del rotor (J)
Constante de velocidad
Constante mecánica (km)
Velocidad en vacío
A modo de información para el alumnado, hemos descrito las principales
características de los motores de corriente continua en el anexo A, para así comprender el
significado de estos.
Más adelante realizaremos un estudio para obtener un modelo aproximado del
motor para poder realizar una simulación de la “planta”.
Proyecto final de carrera
Página 7
Memoria descriptiva
1.3.1.2 Encoder relativo
Para un control de velocidad o posición del motor se necesita posicionar el eje de
este a través de algún elemento que nos proporcione la información necesaria para
determinarlo. Una forma sencilla de obtener esta posición o velocidad es conectando el eje
del motor a un encoder.
En el mercado existen muchos tipos de encoders con características factibles para
realizar esta operación.
En este caso, la planta disponible en el laboratorio está equipada con un encoder
relativo bidireccional de dos canales de salida A y B, el cual permite detectar el sentido de
rotación del eje. Este es de la marca Hohner, de la serie 21, modelo 21-122-200 de 200
pulsos por vuelta.
En la figura 3 mostramos el interior de un encoder relativo para podernos hacer una
idea de cómo están construidos.
Figura 3. Interior teórico Encoder incremental
Es de gran importancia comprender el funcionamiento del encoder y las señales que
nos proporcionará, para poder realizar las prácticas del laboratorio de la asignatura
Informática Industrial II, tanto las rutinas que tendremos que implementar nosotros en el
presente proyecto para simular el comportamiento de este.
En la figura nº 4 mostramos las señales A y B con el paso del tiempo. Como
podemos observar, éstas están desfasadas entre ellas 90 º. A través de esta característica
podremos observar el sentido de giro del motor. Por ejemplo, si la lectura actual de las
señales A y B es 01 y la anterior era 11, el sentido de giro será hacia la derecha, en cambio,
si la lectura anterior era 00, el sentido de giro será hacia la izquierda.
Proyecto final de carrera
Página 8
Memoria descriptiva
Figura 4. Señales A y B del encoder
1.3.1.3 Placa electrónica interface puerto paralelo – PC
Para poder utilizar el motor y el encoder a través de nuestro PC tenemos que tener un
interface que comunique ambas partes.
La placa electrónica montada en el conjunto motor-encoder está formada por dos
partes bien diferenciadas. La primera tiene la función de atender las salidas de nuestro PC a
través del puerto paralelo y adecuar estas señales con la suficiente potencia para atacar al
motor de corriente continua. La segunda, adapta las señales generadas por el encoder para
que esa información pueda ser utilizada y leída por puerto paralelo.
Cabe puntualizar que el motor de corriente continua es un actuador que modifica la
velocidad de salida según el valor medio de la tensión de excitación. A razón de esto,
nuestra etapa de potencia tiene que ser capaz de realizar pequeñas variaciones del valor
medio de la tensión de salida. Generalmente cuando se debe realizar esta operación en las
aplicaciones de control se utiliza la técnica de la modulación de anchura de pulsos, o más
bien conocido por PWM.
En la figura nº 11 mostramos el esquema de este interface. Si analizamos el esquema
de potencia, podemos observar que el circuito de excitación de motor está formado por un
puente en H de transistores. Estos transistores se han escogido con especial cuidado, ya que
deben que tener unas características especiales.
Si recordamos como está formado constructivamente el interior de un motor de
corriente continua, veremos que está compuesto por unas bobinas. Éstas, durante el
se cargan de energía, el problema surge en el período de
. Cuando llega el
período
período
el transistor no conduce, pero por la inductancia sigue circulando una IL,
encontrándose la necesidad de dar continuidad a la corriente magnetizante. Para evitar la
rotura del transistor, estos tienen que llevar incorporado un diodo volante para poder
realizar la descarga de la corriente de la bobina en los periodos de desconexión.
Otro punto a tener en cuenta es el aislamiento galvánico de la placa electrónica. Las
corrientes inducidas por las bobinas del motor provocan ruidos en las tensiones de
alimentación, al igual que la conmutación de los devanados del inducido sobre su colector
Proyecto final de carrera
Página 9
Memoria descriptiva
de delgas, que se podrían propagar a las señales del puerto paralelo del PC, pudiendo dar a
errores de lectura o escritura en la salida del puerto. [1]
Sin dejar de analizar la parte de potencia, podemos ver que se ha implementado una
protección eléctrica en el circuito de control del puente de transistores para evitar la
conexión simultánea de los dos ramales de alimentación.
Pin DB2
Pin DB3
Señal
Derecha
Señal
Izquierda
0
0
1
1
0
1
1
0
1
0
0
1
1
1
1
1
Figura 5. Tabla Verdad Pins DB2 y DB3
Para poder activar cada ramal individualmente, el diodo del optoacoplador debe
entrar en modo de conducción. Este sólo entrará en este modo si la señal proporcionada por
el bloque lógico es cero, tal y como mostramos en la tabla de la verdad descrita
anteriormente, de lo contrario restará abierto.
Por otra parte, como hemos dicho con anterioridad, el encoder que tenernos instalado
en nuestra planta entrega dos señales en cuadratura, a partir de la cuales podremos detectar
el sentido de giro del motor.
Para poder detectar un cambio de sentido se deberá realizar un seguimiento de la
secuencia proporcionada por el encoder de las señales A y B, tal y como mostramos en la
figura nº 6.
Figura 6. Señales de salida circuito acondicionador encoder
Proyecto final de carrera
Página 10
Memoria descriptiva
Como podemos ver, cada vez que alguna de las señales A y B cambia de estado, a
través de un flanco de subida o bajada, el bloque lógico del interface del conjunto motormotor
encoder detecta el cambio y genera la correspondiente interrupción en el puerto paralelo.
par
Los valores que se observan justo en el flanco en que se provoca la interrupción son los
valores de las señales A y B, de esta manera podremos observar el sentido de giro del eje
del motor.
Donde la secuencia a seguir seria:
Figura 7. Sentido de giro
Para poder seguir la secuencia generada por el encoder, el interface motor – PC lleva
incorporado un bloque lógico que genera una señal adecuada para interrumpir la CPU del
PC justo cuando acontecen los flancos de subida y bajada de las señales A y B del encoder.
Para poder detectar los flancos originados por el encoder se ha utilizado un circuito
lógico basado en un diferenciador.
Figura 7. Circuito diferenciador
Como se observa en la figura 7 el circuito diferenciador detecta los flancos
ascendentes
endentes y descendentes. Esta será la base para crear el bloque lógico.
Para poder calcular la red RC tenemos que tener en cuenta la frecuencia máxima en
que el encoder nos entregara las señales. A razón de una velocidad máxima de nuestro
motor de 3980 rpm y que el encoder utilizado provoca 800 flancos por revolución,
tendremos:
Proyecto final de carrera
Página 11
Memoria descriptiva
Por lo cual tendremos un flanco cada
. Si suponemos que las ventanas del
encoder no están todas alineadas, nos podría llegar un flanco en un intervalo menor. Para
solventar deficiencias mecánicas podemos reducir este tiempo a
como coeficiente de
seguridad.
Por otra parte, cabe puntualizar que para preservar los estados de la señal en su
tránsito por los cables, debemos acotar la anchura del pulso de bajada. Un valor del orden
de
es adecuado.
En la siguiente figura mostramos el bloque lógico detector de flancos, el cual
responde a la siguiente ecuación:
Figura 8. Bloque lógico
donde
caída igual a 1.8 V, entonces para
viable es una
y
siendo
implicara una
. [1]
el umbral del inversor en
, donde una solución
Figura 9. Detector de flancos ascendentes y descendentes
Proyecto final de carrera
Página 12
Memoria descriptiva
En la figura nº 9 mostramos el bloque lógico correspondiente a la señal A del
encoder para poder detectar tanto los flancos ascendentes y descendentes de la señal en
cuadratura.
La resistencia
y
limitan la corriente derivada por el diodo interno de la puerta
inversora a valores inferiores a 1 mA si el valor de la resistencia es de 5,6 kΩ. [1]
En la siguiente figura podemos observar las señales generadas por el bloque detector
de flancos, donde la señal azul corresponde a la señal en cuadratura del encoder llamada A,
y en cada flanco la correspondiente detección por parte de cada bloque detector, detectando
tanto el flanco ascendente como el descendente. Nótese la amplitud del pulso generado por
para suplir las deficiencias de los conductores de transporte de la
el bloque, siendo de 4
señal.
Figura 10. Señales resultantes del bloque de detención de flancos.
El bloque lógico implementado tiene que ser lo suficientemente rápido para poder
generar la solicitud a las interrupciones adecuadamente. Es importante que el tiempo en
nivel cero de la señal generada sea el menor posible, de esta manera el tiempo de esta en
nivel 1 será el más grande posible. De esta manera si tenemos una velocidad elevada del
motor el bloque lógico tendrá tiempo de generar los dos pulsos de interrupción entre las
ventanas de cuadratura del encoder, ya que la señal de solicitud tendrá un pulso por paso
por cero muy pequeño.
En la figura nº 11 mostramos todo el montaje del interface para utilizar el conjunto
motor-encoder, compuesto por las partes de potencia que alimenta al motor y lógica de
control, que adapta las señales del encoder al puerto paralelo del PC.
Proyecto final de carrera
Página 13
Memoria descriptiva
Figura 11. Esquema placa Interface con el PC
En la tabla nº 1 mostramos la asociación de señales y pins del puerto paralelo.
Podemos observar la dirección de la información de cada pin.
En la Tabla nº 2 mostramos los registros propios del puerto paralelo y la asociación
con el conector de la Tabla nº 1. Ell registro base de un puerto paralelo está ubicado en una
de las direcciones 0x378, 0x278 o 0x3BC.
Los pines utilizados por el interface motor – PC son los siguientes:
siguientes
Pins 2 y 3 del Registro Base + 0 (ataque puente transistores)
Pins 12 y 13 del Registro Base + 1 (información del encoder)
Pin 10 del Registro Base + 2 (activación de la IRQ del Puerto)
Proyecto final de carrera
Página 14
Memoria descriptiva
Señal
Pin
Dirección
/Strobe
1
OUT
Data 0
2
OUT
Data 1
3
OUT
Data 2
4
OUT
Data 3
5
OUT
Data 4
6
OUT
Data 5
7
OUT
Data 6
8
OUT
Data 7
9
OUT
/Acknowledge
10
IN
Busy
11
IN
Paper End
12
IN
Select
13
IN
/Auto Feed
14
OUT
/Error
15
IN
/Inicialize Printer
16
OUT
/Select Input
17
OUT
18-25
-
Ground
Tabla 1. Puerto DB25 PC
Base + 0: Registro de lectura/escritura
Bit 7
Pin 9
Bit 6
Pin 8
Bit 5
Pin 7
Bit 4
Pin 6
Bit 3
Pin 5
Bit 2
Pin 4
Bit 1
Pin 3
Bit 0
Pin 2
Bit 3
Pin 15
Bit 2
-
Bit 1
-
Bit 0
-
Bit 2
Pin 16
Bit 1
/Pin 14
Bit 0
/Pin 1
Base + 1: Registro de solo lectura
Bit 7
/Pin 11
Bit 6
Pin 10
Bit 5
Pin 12
Bit 4
Pin 13
Base + 2: Registro de lectura/escritura
Bit 7
-
Bit 6
-
Bit 5
-
Bit 4
IRQ
Bit 3
/Pin 17
Tabla 2. Registros del puerto paralelo
Proyecto final de carrera
Página 15
Memoria descriptiva
1.4
Modelado de la Planta
Durante el transcurso de la carrera se han realizado asignaturas donde se imparte
teoría para modelar plantas en el espacio del control continuo y la implementación de
controladores
ontroladores para su control.
control
Encontramos interesante realizar un estudio del modelado de una planta real donde
podremos simular elementos concretos, estudiar sus respuestas y comprobar las
aproximaciones realizadas durante el modelado respecto al elemento real.
real De esta manera
encontrándonos
ndonos con problemas reales del modelado y la correcta identificación de los
parámetros suministrados por los fabricantes de los elementos (motor dc, encoder …).
…)
En la referencia bibliográfica nº 2 podemos encontrar en un pequeño resumen de la
identificación
ción de los parámetros y modelado de un pequeño motor de corriente continua.
1.4.1 Modelo
delo del Motor de corriente continua
conti
En la figura nº 12 mostramos el esquema del cual partiremos para modelar el motor
de corriente continua de imanes permanentes,
permanentes obteniendo su modelo matemático y
representándolo en el programa de simulación Matlab.
Figura 12. Motor DC imanes permanentes
Partimos de las siguientes expresiones en el dominio de Laplace, las cuales
representan el comportamiento eléctrico del motor:
Combinando las ecuaciones 1 y 2 obtendremos la corriente de armadura
Proyecto final de carrera
Página 16
Memoria descriptiva
4
Por otra parte, el par generado por el motor es el siguiente:
5
El par mecánico neto en el eje del motor
será el resultante de:
6
Combinando las ecuaciones 4 y 6 obtenemos la relación entre el torque neto
con la corriente de armadura.
7
En la siguiente figura, mostramos el esquema de bloques el modelo matemático del
motor de corriente continua con excitación permanente a través de los imanes de su estator.
Figura 13. Modelo matemático Motor DC
Proyecto final de carrera
Página 17
Memoria descriptiva
Por otro lado, utilizando la segunda ley de Newton, obtenemos que el par neto
del motor es:
!
"
8
donde ! corresponde al momento de inercia del eje del motor y su carga y " la
fricción de estos.
Si consideramos que el par perturbador
8 obtendremos:
!
es nulo e igualamos las ecuaciones 7 y
9
"
operando la ecuación 9:
!
10
"
' !
(
"
11
obteniendo la función de transferencia del motor a partir de la ecuación nº 11
' !
(
"
12
identificando los términos:
!
*
' !
"
(
"
13
donde tendríamos que tener una función normalizada de la forma:
,
Proyecto final de carrera
*
- *
2 . -
-
*
Página 18
Memoria descriptiva
Esta función de transferencia es la que describe la figura de bloques nº 8, siendo un
sistema de segundo orden. Generalmente llegados a este punto, se suele simplificar la
ecuación de transferencia despreciando
frente de
y la / frente la / obteniendo así
una función de transferencia de primer orden.
Quedando la función de transferencia descrita en la ecuación nº 13 de la siguiente
manera:
!
14
"
Al igual que en el sistema de segundo orden, deberíamos buscar la función de
transferencia equivalente normalizada.
,
,0
/
1
entonces:
!
"
"
"
!
1
15
de forma que:
,0
/
Proyecto final de carrera
16
"
"
!
17
Página 19
Memoria descriptiva
1.4.2 Análisis del modelo obtenido del Motor de corriente continua
Una vez realizado el modelado del comportamiento físico del motor podemos pasar a
simular los resultados obtenidos en los sistemas de primer y segundo y contrastarlos con
las características proporcionadas por el fabricante.
De esta manera podremos comprobar la diferencia entre modelos, si la hubiera, y los
diferentes resultados según la inclusión u omisión de ciertos parámetros.
1.4.2.1 Simulación sistema segundo orden
El sistema a simular en este apartado está representado en la figura nº 13. Este es un
modelo de segundo orden sin realizar ninguna apreciación o simplificación, excepto la de
considerar el torque perturbador
nulo.
La simulación de este se realizará en lazo abierto para observar la respuesta de este a
un escalón unitario.
Los parámetros subministrados por el fabricante los podemos encontrar en la figura
nº 2 de la memoria descriptiva de este proyecto. Estos parámetros son los siguientes:
41,5 2
-
5,02 34
-
55,2 353/7
-
!
;
==
22,1 893²
?
24
Podemos observar que el fabricante, en los datos proporcionados, no habla en ningún
momento del coeficiente de fricción que tiene el rotor. Considerando que es un motor muy
pequeño, podemos estimar que este coeficiente debe ser nulo. Entonces realizaremos una
primera aproximación de este modelo y efectuaremos la simulación del sistema sin este
parámetro.
En la figura nº 14 podemos observar el resultado obtenido de la simulación del
sistema. Podemos apreciar que este no se ajusta del todo a la realidad según los parámetros
entregados por el fabricante.
Proyecto final de carrera
Página 20
Memoria descriptiva
Figura 14. Simulación modelo 2º orden sin coeficiente de fricción.
Según los datos de la figura nº 2 la velocidad del motor en vacío es de 3980 rpm, en
la simulación del modelo obtenemos una velocidad en vacío de 4151,5 rpm, lo que supone
una diferencia entre el modelo y los datos reales del 4,3 %.
Esta diferencia entre los datos del fabricante y los obtenidos en la simulación puede
venir causada por la aproximación realizada en la omisión del coeficiente de fricción del
modelo.
Para obtener el valor del coeficiente de fricción del rotor tenemos una aproximación
matemática:
;>
!
/
18
que nos relaciona la inercia del rotor y la constante mecánica del sistema para
obtener el coeficiente de fricción. Aplicando la formula, obtenemos:
;
!
/
22.1 10@A
30 10@B
7.36 10@C
Con este término, deberían coincidir los resultados de una nueva simulación con el
modelo completo del motor, pero debemos ajustar este valor hasta 3,17 10@D para que los
resultados obtenidos sean iguales al del fabricante.
Proyecto final de carrera
Página 21
Memoria descriptiva
1.4.2.2 Simulación sistema primer orden
La ecuación nº 15 de la memoria descriptiva representa la simplificación del modelo
del motor a un sistema de primer orden. La ecuación de transferencia normalizada de un
sistema de primer orden, como hemos descrito anteriormente, es:
,
/
,0
1
Si paramos atención a la ecuación, podremos identificar los términos que la definen
en los datos proporcionados por el fabricante. Siendo más sencillo realizar la simulación
del sistema con estos datos que no a través de la ecuación encontrada mediante el
modelado.
Donde ,0 es la ganancia del sistema en E F ∞ que podemos identificar con el
parámetro denominado como constante de velocidad (definido en el Anexo A) con un
valor de 173 rpm/V. Por otra parte, la / del sistema la podemos identificar con la / del
motor, con un valor de 30 10@B segundos.
Con estos datos podemos proceder a realizar la simulación del sistema de primer
orden, obteniendo estos resultados mostrados en la figura nº 15.
Estos resultados son muy semejantes a los resultados obtenidos en la primera
simulación del modelo de segundo orden, mostrados en la figura nº 14, donde no se tenía
en cuenta el coeficiente de fricción del rotor.
Si leemos con detenimiento la definición del parámetro de la constante de velocidad
podremos ver que el valor suministrado por el fabricante no tiene en cuenta las pérdidas
por fricción, de ahí la semejanza de resultados.
Figura 15. Simulación modelo 1º orden.
Proyecto final de carrera
Página 22
Memoria descriptiva
Teniendo en cuenta la definición de esta constante y realizando un pequeño ajuste de
esta en el modelo, obtendremos los siguientes resultados:
Figura 16. Simulación modelo 1º orden con parámetros ajustados.
Con la constante de velocidad ajustada a 165,83 rpm/V, obtenemos un modelo
aceptable del motor de corriente continua de imanes permanentes. A partir de este punto
utilizaremos este modelo para la realización del resto de simulaciones.
1.4.3 Excitación PWM y sus efectos
Como ya hemos descrito con anterioridad, el motor de corriente continua está
alimentado a través de un puente en H de transistores con diodo volante y controlados por
una excitación PWM.
Este tipo de excitación provoca unos efectos sobre el motor dependiendo del tiempo
de HI y HJJ en que nos encontremos, los cuales se traducen en una alimentación
pulsante con periodos de KK y 0V respectivamente. Durante el periodo de HI el transistor
está en modo de conducción y por las bobinas del motor circula , pero en HJJ el
transistor corta la alimentación del motor y anula la corriente
a su través. En
consecuencia, se abre camino a través del diodo volante del transistor.
Proyecto final de carrera
Página 23
Memoria descriptiva
Estee tipo de excitación modifica el comportamiento del modelo del motor estudiado
hasta ahora [1].. Para comprobar este efecto,
efecto hemos simulado el motor en el programa de
simulación PSIM y Pspice para observado su comportamiento.
Inicialmete hemos simulado la midad del puente en H con el programa Pspice con
transitores sin diodo volante, para verificar la hipotesis inicial. Como carga hemos
conectado una red RL de caracteristicas similares al modelo de primer orden.
Figura 17. Ramal derecho puente H.
En la siguiente figura se pueden observar la evolución
ev
temporal de la tensión y de la
intensidad en la carga en la simulación del ramal derecho del puente en H (sin diodos
volantes).
Figura 18. Resultado simulación Ramal derecho puente H.
Proyecto final de carrera
Página 24
Memoria descriptiva
Podemos observar que justo en el flanco de bajada donde se produce la desconexión
por parte del transistor darlingthon se genera un pico negativo de tensión, que corresponde
a la corriente magnetizante de la carga intentando abrise camino por las uniones de los
transistores. En el caso de no incorporar diodo volante, estos transistores podrían dañarse.
La simulación realizada es a titulo informativo y no es comparable en magnitud al
estudio realizado del modelo del motor y su excitación, y a que la carga simulada no se
ajusta totalmente al modelo anterior.
Siguiendo con el estudio, realizaremos una comparación para encontrar la diferencia
entre ambas excitaciones, Pero cabe nombrar que el programa de simulación PSIM no
incluye la librería para simular el motor de DC de imanes permanentes, soló el motor DC
de excitación independiente, el cual hemos tenido que adaptar para conseguir las mismas
características que el motor de nuestro modelo. Seguidamente especificamos los
parámetros empleados.
Figura 19. Parámetros modelo motor DC para PSIM .
En la figura nº 20.1 mostramos el esquema de la excitación PWM sin diodo volante y
en la figura nº 20.2 el esquema con el diodo incorporado.
Proyecto final de carrera
Página 25
Memoria descriptiva
Figura 20. Circuito simulación comportamiento PWM sobre motor dc.
En la figura nº 21 podemos observar el resultado de la simulación sin diodo volante
en los transistores de alimentación al motor. Se puede ver el pico de tensión negativa justo
en la desconexión por parte de los transistores.
Figura 21. Tensión transistor de la excitación PWM sin diodo volante.
En la figura nº 22 se muestra la tensión del transistor con diodo volante incorporado.
Se observa que el pico negativo justo en la desconexión del transistor se ha reducido
considerablemente, concretamente a 1.4V que corresponde a la suma de la tensión en cada
diodo en modo de conducción.
Cabe puntualizar que las magnitudes de los valores mostrados en las graficas 21 y 22
son magnitudes aproximadas ya que ha utilizado una carga de 1º orden similar al modelo
del motor.
Proyecto final de carrera
Página 26
Memoria descriptiva
Figura 22. Comparación entre modelos de la corriente armadura motor dc.
Visto que la alimentación del motor es de tipo pulsante y no de forma continua a
causa del tipo de excitación, modificaremos el modelo para incluir esta variación del
comportamiento.
Si reemprendemos el estudio del modelo de primer orden encontrado en la ecuación
nº 15 e incluimos este efecto, tendremos el siguiente modelo [1]:
Figura 23. Esquema modelo + excitación.
Donde la función de transferencia es:
,
Proyecto final de carrera
"
"
!
1
18
Página 27
Memoria descriptiva
Despreciando los términos resultantes del producto de
tendremos la ecuación:
"
,
!
"
"
frente al producto de
19
1
Donde sustituiremos las variables A y B para poder trabajar con más claridad en el
modelo, quedando:
7
L
"
M
!
"
20
Si resolvemos el lazo de control del circuito anterior, obtendremos:
1
M
M
7
7
1
7
1 7
M
1
7
7
M
7
1
1
1
21
Substituyendo con los datos obtenidos en los análisis anteriores tendremos como
resultado final:
!
22,1 10@A 3² ,
"
4 10@D ,
1959,73
0.35
1
41,5 2 ,
55,2 353/7
22
Volviendo al tema que nos ocupaba al inicio del capítulo, la excitación PWM debe
convertir una señal analógica con valor de == a una señal digital de periodo y amplitud
constantes, obteniendo como resultado una señal con valor medio proporcional a la señal
de entrada. Esta proporción se alcanza variando el tiempo de E y ajustando el tiempo de
E
conservando de esta manera el tiempo T constante sin variar el periodo de la señal.
La función de transferencia del sistema será:
3
Proyecto final de carrera
==
E
23
Página 28
Memoria descriptiva
y su modelo en Simulink:
Figura 24. Esquema modelo PWM.
1.4.4 Conjunto Excitación PWM + motor DC
Como ya habremos podido intuir con los resultados vistos en el apartado anterior, la
velocidad instantánea de nuestro motor se ve influida directamente por la frecuencia de la
excitación PWM. Si observamos la figura nº 25 vemos unas fluctuaciones de velocidad que
del PWM.
vienen causadas por los periodos de E y E
Si alimentamos la entrada (m) del modulador PWM con una rampa unitaria
observaremos en la respuesta del conjunto una amplia zona con fluctuaciones de velocidad
[1]. En la figura nº 25 se muestra la gráfica de la velocidad de salida del sistema frente al
ciclo de trabajo del la excitación PWM en forma de rampa con pendiente unitaria
(multiplicando el eje X por un factor de 100 para observar mejor el efecto) donde se hacen
presentes estas fluctuaciones.
Figura 25. Respuesta del sistema.
Proyecto final de carrera
Página 29
Memoria descriptiva
Las fluctuaciones de velocidad que se observan son a consecuencia de una
frecuencia relativamente baja de la excitación PWM. Conociendo que la constante
mecánica del motor es de 30 ms y que el periodo del PWM es de 20 ms, surge este efecto a
causa de la proximidad de ambos tiempos. Este efecto puede ser reducido aumentando la
frecuencia de conmutación de la excitación.[1]
En la figura nº 24 se expone la evolución de la velocidad del motor y la señal del
PWM de forma idealizada.
Figura 26. Evolución de la velocidad del motor
La evolución de la velocidad entre ambos tramos viene dada por la siguiente
ecuación:
O
N
N NP
N
Q
@RU
ST
24
donde N es la velocidad final a que llegaría el motor para t WX T y V[[ 10 ,
siendo N
1640 \]3 y zero en t W^^ T y V[[ 0 , N N es la velocidad inicial de
partida y / es la constante de tiempo mecánica del motor.
Si consideramos que la constante de tiempo mecánica del motor es la misma para
cuando el motor aumenta su velocidad que cuando disminuye, se deducen las siguientes
ecuaciones:
_
N
O
*
Considerando que para E
P Q
N
Q
@RU
ST
t WX ,
]`\` 0 a E a t WX
25
]`\` t WX a E a T
_
*
N
Proyecto final de carrera
@RU
ST
1
y que para E
1
7
7 M
26
T,
nos queda:
27
Página 30
Memoria descriptiva
M
*
28
donde:
7
M
Q
Q
=
b
ST
@ =
b
ST
29
30
En la figura nº 27 mostramos el resultado de la simulación de las anteriores
ecuaciones, obteniendo la relación existente del rizado de la velocidad *
frente al
ciclo de trabajo (dc).
Se puede observar claramente que cuanto mayor es la frecuencia de la excitación del
PWM, menor es el rizado del motor, con lo que comporta que la frecuencia de
conmutación no puede ser escogida a la ligera. A priori podríamos pensar que cuanto más
elevada sea esta mejor, ya que tendríamos un rizado muy pequeño, pero se tienen que tener
en cuenta otros factores, como por ejemplo, la resolución temporal de nuestro sistema…
En este caso, debemos tener en cuenta que el tic del sistema se utiliza para generar la onda
de la excitación PWM, siempre que la frecuencia del PWM sea del orden de magnitud de
10 veces mayor que la resolución del sistema no se intuyen problemas en la generación de
la onda de excitación del PWM. Por ejemplo un tic de 50μ y una frecuencia PWM de
0.53 .
Figura 27. Rizado de velocidad en función del ciclo de trabajo
Proyecto final de carrera
Página 31
Memoria descriptiva
1.4.5 El control PID
Las siglas del controlador responden a la identificación de las partes activas de este,
definido por las letras PID (Proporcional – Integral – Derivativo). [2]
Donde:
-
P es la acción de control proporcional y da una salida del controlador que es
proporcional al error actual, respondiendo a la siguiente función de
transferencia:
L E
donde
-
d
d
Q E
31
es la constante proporcional ajustable.
I es la acción de control integral y da una salida del controlador que es
proporcional al error acumulado, respondiendo a la siguiente función de
transferencia:
L E
1
N
R
eQ E
0
f E
32
El bloque integral tiene como propósito disminuir y eliminar el error en estado
estacionario provocado por el modo proporcional. El control integral
actúa cuando hay una desviación entre la variable y el punto de consigna,
integrando esta desviación en el tiempo y sumándola a la acción proporcional.
-
D es la acción de control derivativo, la cual tiene un carácter de previsión al
error con lo que hace más rápida la acción del controlador, aunque tiene la
desventaja de amplificar las señales de ruido y provocar la saturación en el
actuador. Esta responde a la siguiente función de transferencia:
L E
Proyecto final de carrera
fQ E
f E
33
Página 32
Memoria descriptiva
La suma de estas tres acciones responde a la función de transferencia:
L E
d
1
gQ E
N
R
eQ E
0
fQ E
h
f E
f E
34
Este algoritmo será implementado por el alumnado dentro de las practicas de la
asignatura, y formará parte del software que se elabore, no siendo una parte física de
nuestra planta.
El algoritmo del controlador PID se tendrá que discretizar ya que será ejecutado en
un sistema de procesado digital. De esta manera, la ecuación del controlador quedará de la
siguiente manera:
∆L
∆L
d
L
LO
Q
j1
N
*Q
k,
*
1
1
d
j1
P
35
BQ
2
k
2
L
36
B
d
37
La ecuación nº 36 proporcionará al alumno el incremento que debe aplicar a la salida
actual para corregir la respuesta del sistema. Si observamos la ecuación podremos ver que
el controlador utiliza muestras anteriores del error para determinar el nuevo incremento en
la salida, de esta forma sigue su evolución.
Para poder utilizar la función discretizada en Simulink debemos emplear la
transformada zeta. Simulink ya dispone de bloques preestablecidos para la discretización
de ecuaciones, veamos el esquema de bloques.
Figura 28. Unidad de retardo transformada zeta
A través de este bloque podremos realizar el retardo de una muestra, consiguiendo
por ejemplo Q
1 .
Proyecto final de carrera
Página 33
Memoria descriptiva
En la siguiente figura mostramos la suma de todos los bloques del controlador, ya
discretizados y en formato Simulink. Hemos enmarcado los bloques por funcionalidad para
una mejor identificación.
Figura 29. Controlador PID discretizado
De la ecuación nº 36 podemos desgranar directamente este esquema, donde el bloque
integrador multiplica el error actual por la constante / N , el bloque proporcional resta al
valor actual del error el error anterior, resultando el incremento de error desde
1 a ,
1 y
2
y la parte diferencial tiene en cuenta la evolución de los incrementos en
y lo multiplica por la constante / .
Para un sistema de control con un amplio rango de condiciones de operación, puede
suceder que la variable de control alcance los límites prefijados del actuador. Cuando esto
pasa, el bucle realimentado permanece en su límite independientemente de la salida del
proceso. Si se usa un controlador con acción integral, el error continuará siendo integrado,
incrementando aún más su valor. Esto significa que el término integral puede volverse muy
grande. Para evitar esta situación se inserta el bloque de saturación, el cual implementa el
concepto de la saturación integral del controlador. Éste está ubicado al final del controlador
para evitar entregar a la etapa siguiente cualquier valor superior al máximo de operación,
pero por otro lado, este bloque también permite una operatividad permanente del
controlador, al evitar la saturación de la variable controlada.
Por otra parte, el bloque de retardo colocado en el bloque integrador tiene la función de
implementar la integral, ya que tenemos que recordar que este algoritmo entrega a su salida
en incrementos.
Las constantes ld , N , L juegan un papel importante en el comportamiento del
controlador, pudiendo llevar el sistema a un error próximo a zero o por lo contrario llevarlo
a la inestabilidad. La sintonización de estas variables no es una tarea fácil, por suerte hay
herramientas para averiguar sus valores. Por ejemplo la técnica Ziegler-Nichols.
Proyecto final de carrera
Página 34
Memoria descriptiva
1.4.6 Lazo de Control
La suma de todos los bloques anteriores forman el modelo completo de la planta y su
realimentación para el lazo de control.
Figura 30. Modelo simulink lazo de control
Si procedemos a la simulación del conjunto global a una consigna concreta de 500
rpm observamos los siguientes resultados:
Figura 31. Salida modelo completo con control PI con PWM 50 Hz
Proyecto final de carrera
Página 35
Memoria descriptiva
Este resultado se ha obtenido mediante un control proporcional e integral. Se puede
observar que el resultado obtenido es muy próximo a la consigna al sistema. Existe un
pequeño rizado que puede venir provocado por la frecuencia de la excitación PWM como
ya se explico en su momento en el apartado nº 1.4.4, que en este caso es de 50 Hz
Si en cambio aumentamos la frecuencia de conmutación de la excitación a 100 Hz
veremos que el rizado se reduce sensiblemente, y sin haber cambiado las constantes del
controlador.
Figura 32. Salida modelo completo con control PI con PWM 100 Hz
1.4.7 Sintonización Controlador PID
Para sintonizar el controlador de la planta podemos utilizar el método diferentes
métodos. [2]
Método basado en la respuesta temporal a un escalón en lazo abierto (ZieglerNichols).
Es un método grafico. Consiste en encontrar la respuesta del sistema en lazo
abierto a un escalón. Seguidamente tendremos que observar el resultado y
extraer los siguientes parámetros
Proyecto final de carrera
Página 36
Memoria descriptiva
A través de la siguiente tabla podremos encontrar las diferentes constantes
del controlador.
Controlador
P
PI
PID
Kp
Ti Td
1/a
0.9/a 3·L
1.2/a 2·L L/2
Método de la respuesta en lazo cerrado
Este método consiste en conocer la ubicación de los polos del sistema
utilizando el criterio de Nyquist, e ubicar estos justo encima del eje
imaginario, encontrando entonces los parámetros lm (ultima ganancia) y m
(útimo periodo)
Para encontrar estos parámetros podemos proceder de la siguiente manera:
1.
Eliminar las acciones integral y derivativa.
2. Aumentar k lentamente hasta que la planta empiece a oscilar.
En el momento que se produzca la oscilación obtendremos
los parámetros lm L m
A través de la siguiente tabla podremos encontrar los parámetros del
controlador:
Controlador
P
PI
PID
Proyecto final de carrera
Kp
0,5·lm
0,4·lm
0,6·lm
Ti
0,8·
0,5·
Td
m
m
0,125·
m
Página 37
Memoria descriptiva
Método Empírico
Procederemos de la siguiente manera:
1. Eliminar del controlador las acciones integral y derivativa (Td=0,
Ti=inf)
2. Aumentar K hasta que encontremos una respuesta de la planta
satisfactoria, sin tener en cuenta el error estacionario.
3. Aumentar K y con la acción derivativa intentar recuperar la
respuesta obtenida en el apartado anterior..
4. Repetir el anterior apartado hasta que k sea lo más grande
posible.
5. Agregar la acción integral para eliminar el error en estado
estacionario.
Proyecto final de carrera
Página 38
Memoria descriptiva
1.4.8 Errores del sistema
1.4.8.1 PWM
Para poder obtener el menor rizado de velocidad en el eje del motor deberemos tener
una excitación PWM con una regulación muy precisa. Este tipo de regulación implicará
tener unos incrementos de E y E
muy pequeños, en consecuencia necesitaremos un tic
del sistema adecuado para poder generar estos tiempos [1].
Figura 33. Onda PWM
En la figura anterior se puede observar el efecto que provocaría el incremento de un
tic en la velocidad del motor. Claramente, si el tiempo E es más grande el motor
alcanzara una mayor velocidad, y su media se verá modificada.
Para examinar mejor este efecto, volveremos al estudio realizado en el apartado
1.4.4. donde extrajimos las siguientes formulas:
N
1
1
7
7 M
M
*
27
28
donde:
7
M
Proyecto final de carrera
Q
Q
=
b
ST
@ =
b
ST
29
30
Página 39
Memoria descriptiva
Las cuales nos ayudaran a través de una simulación de Matlab a ver la influencia de
un tic en el tiempo de E .
dc=[0:0.01:1];
Taus=30e-3;
Taub=500e-3;
T=10e-3;
A=exp(dc*(T/Taus));
B=exp((1-dc)*(T/Taub));
Wfin=1640;
for n=1:101,
W1(n)=Wfin*((1-A(n))/(1-A(n)*B(n)));
W2(n)=B(n)*W1(n);
end
T=10e-3;
tic=0.5e-3;
x=(dc+(tic/T));
for m=1:101,
if x(m)>1
x(m)=1;
end
end
A=exp(x*(T/Taus));
B=exp((1-x)*(T/Taub));
Wfin=1640;
for n=1:101,
W3(n)=Wfin*((1-A(n))/(1-A(n)*B(n)));
W4(n)=B(n)*W3(n);
end
figure(1)
hold on;
plot(dc,(W4-W2));
xlabel('Ciclo de Trabajo')
ylabel('incremento (rpm)')
hold off;
Código 1. Simulación incremento velocidad respecto dc
En la siguiente figura podemos observar la influencia que tiene un incremento del
ciclo de trabajo de dc de un solo tic frente a la velocidad del motor, pasando a ser un ciclo
de trabajo de dc a n9 o Ep9/ .
Proyecto final de carrera
Página 40
Memoria descriptiva
Figura 34. Incremento de velocidad respecto el punto de trabajo y el tic
Dependiendo de la base de tiempo del sistema un solo incremento de E en una
magnitud de tic, para un ciclo de trabajo pequeño causa un incremento de velocidad muy
grande. Este efecto provoca una mala regulación de la velocidad y la posición del eje del
motor. El objetivo deseado es la mayor resolución de la excitación PWM posible, para
poder evitar estos saltos de velocidad en un solo incremento. Cuanto más pequeño sea el
tic más resolución obtenemos y en consecuencia tenemos una mejor regulación.
Figura 34.1. Incremento de velocidad a causa del incremento de un tic
La frecuencia de la excitación PWM viene dada por:
1
1
q Ep9
la cual es la inversa de n veces la base de tiempos tic de nuestro sistema. Si
disminuimos el valor de tic, aumentaremos el valor de n, consiguiendo una mejor
resolución al tener un tiempo base tic más pequeño.
Proyecto final de carrera
Página 41
Memoria descriptiva
En cuanto al error producido por un incremento de tic en el tiempo de E , cuanto
más pequeño sea éste, menor desviación tendremos en el punto de trabajo dc de la
excitación PWM.
Por ejemplo, con una frecuencia de excitación del PWM de 50 Hz y un ciclo de
trabajo de 0,05 el error causado por un tic de 50μ es de:
n9
∆Ep9
0,05
50μ
203
0,0525 F rs
|0,05
0,0525|
0,05
5%
En cambio, para un tic de 10μ , el error causado por el incremento del tic es de:
n9
1.5
∆Ep9
0,05
10μ
203
0,0505 F rs
|0,05
0,0505|
0,05
1%
Emulador de la Planta
A causa del coste de los equipos del conjunto Motor-Encoder se dispone de unas
unidades limitadas. Con el fin de facilitar al alumno la realización de las prácticas en los
laboratorios o bien en horas no lectivas se decidió crear un emulador para substituir el
equipo principal.
Este emulador es una placa electrónica de medidas reducidas que puede conectarse al
puerto paralelo del PC, de forma que es substituible un equipo por otro sin realizar ningún
cambio.
Este nuevo equipo debe generar las señales Ay B del encoder según la tensión media
que aplique la excitación PWM, y la señal de petición de interrupción al puerto paralelo.
Para facilitar el diseño se utilizó el modelo de primer orden de respuesta lineal, sin
contemplar el efecto del PWM y el diodo volante del puente de alimentación [1].
En la siguiente figura mostramos la base del diseño para la creación de este
emulador. En la fase inicial se decidió que el emulador no diferenciaría entre el giro de
derechas e izquierdas. De aquí que los pines 2 y 3 de salida del PWM desde el PC se les
aplica la función OR.
Proyecto final de carrera
Página 42
Memoria descriptiva
Figura 35. Conversión señal PWM a frecuencia a través C.I 555
La siguiente etapa se instalo para realizar una separación entre el integrador y las
señales de entrada.
Para dotar al emulador de unas características similares a las del motor se ha
insertado un integrador con la misma constante de tiempo que tenía el sistema original,
dotando de esta manera una dinámica parecida al conjunto del motor-encoder.
La tensión media del integrador responderá a la siguiente ecuación:
N
1
e
N
nE
N
v
E
31
y su evolución temporal seguiría a una forma de onda parecida a la siguiente figura.
(Orden y magnitud no comparables, sólo como ejemplo)
Figura 36. Señal de salida integrador
Proyecto final de carrera
Página 43
Memoria descriptiva
Si fijamos que la función de transferencia del sistema de primer orden del motor es:
115
0.03
1
,
32
y la función de transferencia del integrador:
,N
w
1
1
/
1
1
0.033
1
1
33
Donde las dos funciones de transferencia anteriores deberían de ser parecidas para
poder tener una dinámica comparable.
La etapa de la fuente de corriente proporcionara la ganancia necesaria para equiparar
las dos funciones de transferencia, donde esta suministrara una corriente de colector con
valor:
=
x
y
z
yz
x
0.7
3300
N
34
El espejo de corriente se encargara de cargar el condensador de 33 nF con la misma
intensidad que el colector de la fuente de corriente. Entonces la corriente de este dependerá
de la tensión de salida del integrador, siendo:
=
1
e p= nE
w
1
w
=
E
35
Si consideramos que la corriente del condensador sigue una evolución con pendiente
constante, tendremos que la tensión entre bornes será:
Figura 37. Tensión en bornes del condensador
Proyecto final de carrera
Página 44
Memoria descriptiva
Donde nombraremos la amplitud de la señal entre 1/3 y 2/3 de Vcc con el nombre de
A, que corresponderá a:
7
=
36
w
donde despejaremos:
w
7
37
=
y en consecuencia la frecuencia de la señal:
=
"
38
7 w
donde substituiremos el valor de = :
"
1
7 w
N
z
yz
1
7 w
N
v
E
z
yz
39
En este punto, si configuramos el oscilador C.I. 555 en formato de multivibrador
estable obtendremos una señal de salida de este con una frecuencia de "
23.7 4{,
siendo w 33 q|, z 3,3 2, yz 0.7 y == > N v 5
Realizando este circuito hemos creado un oscilador controlado por tensión, que en
consecuencia relaciona el ciclo de trabajo del PWM con la frecuencia de salida del
oscilador.
El motor real considerado para la realización del emulador tiene una velocidad
máxima de 1725 rpm, el cual tiene unido el encoder relativo con una resolución de 200
pulsos/revolución. Esta unión de elementos, a su máxima velocidad de funcionamiento
según una tensión de alimentación de 15 V, nos supondría una frecuencia de " 200
AC0
5750 4{.
D0
Esta frecuencia es del orden de 4 veces menor que la frecuencia del oscilador
C.I.555, por lo que tendremos que dividir esa frecuencia para conseguir una frecuencia
parecida al conjunto del motor-encoder.
Proyecto final de carrera
Página 45
Memoria descriptiva
Para dividir esta frecuencia se han instalado unos biestables tipo D en cascada, los
cuales dividirán la señal por 4 y generaran la señal en cuadratura parecida a la del encoder.
También se tiene que incluir la detención de flancos para provocar la señal de la solicitud
de interrupción IRQ-7, donde utilizaremos los circuitos estudiados en la figura nº 9.
Figura 38. Circuito Emulador
En la siguiente figura podemos observar la evolución de las señales que genera el
emulador. Vemos la señal producida por el oscilador C.I.555 y cómo el biestable A1
reduce su frecuencia a la mitad, luego los biestable A2 y A3 generan la señal en
cuadratura, y los detectores de flanco generan la señal para la petición de la interrupción
IRQ-7.
Proyecto final de carrera
Página 46
Memoria descriptiva
Figura 39. Relación de la evolución de las señales Emulador
1.6
Software de simulación de la Planta
La premisa del software realizado en el presente proyecto es la de simular el
“comportamiento” de la planta descrita en el anterior apartado, facilitando la tarea de
desarrollo de las practicas de la asignatura en horas no lectivas.
Figura 40. Concepto Simulador
Proyecto final de carrera
Página 47
Memoria descriptiva
No es objeto del proyecto realizar una simulación del modelo matemático del
conjunto motor dc + encoder, sino el crear unas librerías que simulen el comportamiento
de la velocidad del motor respecto la alimentación recibida por la etapa de la excitación
PWM, obteniendo como resultado las correspondientes señales del encoder.
El camino fijado para la realización del presente simulador ha sido el componer un
código que interactúe el mínimo posible con el alumno que realiza las prácticas de la
asignatura, de modo que éste no desvíe su atención en la utilización/comprensión del
código del simulador.
De esta manera, el éxito del simulador será proporcional a su sencillez de utilización,
pretendiendo confundir lo mínimo posible al alumno. Desafortunadamente, para el flujo de
información entre el código creado del emulador y el código del alumno habrá una serie de
restricciones, las cuales serán descritas más adelante.
1.6.1 Descripción del Software
Siguiendo por el camino de la sencillez, el código del simulador se ha implementado
en ficheros de cabecera *.h para facilitar su uso. Estas librerías están formadas por un
código fuente en forma de macros, siguiendo al estilo de las librerías facilitadas en la
asignatura para la realización de las prácticas. Este hecho ha condicionado el desarrollo del
simulador.
También se ha tenido en cuenta los diferentes modos de programación que se pueden
utilizar en el entorno de Turbo C. Si el alumno ha realizado todo el código fuente
directamente en el archivo main ( ), o por lo contrario, si el alumno ha escogido realizar un
proyecto, separando en archivos el código fuente.
Para facilitar la realización del código del simulador se han atacado los diferentes
problemas en dos librerías diferentes, desglosando en cada archivo las macros pertinentes.
Formando 2 librerías nombradas Q5.h y k1.h donde en ellas reside tanto el código del
simulador, como las funciones que debe utilizar el alumno para emplearlo.
Figura 41. Concepto Simulador
Proyecto final de carrera
Página 48
Memoria descriptiva
El archivo nombrado Q5.h aborda el problema del modo de programación utilizado
por el alumno (archivo main ( ) o proyecto) y el modo de funcionamiento del simulador
(ON – OFF)
Por otra parte el archivo k1.h aborta al completo el código fuente para la simulación
del comportamiento de la planta, incluyendo las macros de comunicación con el puerto
paralelo “virtualizado”.
Debemos recordar que la razón de este proyecto reside en el problema de la
accesibilidad del puerto paralelo. Por este motivo hemos “virtualizado” los registros del
puerto paralelo ubicados en Base+0, Base+1 y Base+2 a un array de las mismas
dimensiones, un array de 8+8+8 bits, como mostramos en la figura nº 42.
Figura 42. Virtualización del Puerto Paralelo
1.6.2 Librería Q5.h
La librería Q5.h tiene principalmente dos propósitos, solucionar:
-
“Modo” de programación
-
“Modo” de operación
Dependiendo de la opción escogida por el alumno en la realización del código fuente
de las prácticas, tenemos que amoldar nuestro código para que él pueda compilar el código
sin ningún error. En el entorno de Turbo C tenemos las siguientes opciones para realizar un
archivo ejecutable:
-
Realizar todo el código fuente en un archivo con extensión *.c el cual
contendrá la función main ( ).
-
Realizar un proyecto con diferentes archivos con extensión *.c y otro
archivo con extensión *.c que contenga la función main ( )
Proyecto final de carrera
Página 49
Memoria descriptiva
Para poder escoger entre las diferentes opciones de programación sin que fuera de
difícil aplicación para el alumno, se creó la definición project. Mediante la inserción de
esta definición, el alumno escoge de una manera simple y fácil el modo que utilizará.
La única diferencia entre las dos opciones es la declaración de las variables a utilizar
por nuestro emulador. En el caso que el alumno sólo programara en un único archivo, este
problema no existiría, pero si el alumno realizaba un proyecto, podría llegar el caso que
durante la compilación del código surgiera un error por no tener las variables del emulador
declaradas en diferentes archivos de código fuente.
Inicio
NO
Project
defined?
SI
Archivo Principal
Archivo Secundario
Definir Variable
como local
Definir Variable
como externa
Fin
Figura 43. Modo de Programación
#ifndef project
hard_motor virtual_motor;
//Declaració variable simulador
void interrupt (*old_handler_prn2)();
/* mantiene el manejador original */
#else
extern hard_motor virtual_motor;
#endif
Código 1. Parte código librería Q5.h
Mediante el código descrito anteriormente solucionamos el problema de la
compilación. En el caso de haber utilizado un proyecto, se inserta la declaración #define
Project, de esta manera, automáticamente se declara el puntero de la estructura de datos de
forma externa en los diferentes archivos del proyecto realizado.
Proyecto final de carrera
Página 50
Memoria descriptiva
En el anexo B se detalla las operaciones a realizar en cada caso, para facilitar el uso
al alumno.
El otro problema abordado en esta librería es la funcionalidad del emulador. La
premisa más importante de este proyecto era la de crear un simulador de la planta, donde
fuese extremadamente sencillo cambiar de modo real a modo simulación.
Al inicio de las prácticas de la asignatura se hace entrega del tutorial de prácticas. En
este tutorial se incluye una librería llamada “printer.h”, donde residen las macros
necesarias para comunicarse con el puerto paralelo del PC, y así poder leer y escribir en el
puerto. El problema surge cuando estamos utilizando un ordenador portátil, ya que
normalmente no tienen accesible el puerto paralelo. De esta manera, nuestro simulador
tendría que tener total compatibilidad con las macros existentes, de tal forma que a la hora
de compilar no se produjeran errores.
Mediante la definición de una etiqueta pudimos reparar en la solución al problema.
En el caso de que el alumno defina la etiqueta #define simula, nuestro código substituirá la
librería “printer.h” por la nuestra llamada “k1.h”, equipada con las mismas declaraciones
de macros para no provocar errores en la compilación. En caso contrario, si esta etiqueta
no se ha definido, nuestro código incluirá la librería “printer.h” y sustituirá las
declaraciones de las funciones utilizadas por el simulador por macros vacías, de esta forma
no se tendrá que borrar la línea de dentro del código del alumno cada vez que pase de
modo simulación a modo real.
Inicio
SI
Simula
defined?
NO
Simulador RUN
Simulador OFF
Adjuntamos librería
simulación
Adjuntamos Liberia
printer.h
Fin
Figura 44. ON-OFF simulador
Proyecto final de carrera
Página 51
Memoria descriptiva
#ifdef simula
#include "k1.h"
#else
#include "printer.h"
#define ini_datos_sim() { }
#define sim_motor() { }
#define restaura() { }
#endif
Código 2. Parte código librería Q5.h
Por otra parte, en esta librería se define la estructura de datos hard_motor donde se
declaran las variables necesarias para realizar la simulación.
typedef struct
{
long count;
//interval abans d'executar la
funci¢ associada (micro seg)
long recarga;
//valor de recarrega
double tic;
//interval entre
interrupcions(microseg)
int direction; //direccion motor;izquierdaderecha-0
int vel_max_motor;
//velocidad maxima nominal
motor
int puntos_encoder;
//n§ ventanas del encorder
por vuelta
int index;
//n§ de ventana en que se
encuentra el encoder (0-3)
unsigned int registroPRN[3]; //variable port
virtualitzat
}hard_motor;
Código 3. Parte código librería Q5.h
Donde la variable count será el valor resultante del cálculo definido por las variables
de programa del ciclo de trabajo y la velocidad máxima del motor, interviniendo también
la base de tiempos del sistema (tic)..
La variable recarga es el valor de recarga de la variable count una vez consumida.
La variable tic hará referencia al tic que seleccione el alumno durante la ejecución de su
programa, siendo la base de tiempo mínima para poder realizar los correspondientes
timers.
La variable direction nos indicará el sentido del motor, a izquierdas o a derechas. La
variable vel_max_motor tal y como indica su nombre, es el valor de velocidad máxima
según la tensión de alimentación de nuestra fuente.
La variable index nos indica en qué ventana del encoder se encuentra el sistema en
un momento dado. Se ha definido el orden de las ventanas en la siguiente figura:
Proyecto final de carrera
Página 52
Memoria descriptiva
Figura 45. Orden ventanas encoder
La variable registroPRN es un array de 3 posiciones de 8 bits donde almacenaremos
la información que dirigíamos antes a los registros del puerto paralelo.
registroPRN + 0:
Bit 7
Pin 9
Bit 6
Pin 8
Bit 5
Pin 7
Bit 4
Pin 6
Bit 3
Pin 5
Bit 2
Pin 4
Bit 1
Pin 3
Bit 0
Pin 2
Bit 5
Pin 12
Bit 4
Pin 13
Bit 3
Pin 15
Bit 2
-
Bit 1
-
Bit 0
-
Bit 5
-
Bit 4
IRQ
Bit 3
/Pin 17
Bit 2
Pin 16
Bit 1
/Pin 14
Bit 0
/Pin 1
registroPRN + 1:
Bit 7
/Pin 11
Bit 6
Pin 10
registroPRN + 2:
Bit 7
-
Bit 6
-
Tabla 3. Registros del puerto paralelo
Habiendo sustituido los tres registros del puerto paralelo mapeados en memoria por
esta variable con igual tamaño.
Proyecto final de carrera
Página 53
Memoria descriptiva
1.6.3 Librería k1.h
En esta librería residen todas las funciones necesarias para poder simular el
comportamiento de la planta estudiada, emulando la velocidad respecto la tensión de
alimentación versus el ciclo de trabajo del PWM y las señales ocasionadas al respecto por
el encoder.
En la cabecera de la librería se declaran unas etiquetas que nos ayudaran a
simplificar las operaciones de escritura del código.
Seguidamente tenemos la macro llamada ini_datos_sim( ), que tal y como da a
entender su nombre inicializa las variables de la estructura que contiene los datos
necesarios para el funcionamiento del sistema.
Como puntos más importantes a destacar de la macro es la puesta a cero de la
variable donde almacenaremos los datos que iban antes a los registros del puerto paralelo y
la sustitución del puntero a la función asociada a la interrupción software del puerto
paralelo, pudiendo provocar de esta manera interrupciones de este a nuestra voluntad.
Consiguiendo de esta manera cerrar el lazo entre la información del “encoder” y el control
de la velocidad del motor.
#define ini_datos_sim() {
*(virtual_motor.registroPRN+0)=0x00;
*(virtual_motor.registroPRN+1)=0x00;
*(virtual_motor.registroPRN+2)=0x00;
virtual_motor.index=0;
old_handler_prn2=_dos_getvect(0x17);
_dos_setvect(0x17,cuadrat);
virtual_motor.vel_max_motor=25;
virtual_motor.puntos_encoder=800;
virtual_motor.count=0;
virtual_motor.recarga=0;
virtual_motor.direction=d_derecha;
}
Código 4. Macro ini_datos_sim. Parte código librería k1.h
La base de tiempos utilizada a través de un temporizador del chip 8253 la cual se ha
denominado como tic, que utiliza el alumno para realizar otros timers, no es una base de
tiempo fijada.
Cada alumno puede escoger una base de tiempos tic de forma sensata y dentro de
unos rangos. Este hecho condiciona totalmente nuestra forma de operar. A causa de no
tener fijada una base de tiempo concreta, nuestro sistema tiene que ser flexible al cambio
ésta.
Proyecto final de carrera
Página 54
Memoria descriptiva
En relación a este hecho, tenemos la macro llamada cal_time_irq7( ).
#define cal_time_irq7() {
float x;
x=virtual_motor.vel_max_motor*inf_pwm.dc;
if (x<0)
{
x=x*(-1);
virtual_motor.direction=d_izquierda;
}
else
{virtual_motor.direction=d_derecha; }
if (x==0) x=1;
x=x*virtual_motor.puntos_encoder;
x=(1/x)*1000000;
x=x/h_timer.tic;
virtual_motor.count=x+0.5;
virtual_motor.recarga=virtual_motor.count;
}
Código 5. Macro cal_time_irq7. Parte código librería k1.h
Esta macro calcula el tiempo que asociaremos al timer count de la estructura de datos
del tipo hard_motor. Este tiempo se determina a través de la velocidad máxima del motor
(según su alimentación), el ciclo de trabajo determinado por el controlador PID, la
resolución del encoder y finalmente por el tic escogido por el usuario.
1
qº nQ pqEQ\\~]99p}qQ € 5
Ep9
9}~qE
qº nQ pqEQ\\~]99p}qQ € 5
Q•
áv
R s
38
n9 ]~qE} _Qq9}nQ\
39
El timer count nos determinará el tiempo entre interrupciones asociadas a la función
de interrupción software del IRQ 7.
Dependiendo de la velocidad que tenga el motor, este tiempo será mayor o menor. Es
importante tener un tic pequeño para conseguir una buena resolución, ya que si por lo
contrario tenemos un tic grande, como cabe esperar el rizado de velocidad será elevado.
qº nQ pqE. € 5
9}~qE
1
53066
35 10@D
3980
0.53
Proyecto final de carrera
\Q„ 1 3pq
800 ]~•. Qq9}nQ\
3pq 60
† ‡íqp3} 1 9}~qE
†
1
35 10@D
53066
p\…
Q8
28571
40
p\…
Q8
41
Página 55
Memoria descriptiva
Como se observa en las formulas anteriores, para la máxima velocidad del motor,
con un tic de 35µs obtendríamos un error muy grande en la velocidad final de éste, a causa
de tener un tic inapropiado para tener la resolución necesaria para esa velocidad.
Figura 46. Tiempo entre interrupciones IRQ07
La base principal del emulador es la macro llamada sim_motor( ). Esta origina las
señales A y B que generaría el encoder, según el número de ventana ya especificado más
arriba, provocando posteriormente la interrupción
interrupción del puerto paralelo, cerrando de esta
manera el lazo de control. En la figura 47 mostramos el diagrama de ejecución.
ejecución
La llamada a esta
sta macro debe insertarse al final de la rutina de atención a la
interrupción IRQ0 realizada por el alumno, un lugar sencillo y que no entorpecerá la
ejecución de su código.
Si observamos el diagrama de bloques de la página anterior, la variable clave es la
variable count,, la cual determina en qué
qu instante debe provocarse una interrupción en IRQIRQ
07. Una vez transcurrido el tiempo, la macro recalcula el tiempo por si se ha variado el
ciclo de trabajo. Dependiendo de la dirección establecida y de la ventana actual (señales
encoder), se generaránn las señales A y B correctamente al igual como haría el encoder, y se
provocará una llamada a la interrupción software asociada a IRQ-07.
IRQ
De esta forma, cerramos el lazo de control sin modificar considerablemente el código
c
realizado por el alumno. La clave reside en cambiar el vector que apunta a la interrupción
hardware del puerto paralelo por el vector que apunta a la interrupción software de este.
En modo de utilización normal con el hardware activo, el alumno coloca el puntero
de la función a asociada a la interrupción el puerto paralelo en el vector 0x0F de la tabla de
vectores de interrupciones. El cambio el software de simulación coloca el puntero
punte de la
función asociada a la interrupción IRQ-7
IRQ 7 en el vector 0x17 de la tabla de vectores de
interrupción, que corresponde a la interrupción software del puerto paralelo.
Proyecto final de carrera
Página 56
Memoria descriptiva
Rutina atención IRQ0
{…}
Llamada Rutina
Sim_motor ( )
Count=0
?
Count -NO
SI
Calcula tiempo
Tiner según dc
PWM
Dirección ?
IZQUIERDA
DERECHA
Genera señales
AyB
Genera señales
AyB
Provoca soft
interrupt puerto
paralelo
Provoca soft
interrupt puerto
paralelo
Fin rutina
atención IRQ-0
Figura 47. Diagrama ejecución IRQ 0
Proyecto final de carrera
Página 57
Memoria descriptiva
El código fuente de la macro es el siguiente:
#define sim_motor() {
if (!virtual_motor.count)
{
cal_time_irq7();
virtual_motor.count=virtual_motor.recarga;
if (virtual_motor.direction==d_derecha) {
switch(virtual_motor.index){
case 0:
*(virtual_motor.registroPRN+1)=0x20;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 1:
*(virtual_motor.registroPRN+1)=0x30;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 2:
*(virtual_motor.registroPRN+1)=0x10;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 3:
*(virtual_motor.registroPRN+1)=0x00;
geninterrupt(0x17);
virtual_motor.index=0;
break;}
}
if (virtual_motor.direction==d_izquierda) {
switch(virtual_motor.index){
case 0:
*(virtual_motor.registroPRN+1)=0x10;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 1:
*(virtual_motor.registroPRN+1)=0x30;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 2:
*(virtual_motor.registroPRN+1)=0x20;
geninterrupt(0x17);
virtual_motor.index++;
break;
case 3:
*(virtual_motor.registroPRN+1)=0x00;
geninterrupt(0x17);
virtual_motor.index=0;
break;}
} }
else
{ virtual_motor.count--;}
}
Código 6. Macro sim_motor. Parte código librería k1.h
Proyecto final de carrera
Página 58
Memoria descriptiva
A partir de este punto, tenemos que cambiar las macros que trabajaban con los
registros del puerto paralelo (datos de partida en las practicas de la asignatura) por macros
con igual identidad, pero cambiando su interior para operar con nuestra variable llamada
registroPRN de la estructura de datos virtual_motor.
Por ejemplo la macro llamada pulse_on_a( ) la cual tenía por función alimentar la
parte derecha del puente de transistores. La metodología de la operación a realizar es la
misma que la original, pero sobre la variable registroPRN en vez del registro del puerto
paralelo.
#define pulse_on_a()
{
*(PRN_BASE)=((*(PRN_BASE)&PULSEOFF_B)|PULSEON_A);
virtual_motor.direction=d_derecha;
}
Código 7. Macro pulse_on_a. Parte código librería k1.h
Por otra parte, al contrario que la operación anterior, se anula la alimentación a la
parte derecha del puente de transistores.
#define pulse_off_a()
{
*(PRN_BASE)=(*(PRN_BASE))&PULSEOFF_A;
virtual_motor.direction=d_stop;
}
Código 8. Macro pulse_off_a. Parte código librería k1.h
Es importante transformar todas las macros existentes en el archivo printer.h
suministrado al principio de las practicas, porque durante el cambio de modo entre sistema
real y sistema en emulador no surjan errores de compilación por no tener declaradas las
macros.
El resto de macros serán comentadas en el anexo B, donde estará especificado todo
el código del emulador.
Proyecto final de carrera
Página 59
Memoria descriptiva
1.7
Modo de Uso
Para poder utilizar este simulador y sus librerías existen unas restricciones de uso.
A causa del flujo necesario de información entre el código que realice el alumno y las
librerías del simulador, es necesario definir las variables nombradas de la siguiente forma:
-
El puntero a la estructura HARD_TIMER debe llamarse h_timer
-
El puntero a la estructura SOFT_TIMER debe llamarse s_timer
-
El puntero a la estructura PWM debe llamarse inf_pwm
-
El puntero a la estructura PID debe llamarse inf_pid
Figura 48. Restricciones de Uso
De no ser así, el programa de compilación retornará diferentes errores por variables
no declaradas y no se generará el fichero ejecutable.
Proyecto final de carrera
Página 60
Memoria descriptiva
En el caso que el alumno haya decidido realizar la programación de las prácticas en
un solo archivo con extensión *.c, donde residan todas sus funciones y macros, deberá
realizar estos ajustes en su código de programa para poder utilizar el simulador.
-
Insertar definición: # define simula
-
Incluir librería: #include “q5.h” , NO incluir la librería “Printer.h”
-
Insertar llamada a función de inicialización simulador: ini_datos_sim ( )
(Esta debe ubicarse después de las pertinentes inicializaciones de todas
las variables del programa realizado por el alumno)
-
Insertar llamada a función de restauración: Restaura_sistema ( )
(Debe ubicarse al final del programa)
-
Insertar llamada a función para ejecutar el simulador: sim_motor ( )
(Esta debe ubicarse al final de la rutina de atención IRQ 0 realizada por el
alumno)
Figura 49. Cambios en el código
Estos ajustes sólo se deberán realizar la primera vez que utilice el simulador. Las
macros insertadas son inertes en caso que el simulador esté en modo de no operación.
Proyecto final de carrera
Página 61
Memoria descriptiva
En el caso que el alumno haya decidido realizar la programación con la modalidad
de proyecto, teniendo un archivo base *.c con la correspondiente función main() más
archivos complementarios con extensión *.c donde residan funciones varias deberá seguir
esta guía de ejemplo para realizar los cambios necesarios en el código para utilizar el
simulador.
Ejemplo de proyecto formado por: Archivo Main.c + Archivo Timer.c +
Archivo Ini_IRQ.c + Archivo PID.c + Archivo PWM.c
Cambios a realizar en archivo Main.c:
-
Insertar definición: # define simula
Incluir librería: #include “q5.h”
Insertar llamada a función de inicialización simulador: ini_datos_sim ( )
(Esta debe ubicarse después de las pertinentes inicializaciones de todas las variables del
programa realizado por el alumno)
Insertar llamada a función de restauración: Restaura_sistema ( )
(Debe ubicarse al final del programa)
-
Cambios a realizar en archivo Timer.c:
(Este archivo contiene la rutina de atención a la interrupción IRQ 0)
-
Insertar definición: # define simula
Insertar definición: # define Project
Incluir librería: #include “q5.h”
Insertar llamada a función para ejecutar el simulador: sim_motor ( )
(Esta debe ubicarse al final de la rutina de atención IRQ 0 realizada por el alumno)
Cambios a realizar en archivo Ini_IRQ.c:
-
Insertar definición: # define simula
Insertar definición: # define Project
Incluir librería: #include “q5.h”
Cambios a realizar en archivo PID.c:
-
Insertar definición: # define simula
Insertar definición: # define Project
Incluir librería: #include “q5.h”
Cambios a realizar en archivo PWM.c:
-
Insertar definición: # define simula
Insertar definición: # define Project
Incluir librería: #include “q5.h”
Proyecto final de carrera
Página 62
Memoria descriptiva
Estos ajustes sólo se deberán realizar la primera vez que utilice el simulador. Las
macros insertadas son inertes en caso que el simulador este en modo OFF.
Una vez realizados los cambios, para poder utilizar el simulador se debe operar de la
siguiente manera:
-
Simulador OFF -> // #define simula
(Comentar definición para no ser compilada)
-
Simulador ON -> #define simula
(La definición debe ser compilada)
Figura 51. ON/OFF simulador
Proyecto final de carrera
Página 63
Memoria descriptiva
En el anexo C del presente proyecto adjuntamos todo el código de la práctica nº 4 de
la asignatura Informática Industrial II para utilizar este simulador.
Proyecto final de carrera
Página 64
2
Anexo A
Proyecto final de carrera
Página 65
Anexo B
2.1
El motor de corriente continua
En el siguiente anexo describiremos brevemente el motor de corriente continua y
sus principales características de manera que el alumnado pueda comprender más
fácilmente los parámetros que identifican a este tipo de motores. [2]
El motor de corriente continua de imanes permanentes se compone principalmente
de dos partes, una parte exterior llamada estator, la cual da soporte mecánico al aparato, y
un núcleo llamado rotor, el cual es la parte móvil del motor.
El estator está formado por unos imanes permanentes de altas prestaciones de polos
opuestos, enfrentado entre ellos, los cuales provocan unas líneas de fuerza entre N-S de los
respectivos imanes.
En cambio el rotor está formado por un núcleo de hierro devanado con unas espiras
de conductor eléctrico, generalmente cobre, que son alimentadas a través de dos escobillas.
El movimiento del rotor viene ocasionado por la acción derivada de la repulsión y
atracción entre polos magnéticos. Creando campos constantes convenientemente
orientados en estator y rotor, se origina un par de fuerzas que obliga a que el rotor gire
buscando la posición de equilibrio.
Figura 52. Motor de corriente continua.
A la hora de interpretar una hoja de características de un motor de corriente
continua es conveniente conocer el significado de cada parámetro, para ello, describiremos
los más significativos.
Potencia nominal asignada:
Esta cifra representa la máxima potencia de salida cuando se opera dentro del rango
de trabajo recomendado.
Unidad de medida internacional expresada en watios (w)
Tensión nominal:
Proyecto final de carrera
Página 66
Anexo B
Es el voltaje al cual se han medido los datos nominales (velocidad en vacío, par de
arranque, corriente de arranque, máx. potencia de salida, máx. rendimiento).
Se ha escogido este dato para no exceder la máxima velocidad recomendada en
vacío. Por supuesto, el uso del motor no está limitado a este voltaje. Para alcanzar
la potencia nominal asignada se permiten voltajes de trabajo más elevados.
La velocidad en vacío, par de arranque y corriente de arranque dependen
directamente del voltaje aplicado.
Unidad de medida internacional expresada en voltios (V)
Velocidad en vacío:
Es la velocidad a la que gira el motor cuando no tiene carga y se le aplica la tensión
nominal. En la práctica, esta velocidad es proporcional al voltaje aplicado
(constante de velocidad).
Unidad de medida internacional expresada en rpm.
Par de arranque:
Es el par teórico a la tensión nominal y con el rotor bloqueado. El par de arranque
aumenta proporcionalmente con el voltaje aplicado. El valor dado corresponde a
una temperatura del rotor de 25°C. El par de arranque está relacionado con la
corriente de arranque. Su conexión es la constante de par km
Simbolizado con las siglas Mh y la unidad de medida internacional esta expresada
en Nm (newton metro)
Relación velocidad/par:
La relación velocidad/par da información de las prestaciones del motor y se
representa por la línea (o curva) velocidad-par. Cuanto más pequeño es este valor,
más potente es el motor, y consecuentemente menor es la variación de la velocidad
del motor con los cambios en la carga.
La constante velocidad/par depende de las prestaciones del circuito magnético
(ej: imán permanente), de las dimensiones del bobinado (longitud, diámetro,
número de espiras) y de la resistencia del bobinado. En la práctica, la constante
velocidad/par se puede obtener dividiendo la velocidad en vacío entre el par de
arranque.
Simbolizado con las siglas n/M y la unidad de medida internacional esta expresada
en rpm/Nm
Corriente en vacío:
Proyecto final de carrera
Página 67
Anexo B
Esta es la corriente que consume el motor sin carga, alimentado a su tensión
nominal.
Simbolizado con las siglas Io y la unidad de medida internacional esta expresada en
Amperios (A)
Corriente de arranque:
Es el cociente entre el voltaje nominal U y la resistencia en bornes Ra. Esta
corriente es proporcional al par de arranque. Ambas magnitudes están
relacionadas mediante la constante de par km.
Simbolizado con las siglas IA y la unidad de medida internacional esta expresada
en Amperios (A)
Resistencia en bornes:
Es la resistencia en los terminales a 25°C y determina la corriente de arranque a un
voltaje dado. La resistencia entre bornes es un valor compuesto por la resistencia
del bobinado, la resistencia de la escobilla y la resistencia de contacto entre la
escobilla y el colector.
Simbolizado con las siglas Ra y la unidad de medida internacional esta expresada
en Ohmios (Ω)
Velocidad máxima permitida:
Esta velocidad representa el límite superior del rango recomendado de
funcionamiento y no debería ser excedida durante el funcionamiento normal del
motor. La velocidad está limitada principalmente por la conmutación. Si el
motor gira a velocidades superiores pueden aparecer problemas de
conmutación, que a su vez pueden llevar a reducir la vida útil del motor.
Esto es debido a los siguientes factores:
1.- Aumento del desgaste mecánico debido a que la distancia recorrida por el
colector es mayor.
2.-Aumento del desgaste por electro-erosión debido a la vibración de las escobillas
y la formación de chispas.
Simbolizado con las siglas nmax y la unidad de medida internacional esta expresada
en rpm
Máxima corriente en servicio continuo:
Proyecto final de carrera
Página 68
Anexo B
Si el motor funciona continuamente con esta corriente y a 25°C de
temperatura ambiente, se calentará hasta alcanzar la máxima temperatura del
bobinado. Se asume que el motor no tiene refrigeración adicional, sin otras
piezas que hagan de radiador de calor y aumenten este valor sustancialmente. Un
aumento de la temperatura ambiente reduce la corriente máxima en continuo. Los
bobinados con baja resistencia óhmica admiten corrientes más altas que los
bobinados con alta resistencia. En motores con bobinados de resistencia baja, la
máxima corriente en continuo puede estar limitada por las escobillas y no por el
bobinado. La máxima corriente en continuo es equivalente al máx. par permanente.
Están relacionados por la constante de par km.
Simbolizado con las siglas Imax y la unidad de medida internacional esta expresada
en Amperios (A)
Máxima par en servicio continuo:
Es el par que se puede entregar continuamente, o de media, alcanzando en el
bobinado la máxima temperatura admisible, basado en una temperatura ambiente de
25°C. A temperatura ambiente más alta, este valor se reduce. El par máximo limita
el rango recomendado de funcionamiento.
Simbolizado con las siglas Mcont y la unidad de medida internacional esta
expresada en Nm (newton metro)
Máxima potencia de salida:
Es la máxima potencia teórica a 25°C de temperatura del rotor. La máxima potencia
se alcanza en la mitad del par de arranque y la mitad de la velocidad en vacío. Los
límites permitidos (máx. corriente en continuo y máx. velocidad permitida)
frecuentemente están por debajo de este nivel.
Simbolizado con las siglas Pmax y la unidad de medida internacional esta
expresada en watios (w)
Constante de par:
Representa la relación del par generado y la corriente aplicada. La constante de par
transforma valores de par en valores de corriente y viceversa.
En la práctica, km se determina por el par de arranque MH y la corriente de
arranque Ia. En el cálculo teórico, han de tomarse en consideración las
dimensiones del bobinado (longitud l, diámetro 2r, número de espiras w), así como
la fuerza del campo magnético.
La constante de par está relacionada con la constante de velocidad kn ya que ambas
están determinadas por los mismos parámetros.
Simbolizado con las siglas km y la unidad de medida internacional esta expresada
en Nm/A (Newton metro por Amperio)
Proyecto final de carrera
Página 69
Anexo B
Constante de velocidad:
Muestra la velocidad específica por voltio del voltaje aplicado sin contar las
pérdidas por fricción.
En la práctica, kn se determina por el voltaje nominal U y la velocidad en vacío n0.
En el cálculo teórico, deben tenerse en cuenta las dimensiones del bobinado
(longitud, diámetro, número de espiras, w), así como la fuerza del campo
magnético B0. La constante de velocidad está relacionada con la constante de par
km porque éstas se determinan por los mismos parámetros.
Simbolizado con las siglas kn y la unidad de medida internacional esta expresada
en rpm/V (revoluciones por minuto por Voltio)
Inercia del motor:
Es el momento de inercia del rotor, basado en el eje de giro. Determina la constante
de tiempo mecánica del motor.
Simbolizado con las siglas JR y la unidad de medida internacional esta expresada
en km² (kilos por metro cuadrado)
Constante de tiempo mecánica:
Es el tiempo que tarda el rotor en acelerar desde parado hasta el 63% de la
velocidad en vacío. Este valor se calcula desestimando las fricciones, carga e
inercia de la carga.
Transcurridas 4 veces este valor (τ) el rotor habrá alcanzado más del 99% de la
velocidad en vacío.
La constante mecánica de tiempo se puede calcular con la inercia del rotor y el
gradiente velocidad-par
Simbolizado con las siglas τm y la unidad de medida internacional esta expresada
en milisegundos (ms)
Inductancia entre bornes:
Es la inductancia del bobinado estacionario y medida con una onda senoidal de 1
kHz.
Simbolizado con las siglas La y la unidad de medida internacional esta expresada
en Henrios (H)
Constante eléctrica:
Proyecto final de carrera
Página 70
Anexo B
La inductancia entre bornes y la resistencia entre bornes determina la constante
eléctrica de tiempo del motor. Este parámetro se refiere al tiempo requerido
por la corriente para aumentar o disminuir.
Típicamente, la constante eléctrica de tiempo es de 100 a 1.000 veces más pequeña
que la constante mecánica de tiempo. Los cambios de corriente ocurren
instantáneamente comparados con los cambios en velocidad.
Un fenómeno a destacar cuando la corriente puede reaccionar de manera tan rápida,
es el caso de los motores que son alimentados mediante PWM. En algunas
ocasiones se puede producir un rizo de corriente no deseado que sobrecalienta al
motor. En estos casos, puede que sea necesario aumentar la frecuencia del
PWM o conectar una inductancia adicional.
Simbolizado con las siglas ke
Proyecto final de carrera
Página 71
3
Anexo B
Proyecto final de carrera
Página 72
Anexo B
3.1
Código Librería Q5.h
#ifdef simula
#include "k1.h"
#else
#include "printer.h"
#define ini_datos_sim() { }
#define sim_motor() { }
#endif
//Mode de funcionament simulador ON//ON-OFF segons si es declara la
//definicio
typedef struct
{
long count;
//Estructura de dades necesaries pel
//funcionament del simular soft
//Interval de Temps abans d'executar
//la funci¢ associada (micro seg)
long recarga;
//Valor de recarrega
double tic;
//Interval entre
//interrupcions(microseg)
int direction;
//Direccio motor;Izquierda-Derecha-0
int vel_max_motor;
//Velocidad maxima nominal motor
int puntos_encoder;
//num. Finestres del encorder per
//volta
int index;
//nº de finestra en que es troba en
//un instant el encoder (0-3)
unsigned int registroPRN[3]; //Variable port paral·lel
//virtualitzat
}hard_motor;
#ifndef project
hard_motor virtual_motor;
void interrupt
(*old_handler_prn2)();
#else
extern hard_motor virtual_motor;
#endif
Proyecto final de carrera
//En cas de projecte declara la
//variable con a interna o externa
//del arxiu en questió
//Mante el punter original
Página 73
Anexo B
3.2
Código Librería K1.h
#define PRN_IRQ_MASK
0x10
#define PULSEON_A
#define PULSEOFF_A
0x01
~PULSEON_A
#define PULSEON_B
#define PULSEOFF_B
0x02
~PULSEON_B
#define INI_PRN
0xFF
#define VCC_ON
0xFC
#define VCC_OFF
#define MASK
0x00
0x80
#define CUADRAT_MASK
0x30
#define d_derecha
#define d_izquierda
#define d_stop
1
2
0
//Mascara interrupcions pin 10
//DB-25
//ON de pin 2 DB25
//Pulsos de control en pin 2
//DB-25
//On de pin 3 DB25
//Pulsos de control en pin 3
//DB-25
//11111111 Inicializacio del
//port_base+ 1 de prn
//Pines 2 y 3 a zero i pins
//4...9 a ú DB25
//Pines 2...9 a zero DB25
//Mascara per confirmacio de
//int
//Mascara bits 4 y 5 de
//cuadratura (pins 12 y 13)
//Direccio motor a dreta
//Direcció motor Esquerra
//Motor Parat
#define PRN_BASE
virtual_motor.registroPRN
//Etiqueta
//registre
#define PRN_VERIFI (virtual_motor.registroPRN+1)
//Etiqueta
//registre
#define PRN_IRQ
(virtual_motor.registroPRN+2)
//Etiqueta
//registre
a la direccio del
soft virtual PRN
a la direccio del
soft virtual PRN+1
a direcció del
soft virtual PRN+2
//---------------------------------------------------------------------// ini_datos_sim:
//
Inicialitza datos principals del similador
//---------------------------------------------------------------------#define ini_datos_sim() {
\
*(virtual_motor.registroPRN+1)=0x00;
\
virtual_motor.index=0;
\
old_handler_prn2=_dos_getvect(0x17);
\
_dos_setvect(0x17,cuadrat);
\
virtual_motor.vel_max_motor=25;
\
virtual_motor.puntos_encoder=800;
\
virtual_motor.count=0;
\
virtual_motor.recarga=0;
\
virtual_motor.direction=d_derecha;
\
}
Proyecto final de carrera
Página 74
Anexo B
//----------------------------------------------------------------------//cal_time_irq7:
//
Funcio que determina el temps entre les interrupcions
//
irq7 realitzades pel encoder virtual en funcio del
//
dc del pwm, tic hardware timer i vel. max. del motor cc
//----------------------------------------------------------------------#define cal_time_irq7() {
\
float x;
\
x=virtual_motor.vel_max_motor*inf_pwm.dc; \
if (x<0)
\
{
\
x=x*(-1);
\
virtual_motor.direction=d_izquierda; \
}
\
else
\
{virtual_motor.direction=d_derecha; } \
if (x==0) x=1;
\
x=x*virtual_motor.puntos_encoder;
\
x=(1/x)*1000000;
\
x=x/h_timer.tic;
\
virtual_motor.count=x+0.5;
\
virtual_motor.recarga=virtual_motor.count;\
}
//----------------------------------------------------------------------//sim_motor:
//
Funcio que simula les senyales A i B del encorder en el port
//
PRN virtual i genera la interrupcio irq7
//----------------------------------------------------------------------#define sim_motor() {
\
\
if (!virtual_motor.count)
\
{
\
cal_time_irq7();
\
virtual_motor.count=virtual_motor.recarga;
\
if (virtual_motor.direction==d_derecha)
\
{
\
kk1++;
\
switch(virtual_motor.index)
\
{
\
case 0:
\
*(virtual_motor.registroPRN+1)=0x20;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 1:
\
*(virtual_motor.registroPRN+1)=0x30;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 2:
\
*(virtual_motor.registroPRN+1)=0x10;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 3:
\
*(virtual_motor.registroPRN+1)=0x00;
\
geninterrupt(0x17);
\
virtual_motor.index=0;
\
break;
\
}
\
Proyecto final de carrera
Página 75
Anexo B
}
\
if (virtual_motor.direction==d_izquierda)
\
{
\
switch(virtual_motor.index)
\
{
\
case 0:
\
*(virtual_motor.registroPRN+1)=0x10;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 1:
\
*(virtual_motor.registroPRN+1)=0x30;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 2:
\
*(virtual_motor.registroPRN+1)=0x20;
\
geninterrupt(0x17);
\
virtual_motor.index++;
\
break;
\
case 3:
\
*(virtual_motor.registroPRN+1)=0x00;
\
geninterrupt(0x17);
\
virtual_motor.index=0;
\
break;
\
}
\
}
\
}
\
else
\
{
\
virtual_motor.count--;
\
}
\
}
//------------------------------------------------------------------//pulse_on_a() pin 2 DB-25 a '1' i pin 3 DB-25 a 'O'
//------------------------------------------------------------------#define pulse_on_a()
\
{
\
*(PRN_BASE)=((*(PRN_BASE)&PULSEOFF_B)|PULSEON_A);
\
virtual_motor.direction=d_derecha;
\
}
/*-------------------------------------------------pulse_off_a() pin 2 DB-25 a 'O'
----------------------------------------------------*/
#define pulse_off_a() {
*(PRN_BASE)=(*(PRN_BASE))&PULSEOFF_A;
virtual_motor.direction=d_stop;
}
/*--------------------------------------------------pulse_on_b() pin 3 DB-25 a '1' i pin 2 DB-25 a 'O'
---------------------------------------------------*/
#define pulse_on_b() {
*(PRN_BASE)=(((*(PRN_BASE))&PULSEOFF_A)|PULSEON_B);
virtual_motor.direction=d_izquierda;
}
Proyecto final de carrera
\
\
\
\
\
\
Página 76
Anexo B
/*--------------------------------------------------pulse_off_b() pin 3 DB-25 a 'O'
----------------------------------------------------*/
#define pulse_off_b() {
\
*(PRN_BASE)=((*(PRN_BASE))&PULSEOFF_B);
\
virtual_motor.direction=d_stop;
\
}
/*--------------------------------------------------ini_prn() pins 2 i 3 a zero (PWM), pins 4 i 5 a ú (cuadrat), pins 6 a 9 a
ú (VCC=ON)
-----------------------------------------------------*/
#define ini_prn() {
\
*(PRN_BASE+1)=INI_PRN;
\
}
/*----------------------------------------------------verifi() pin 11 -BUSY -DB-25. Utilitzat com a comfirmació de int
------------------------------------------------------*/
//#define verifi() (inportb(PRN_VERIFI)&MASK)
#define verifi() {}
/*----------------------------------------------------cuadrat_leer() pin 12 Data_5 i pin 13 Data_4,info de cuadratura
-------------------------------------------------------*/
#define cuadrat_leer() ((((*(PRN_BASE+1))&CUADRAT_MASK)>>4))
/*-------------------------------------------------------vcc_on() pins 2 i 3 a zero i pins 4...9 a ú DB 25
---------------------------------------------------------*/
//# #define vcc_on() {
\
*(PRN_BASE)=VCC_ON;
\
}
/*-------------------------------------------------------vcc_off() pines 2...9 a zero DB 25
---------------------------------------------------------*/
#define vcc_off() {
\
*(PRN_BASE)=VCC_OFF;
\
}
/*-------------------------------------------------------en_i_prn(): Es valida la interrupcio de prn pin 10 DB-25
---------------------------------------------------------*/
#define en_i_prn() {
\
*(PRN_IRQ)=((*(PRN_BASE))|PRN_IRQ_MASK);
\
}
/*-------------------------------------------------------dis_i_prn(): Inibeix interrupcions des de prn
---------------------------------------------------------*/
#define dis_i_prn() {
\
*(PRN_IRQ)=((*(PRN_BASE))&~PRN_IRQ_MASK);
\
}
Proyecto final de carrera
Página 77
4
Anexo C
Proyecto final de carrera
Página 78
Anexo C
4.1
Librería 8259.h
/*--------------------------------------------------------------------FILE:
8259.h -declaraciones y macros para el chip 8259
MACROS:
mask_prn_off() - desactiva m scara IRQ7
mask_prn_on() - activa m scara IRQ7
mask_prn()
- devuelve el estado de la m scara IRQ7
eoi_ns()
- fin de interrupci¢n no espec¡fica
eoi_prn()
- fin de interrupci¢n espec¡fica IRQ7
eoi_timer()
- fin de interrupci¢n espec¡ficaIRQO
-----------------------------------------------------------------------*/
#define BASE_8259
0x20
/* direcci¢n base */
#define PORT_EOI
(BASE_8259+0)
/* puerto para EOI */
#define PORT_MASK
(BASE_8295+1)
/* puerto para mascaras */
#define VECT_BASE
#define VECT_TIMER
#define VECT_PRN
8
(VECT_BASE+O)
(VECT_BASE+7)
/* vector base */
/* vector del timer 8253 */
/* vector de impresora */
#define MASK_TIMER
#define MASK_PRN
0x0l
0x80
/* M scara para timer */
/* M scara para impresora */
#define EOI_TIMER
0x60
/* F¡n de interrup. para timer */
#define EOI_PRN
0x67
/* F¡n de interrup. para
inpresora */
#define EOI_NS
0x20
/* F¡n deinterrup. no espec¡fica
/*-------------------------------------------------------mask_prn_off() desactiva la m scara permitiendo las interrupciones.
---------------------------------------------------------*/
#define mask_prn_off()
(outportb(BASE_8259+1,(inportb(BASE_8259+1)&~MASK_PRN)))
/*--------------------------------------------------------mask_prn_on() activa la m scara bloqueando las interrupciones.
----------------------------------------------------------*/
#define mask_prn_on()
(outportb(BASE_8259+1,(inportb(BASE_8259+1)|MASK_PRN))
/*---------------------------------------------------------mask_prn() devuelve 1 si m scara activa y O en caso contrario
-------------------------------------------------------------*/
#define mask_prn() (((inportb(BASE_8259+1>>7)&0x0l)
/*-----------------------------------------------------------eoi_ns() fin de interrupci¢n no espec¡fica
-------------------------------------------------------------*/
#define eoi_ns() (outportb(BASE_8259,EOI_NS))
/*-----------------------------------------------------------eoi_prn() fin de interrupci¢n espec¡fica para port paralelo (IRQ7)
--------------------------------------------------------------*/
#define eoi_prn() (outportb(BASE_8259,EOI_PRN))
/*------------------------------------------------------------eoi_timer() fin de interrupci¢n espec¡fica el timer (IRQO)
----------------------------------------------------------------*/
#define eoi_timer() (outportb(BASE_8259,EOI_TIMER))
Proyecto final de carrera
Página 79
Anexo C
4.2
Librería Ini_IRQ.h
#define CR 0x0D
/* c¢digo ASCII de tecla retorno
de carro */
#define PULSOS_ENCODER 200
/*pulsos por revoluci¢n*/
#define
#define
#define
#define
/* estados de cuadratura*/
ESTADO_00
ESTADO_01
ESTADO_10
ESTADO_11
0x00
0x01
0x02
0x03
#define DIRECTA 1
direcci¢n */
#define INVERSA 0
/* valores de los flags de
/* declaraci¢n de tipos derivados
--------------------------------*/
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
/* prototipos de funciones
---------------------------------*/
double
get_posicion(void);
void
inc_p(void),
dec_p(void),
reset_prn(void),
ini_cuadrat(void);
void interrupt cuadrat(_CPPARGS);
Proyecto final de carrera
/* retorna la posici¢n */
/* incrementa la cuenta de pulsos
/* decrementa de cuenta de pulsos
/* restaura condiciones iniciales
/*de prn */
/* inicilizaci¢n */
Página 80
Anexo C
4.3
Librería PID.h
/*----------------------------------------------------------------------FILE: pid.h -declaracions per al pid.c
-----------------------------------------------------------------------*/
typedef struct
{
double
kp,
Ti,
Td,
consigna,
error_1,
error_2,
t_sample;
}struct_PID;
//----------------------------------------------------------------------//
cap‡alera
//----------------------------------------------------------------------double obtenir_voltes(void);
int variables_pid(void);
int control(void);
int funcio_velocitat(void);
Proyecto final de carrera
Página 81
Anexo C
4.4
Librería Printer.h
/*-------------------------------------------------------FILE:
printer.h
NOTAS:
Se definen las macros para el acceso al port paralelo
Las macros de ataque al puente excluyen la posibilidad
de que ambas ramas puedan activarse simultaneamente
MACROS:
pulse_on_a()
pulse_off_a()
pulse_on_b()
pulse_off_b()
ini_prn()
verifi()
cuadrat_leer()
en_i_prn()
dis_i_prn()
vcc_on()
vcc_off()
activa la rama 'a' del puente
desactiva la rama 'a' del puente
activa la rama 'b' del puente
desactiva la rama 'b' del puente
inicializa el port prn
verifica que la interrupci¢n no es ruido
lee estado de cuadratura para posicion
habilita las interrupciones (IRQ7)
deshabilita las interrupciones (IRQ7)
entrega tensi¢n al exterior a trav‚s del port
anula tensi¢n exterior
FUNCIONES:
printer()
devuelve la direcci¢n base asociada al port
---------------------------------------------------------------------*/
#include <dos.h>
#define PRN_BASE
0X378
#define PRN_VERIFI
PRN_BASE+1
#define PRN_IRQ
PRN_BASE+2
#define PRN_IRQ_MASK
0x10
DB-25 */
#define PULSEON_A
0x01
#define PULSEOFF_A
~PULSEON_A
25 */
#define PULSEON_B
0x02
#define PULSEOFF_B
~PULSEON_B
25 */
#define INI_PRN
0xFF
port_base+ 1 de prn */
#define VCC_ON
0xFC
4...9 a uno DB25 */
#define VCC_OFF
0x00
#define MASK
0x80
int */
#define CUADRAT_MASK
0x30
cuadratura (pines 12 y 13)*/
#define N_PRN
0x00410
impresora */
#define D_PRN
0x00408
base de PRN */
Proyecto final de carrera
/* mascara interrupciones pin 10
/* puesta a uno de pin 2 DB25 */
/* pulsos de control en pin 2 DB/* puesta a uno de pin 3 DB25 */
/* pulsos de control en pin 3 DB/* 11111111 inicializaci¢n del
/* pines 2 y 3 a cero y pines
/* pines 2...9 a cero DB25 */
/* m scara para confirmaci¢n de
/* m scara para bits 4 y 5 de
/* direcci¢n de nø de ports de
/* indirecci¢n para direcci¢n
Página 82
Anexo C
/*------------------------------------------------pulse_on_a() pin 2 DB-25 a '1' y pin 3 DB-25 a 'O'
-------------------------------------------------*/
#define pulse_on_a()
(outportb(PRN_BASE,((inportb(PRN_BASE)&PULSEOFF_B)|PULSEON_A)))
/*-------------------------------------------------pulse_off_a() pin 2 DB-25 a 'O'
----------------------------------------------------*/
#define pulse_off_a() (outportb(PRN_BASE,(inportb(PRN_BASE)&PULSEOFF_A)))
/*--------------------------------------------------pulse_on_b() pin 3 DB-25 a '1' y pin 2 DB-25 a 'O'
---------------------------------------------------*/
#define pulse_on_b()
(outportb(PRN_BASE,((inportb(PRN_BASE)&PULSEOFF_A)|PULSEON_B)))
/*--------------------------------------------------pulse_off_b() pin 3 DB-25 a 'O'
----------------------------------------------------*/
#define pulse_off_b() (outportb(PRN_BASE,(inportb(PRN_BASE)&PULSEOFF_B)))
/*--------------------------------------------------ini_prn() pines 2 y 3 a cero (PWM), pines 4 y 5 a uno (cuadrat), pines 6
a 9 a uno (VCC=ON)
-----------------------------------------------------*/
#define ini_prn() (outport(PRN_BASE+l,INI_PRN))
/*----------------------------------------------------verifi() pin 11 -BUSY -DB-25. Usado como confirmaci¢n de int
NOTA: el valor le¡do es el inverso del real
------------------------------------------------------*/
#define verifi() (inportb(PRN_VERIFI)&MASK)
/*----------------------------------------------------cuadrat_leer() pin 12 Data_5 y pin 13 Data_4,info de cuadratura
-------------------------------------------------------*/
#define cuadrat_leer() ((inportb(PRN_BASE+1)&CUADRAT_MASK)>>4)
/*-------------------------------------------------------vcc_on() pines 2 y 3 a cero y pines 4...9 a uno DB 25
---------------------------------------------------------*/
#define vcc_on() (outportb(PRN_BASE,VCC_ON))
/*-------------------------------------------------------vcc_off() pines 2...9 a cero DB 25
---------------------------------------------------------*/
#define vcc_off() (outportb(PRN_BASE,VCC_OFF))
/*-------------------------------------------------------en_i_prn() se valida la interrupci¢n de prn pin 10 DB-25
---------------------------------------------------------*/
#define en_i_prn() (outport(PRN_IRQ,(inportb(PRN_IRQ)|PRN_IRQ_MASK)))
/*-------------------------------------------------------dis_i_prn() inhibe interrupciones desde prn
---------------------------------------------------------*/
#define dis_i_prn() (outportb(PRN_IRQ,(inportb(PRN_IRQ)&~PRN_IRQ_MASK)))
/*------------------------------------------------------printer() -devuel ve la direcci¢n base asociada al port pasado
-------------------------------------------------------------*/
int printer(int);
Proyecto final de carrera
Página 83
Anexo C
4.5
Librería PWM.h
typedef struct
{
double dc;
long
T,
ton,
toff,
gir,
abans;
}struct_PWM;
#define
#define
#define
#define
dreta
esquerra
ON
OFF
0
// referida a excitacio PWM
//
//
//
//
//
//
cicle de treball
periode (us)
temps de on (us)
temps de off (us)
dreta/esquerra
ve de on o de off
1
0
1
//--------------------------------------------------------------//Cap‡aleres de pwm.c
//--------------------------------------------------------------int frequency(double freq);
int duty_cycle(double dc);
int pwm(void);
4.6
Librería Timer.h
/*--------------------------------------------------------------FILE:
TIMER.h -declaracions per al TIMER.c
----------------------------------------------------------------*/
#ifdef _cplusplus
*/
#define _CPPARGS...
#else
#define _CPPARGS
#endif
/* consideracions sobre el tipus de compilador
/* declaraci¢ de tipus derivats
--------------------------------*/
typedef struct
{
int
port,
//@ del port base
timer;
//un de tres
double clock,
//frecuencia del cristall d'exitaci¢
tic;
//interval entre
//interrupcions(microseg)
}hard_timer;
Proyecto final de carrera
Página 84
Anexo C
typedef struct
{
long count,
//interval abans d'executar la funci¢
//associada (micro seg)
//valor de recarrega
//incremental/decremental
//funcio associada a count
recarga;
int incremental;
int (*fun)(void);
}soft_timer;
#define base_8253
#define tmr0
#define clock_timer
0x40
0
1193180
//@ base del timer 8253
//timer 0 del 8253
//freq encia d'oscilúlacio del
//cristall
//posicio del vector a la taula
//vectoritzada
#define vector_irq_timer 0x08
#define base_8259
#define EOI_NS
0x20
0x20
//final d'irq no especifica
/*-------------------------------------Cap‡aleres de les funcions de timer.c
----------------------------------------*/
int captura_valors(double *valors);
//adquireix dades del teclat
int captura_tecla_teclat(char taula[30]);
int set_timer(int timer,double interval);//estableix el contingut d'un
//soft_timer concret
int ini_timers(double *valors);
//inicia tots els soft_timers
void ini_struct_hard_timer(int interval);//estableix el contingut de
//l'estructura del hard_timer
void canvi_vector_irq(void);
//posa el nou vector a la taula
//vectoritzada
int trans_interval_tic(void);
//transforma microseg a tics
int ini_8253(void);
//inicialitza el timer 8253
void restaura_sistema(void);
//restaura tot el sistema
double get_timer(int timer);
//captura el contingut d'un
//soft_timer
void interrupt irq_timer(void);
Proyecto final de carrera
//rutina d'atencio a la
//interrupcio
Página 85
Anexo C
4.7
Librería Main.c
/*---------------------------------------------------------------FILE: inf4.c
ALGORISME DE CONTROL
NOTES: FORMAT D'ENTRADA: Nom del programa + espai + base de temps del
8253
en microsegons
-----------------------------------------------------------------*/
//PFC
#define simula
#include "q5.h"
//PFC
#include
#include
#include
#include
"timer.h"
"pwm.h"
"ini_irq.h"
"pid.h"
#include
#include
#include
#include
#include
<stdio.h>
<conio.h>
<stdlib.h>
<dos.h>
<math.h>
int analisi_arguments(int argc,char **argv);
int inicialitzacio(int tmp,double *valors);
//Comprova els arguments
//d'entrada
//inicialitza tot el
//sistema
int control_tecla(int tecla);
void presentacio (void);
//PFC
extern
extern
extern
//PFC
extern
hard_timer h_timer;
double k1,k2,k3;
double error_0;
soft_timer s_timer[3];
//variable declarada a
timer.c
extern struct_PWM inf_pwm;
long int irq_8253=0;
//compta les irq's
provocades pel 8253
extern int error_irq;
extern
extern
extern
extern
long cuenta_p;
long irq_prn;
double velocitat;
struct_PID inf_pid;
Proyecto final de carrera
Página 86
Anexo C
//------------------------------------------------main(int argc,char **argv)
{
int tmp;
double valors[3];
char tecla;
tmp=analisi_arguments(argc,argv); //comprova els arguments d'entrada
clrscr();
if (inicialitzacio(tmp,valors)) return (1);
//PFC
ini_datos_sim();
//PFC
while(tecla!=27)
{
if(error_irq) return(1);
presentacio();
tecla=getch();
}
restaura_sistema();
return(0);
//restaura l'antic apuntador de la t.vectoritzada,
//el port paralel i para el motor
// retorn sense error
}
//------------------------------------------------------------//analisi_arguments: Analitza els arguments introduits
//
per teclat, realitza l'arrodoniment
//
//------------------------------------------------------------int analisi_arguments(int argc,char **argv)
{
float tmp;
char *missatge="\nError en la cadena d'entrada al programa. \n\nFORMAT:
Nom del programa + espai + base de temps\nen micro segons";
tmp=0.0;
if ((argc==1)|(argc>2))
//Si l'argument de crida al programa
no es 2
{
//donarem error d'entrada dades
printf("%s\n",missatge);
abort();
}
if(argc==2)
{
tmp=atof(argv[1]);
//tractem argument introduit
tmp=tmp+0.5;
//arodonim
}
if ((tmp<5.0)|(tmp>200.0))
//si base temps no adecuada
{
//abortem programa
printf("\n\nBase de temps no adecuada\n\n");
abort();
}
return (tmp);
}
Proyecto final de carrera
Página 87
Anexo C
int inicialitzacio(int tmp,double *valors)
{
ini_struct_hard_timer(tmp);
if(captura_valors(valors))
//adquireix dades del teclat
{
printf("\n\nError al entrar les dades");
return(1);
}
if (ini_timers(valors))
//inicia els soft_timers, si es
//retorna 1 hi ha
{
//error i finalitzal'execucio
printf("\n\nError en les dades dels timers");
return(1);
}
pulse_off_b();
pulse_off_a();
if (frequency((1/valors[1])*1e3))
{
printf("Error de dades en Frequencia PWM");
return(1);
}
inf_pid.t_sample=valors[0];
if(variables_pid()) return(1);
inf_pid.error_1=0.0;
inf_pid.error_2=0.0;
ini_cuadrat();
canvi_vector_irq();
if (ini_8253())
//POSAR DINS LA FUNCIO variables_pid
//posa el nou apuntador a la nostra
//rutina de servei dins la taula
//vectoritzada
//programa el 8253 per a que comenci
//a comptar
{
printf("\n\nError en la inicialitzaci¢ del hard timer");
return(1);
}
return (0);
}
void presentacio (void)
{
double graus;
int voltes;
clrscr();
while (!kbhit())
{
graus=get_posicion();
//posici¢ absoluta de l'eix
voltes=(int)(graus/360.0);
// voltes donades
gotoxy(7,2);
printf("---------------------- Control de potencia -------------");
gotoxy(7,3);
|");
printf("|
gotoxy(7,4);
Proyecto final de carrera
Página 88
Anexo C
printf("--------------------------------------------------------");
gotoxy(15,5);
printf("DC:%3.0lf % ",(inf_pwm.dc)*100);
gotoxy(15,6);
printf("Ton: %ld microsegons
",inf_pwm.ton);
gotoxy(15,7);
printf("Toff: %ld microsegons
",inf_pwm.toff);
gotoxy(15,8);
if(inf_pwm.gir==1)
");
printf("Sentit de gir: DRETA
else
printf("Sentit de gir: ESQUERRA ");
gotoxy(15,9);
printf("Velocitat real motor: %4.2lf rpm
",velocitat);
gotoxy(15,10);
printf("Pulsos del encoder: %ld polsos
",cuenta_p);
gotoxy(15,11);
printf("errors encoder: %d
",error);
gotoxy(15,12);
printf("posici¢ absoluta de l'eix: %8.2f§C
", graus);
gotoxy(15,13);
printf("posici¢ relativa de l'eix: %8.2f¦C ", graus-voltes*360.0);
gotoxy(15,14);
printf("n§ de voltes:%5d ", voltes);
//PFC
gotoxy(7,15);
printf("------------------------- Proves -----------------------");
gotoxy(7,16);
printf("|
|");
gotoxy(7,17);
printf("--------------------------------------------------------");
gotoxy(7,18);
printf("k1 PID:%5f ", k1);
gotoxy(7,19);
printf("k2 PID:%5f ", k2);
gotoxy(7,20);
printf("N§ Tics:%5d ", virtual_motor.recarga);
gotoxy(7,21);
printf("Direcci¢:%5d ", virtual_motor.direction);
gotoxy(7,22);
printf("Index finestra:%5d ", virtual_motor.index);
gotoxy(30,18);
printf("Consigna velocitat:%5f ",inf_pid.consigna);
gotoxy(30,19);
printf("Velocitat Real:%5f ",velocitat);
gotoxy(30,20);
printf("PWM:%5f ",inf_pwm.dc);
gotoxy(30,21);
printf("Error 0:%5f ",error_0);
gotoxy(30,22);
printf("Error 1:%5f ",inf_pid.error_1);
gotoxy(30,23);
printf("increment PWM:%4f",k1*error_0+k2*inf_pid.error_1);
//PFC
}
}
Proyecto final de carrera
Página 89
Anexo C
4.8
Librería Ini_IRQ.c
/*------------------------------------------------------------------FILE: ini_irq.c -medida de posici¢n del eje de un motor partiendo
de dos se¤ales en cuadratura propocionadas
por un encoder relativo
autor: Jacob Pie
NOTAS:
La posici¢n se determina contando el n£mero de pulsos que
se detectan en una misma direcci¢n.
La direcci¢n se determina a partir de la secuencia
de pulsos desfasados 90 grados que proporciona el encoder
relativo.
--------------------------------------------------------------------*/
//PFC
#define simula
#define project
#include "q5.h"
//PFC
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
#include "ini_irq.h"
//#include "printer.h"
#include "8259.h"
/*------------datos privados
-------------*/
long cuenta_p;
static int
direccion,
estado_old,
flag_inver,
prn_base;
//conta el nø de interrupcions
//del encoder
//sentido de giro del motor
//estado previo de la entrada
//de cuadratura
//flag de direcci¢n inversa
//direcci¢n base del puerto
//paralelo
int error=0;
void interrupt (*old_handler_prn)();
//mantiene el manejador
//original
double grados;
//posici¢n absoluta del eje del
//motor en grados sexagesimales
//vueltas dadas
int vueltas;
long irq_prn=0;
Proyecto final de carrera
Página 90
Anexo C
/*-------------------------------------------------------------------cuadrat() -Rutina de servicio a la interrupcion de cuadratura
NOTA:
Esta funcion es llamada a cada flanco (ascendente
y descendente) de cada una de las dos se¤ales
en cuadratura.
El sentido de giro es funcion de la secuencia
de unos y ceros provinientes de las dos se¤ales
desfasadas 90§ dadas por el encoder. Asi, la
accion a tomar depender del estado actual y
del anterior.
---------------------------------------------------------------------*/
void interrupt cuadrat(_CPPARGS)
{
int estado_curso;
//estado actual de cuadratura
estado_curso=cuadrat_leer();
if(estado_old!=estado_curso)
{
switch(estado_old)
//lectura de info de cuadratura
//analisis de secuencia de pulsos
//del encoder
{
case ESTADO_00:
if( estado_curso==ESTADO_01)
dec_p();
/* retroceso */
else if(estado_curso==ESTADO_10)
inc_p();
/* avance */
else
error++;
/* error */
break;
case ESTADO_01:
if(estado_curso==ESTADO_11)
dec_p();
else if(estado_curso==ESTADO_00)
inc_p();
else
error++;
break;
case ESTADO_11:
if(estado_curso==ESTADO_10)
dec_p();
else if(estado_curso==ESTADO_01)
inc_p();
else
error++;
break;
case ESTADO_10:
if(estado_curso==ESTADO_00)
dec_p();
else if(estado_curso==ESTADO_11)
inc_p();
else
error++;
break;
}
Proyecto final de carrera
Página 91
Anexo C
estado_old=estado_curso;
}
irq_prn++;
eoi_ns();
//el estado actual pasa a ser
//el anterior ahora
//fin de interrupci¢n no
//espec¡fica
}
/*--------------------------------------------------------------------inc_p() -incrementar cuenta_p
incrementa el nø de inten-upciones acumuladas
----------------------------------------------------------------------*/
static void inc_p(void)
{
++cuenta_p;
//incrementamos la cuenta de
//pulsos
if(direccion==INVERSA)
//si la direcci¢n anterior era
//inversa==>cambio de direcci¢n
{
direccion=DIRECTA;
//direcci¢n actual
flag_inver=1;
//indicaci¢n de cambio en
//direcci¢n
}
}
/*-------------------------------------------------------------------dec_p -decrementar cuenta_p
decrementa el nø de interrupciones acumuladas
---------------------------------------------------------------------*/
static void dec_p(void)
{
//decrementamos la cuenta de
--cuenta_p;
//pulsos
if( direccion==DIRECTA)
//si la direcci¢n anterior era
//directa==>cambio de direcci¢n
{
direccion=INVERSA;
//direcci¢n actual
flag_inver=1;
//indicaci¢n de cambio de
//direcci¢n
}
}
/*--------------------------------------------------------------------ini_cuadrat -inicializaci¢n
----------------------------------------------------------------------*/
void ini_cuadrat(void)
{
cuenta_p=0;
//puesta a cero
error=0;
flag_inver=0;
direccion=DIRECTA;
estado_old=cuadrat_leer();
//arbitrariamente elegida
//estado actual
old_handler_prn=getvect(VECT_PRN); //guadamos vector original
setvect(VECT_PRN,cuadrat);
//establecemos nueva rutina de
//atenci¢n
Proyecto final de carrera
Página 92
Anexo C
en_i_prn();
mask_prn_off();
}
//activamos interrup. IRQ7 (prn)
//permitimos int de prn en 8259
/*----------------------------------------------------------------------reset_prn()
Restaura el vector original y desactiva interrup.
----------------------------------------------------------------------*/
void reset_prn(void)
{
dis_i_prn();
//inhibe interrupciones de pin
//10
setvect(VECT_PRN,old_handler_prn);
//restaura vector original
pulse_off_a();
//pin 2 DB-25 a cero
pulse_off_b();
//pin 3 DB-25 a cero
}
/*---------------------------------------------------------------------cuadrat_getp()
retorna de la posici¢n en grados sexagesimales
-----------------------------------------------------------------------*/
double get_posicion(void)
{
long cuenta;
//copia de cuenta_p
disable();
//comienzo regi¢n cr¡tica
cuenta=cuenta_p;
//info de posici¢n en pulsos
enable();
//fin de regi¢n cr¡tica
return(cuenta*360.0/(PULSOS_ENCODER*4.0)); //conversi¢n a grados
//cent¡grados
}
Proyecto final de carrera
Página 93
Anexo C
4.9
Librería PID.c
//----------------------------------------------------------------------FILE: pid.c
Implementacio de les funcions relatives al control PID
//---------------------------------------------------------------------#include
#include
#include
#include
#include
<stdio.h>
<conio.h>
<stdlib.h>
<dos.h>
<math.h>
#include
#include
#include
#include
"timer.h"
"pwm.h"
"ini_irq.h"
"pid.h"
double velocitat=0.0;
extern long cuenta_p;
double k1,k2,k3;
struct_PID inf_pid;
extern struct_PWM inf_pwm;
extern soft_timer s_timer[3];
//taula que conte els 3 soft timers
double error_0;
//--------------------------------------------------------------------//funcio_velocitat:
//--------------------------------------------------------------------int funcio_velocitat(void)
{
double espai,temps;
espai=obtenir_voltes();
temps=get_timer(2)/1000.0;
s_timer[2].count=0;
velocitat=(espai/temps)*60.0;
return(0);
//nºde voltes en un interval de t
//temps esta en segons
//velocitat es mesura en rpm
}
//--------------------------------------------------------------------//obtenir_voltes()
//
retorna de les voltes
//--------------------------------------------------------------------double obtenir_voltes(void)
{
long cuenta;
double voltes;
static long cuenta_ant=0;
disable();
//comienzo regi¢n cr¡tica
cuenta=cuenta_p;
//info de posici¢n en pulsos
enable();
//fin de regi¢n cr¡tica
voltes=((cuenta-cuenta_ant)/(PULSOS_ENCODER*4.0));
cuenta_ant=cuenta;
Proyecto final de carrera
Página 94
Anexo C
return(voltes);
}
//---------------------------------------------------------------------//Variables_pid:demana per teclat les variables
//
del controlador pid
//---------------------------------------------------------------------int variables_pid(void)
{
char temp[10];
printf("Introdueix la variable Kp pel controlador PID: ");
if (captura_tecla_teclat(temp)) return(1);
else inf_pid.kp=atof(temp); //valor de kp
printf("Introdueix el temps Td(ms) pel controlador PID: ");
if (captura_tecla_teclat(temp)) return(1);
else inf_pid.Td=atof(temp);
//valor de td
printf("Introdueix el temps Ti(ms) pel controlador PID: ");
if (captura_tecla_teclat(temp)) return(1);
else inf_pid.Ti=atof(temp);
//valor de ti
printf("Introdueix la consigna de velocitat pel controlador PID: ");
if (captura_tecla_teclat(temp)) return(1);
else inf_pid.consigna=atof(temp);
//valor de consigna
//inf_pid.consigna=+180;
//consigna posicio
k1=inf_pid.kp*(1+(inf_pid.t_sample/inf_pid.Ti)+(inf_pid.Td/inf_pid.
t_sample));
k2=-(1+2*(inf_pid.Td/inf_pid.t_sample))*(inf_pid.kp);
k3=inf_pid.kp*(inf_pid.Td/inf_pid.t_sample);
return(0);
}
//----------------------------------------------------------------------//control: Funcio associada al control PID
//---------------------------------------------------------------------int control(void)
{
if (funcio_velocitat()) return(1);
error_0=inf_pid.consigna-velocitat;
//error_0=inf_pid.consigna-get_posicion();
//calcul de l'error de
//velocitat
//calcul de l'error de
//posicio
inf_pwm.dc+=k1*error_0+k2*inf_pid.error_1;
if(inf_pwm.dc>1.0) inf_pwm.dc=1.0; //evita la saturacio integral del PID
if(inf_pwm.dc<-1.0) inf_pwm.dc=-1.0;
if(duty_cycle(inf_pwm.dc)) return(1);
//actualitza Ton i Toff
inf_pid.error_2=inf_pid.error_1;
inf_pid.error_1=error_0;
return(0);
}
Proyecto final de carrera
Página 95
Anexo C
4.10 Librería PWM.c
//-----------------------------------------------------------------// FILE pwm.c
//-----------------------------------------------------------------//PFC
#define simula
#define project
#include "q5.h"
//PFC
#include "pwm.h"
//#include "printer.h"
#include "timer.h"
extern hard_timer h_timer;
struct_PWM inf_pwm;
//-----------------------------------------------------------------// frequency():
//-----------------------------------------------------------------int frequency(double freq)
{
//TOTS ELS VALORS ESTAN EN us
if(freq>0.0)
{
inf_pwm.dc=0.0;
inf_pwm.T=(1/freq)*1e6;
inf_pwm.ton=inf_pwm.T*inf_pwm.dc;
inf_pwm.toff=inf_pwm.T-inf_pwm.ton;
inf_pwm.gir=dreta;
inf_pwm.abans=OFF;
return(0);
}
return(1);
//retorn amb error
}
//----------------------------------------------------------------// duty_cycle:
//----------------------------------------------------------------int duty_cycle(double dc)
{
double tmp;
inf_pwm.gir=inf_pwm.dc>0.0?dreta:esquerra;
if ((dc>=-1.0)&&(dc<=1.0))
//comprova si tmp>0, si ho es Ton=tmp
{
//sino Ton=-tmp
tmp=inf_pwm.T*dc;
//actualitza valor de Ton
inf_pwm.ton=tmp>0.0?tmp:-tmp;
inf_pwm.toff=inf_pwm.T-inf_pwm.ton; //actualitza valor de Toff
return(0);
}
return(1);
//retorna amb error
}
Proyecto final de carrera
Página 96
Anexo C
//---------------------------------------------------------------// pwm():
//----------------------------------------------------------------int pwm(void)
{
//prove de gir a dretes
//if (inf_pwm.gir==dreta)
//aixi pel motor casa PFC
if (inf_pwm.gir==esquerra)
{
if (inf_pwm.abans==ON)
//prove de TON
{
if (set_timer(1,inf_pwm.toff)) return(1);
pulse_off_b();
inf_pwm.abans=OFF;
}
else
//prove de TOFF
{
if (set_timer(1,inf_pwm.ton)) return(1);
pulse_on_b();
inf_pwm.abans=ON;
}
}
else
//prove de gir a esquerres
{
if (inf_pwm.abans==ON) //prove de TON
{
if (set_timer(1,inf_pwm.toff)) return(1);
pulse_off_a();
inf_pwm.abans=OFF;
}
else
//prove de TOFF
{
if (set_timer(1,inf_pwm.ton)) return(1);
pulse_on_a();
inf_pwm.abans=ON;
}
}
return(0);
}
Proyecto final de carrera
Página 97
Anexo C
4.11 Librería Timer.c
/*-------------------------------------------------------------------FILE: timer.c
Implementacio de les funcions relatives als temporitzadors
---------------------------------------------------------------------*/
//PFC
#define simula
#define project
#include "q5.h"
//PFC
#include "pid.h"
#include "timer.h"
#include "pwm.h"
#include
#include
#include
#include
#include
//necessari per l'assignacio del apuntador a
//ini_timers
<stdio.h>
<conio.h>
<stdlib.h>
<dos.h>
<math.h>
void interrupt
(*old_handler_timer)();
//mante el manejador
//original
extern struct_PWM inf_pwm;
soft_timer s_timer[3];
//taula que conte els 3 soft timers
hard_timer h_timer;
extern long int irq_8253;
long int PID=0;
int error_irq=0;
//dtecta si alguna de les funcions associades h
//a generat error
//-------------------------------------------------------------------//captura_valors: comprova els valors de temps introduits
//
des de teclat
//-------------------------------------------------------------------int captura_valors(double *valors)
{
char temps[10];
printf("\n\nEls valors de TEMPS han d'estar en ms\n\n");
printf("Periode de mostreig PID: ");
if (captura_tecla_teclat(temps)) return(1);
else valors[0]=atof(temps);
printf("Periode de PWM: ");
if (captura_tecla_teclat(temps)) return(1);
else valors[1]=atof(temps);
return(0);
}
Proyecto final de carrera
Página 98
Anexo C
//----------------------------------------------------------------------// captura_tecla_teclat: captura una cadena de numeros i realitza
control
//
d'error.
//
retorna una cadena de caracters
//----------------------------------------------------------------------int captura_tecla_teclat(char taula[30])
{
char caracter;
int ind=0;
caracter=getchar();
while(caracter!='\n')
{
if ((caracter>='0')&&(caracter<='9')||(caracter=='.'))
taula[ind]=caracter;
ind++;
caracter=getchar();
}
if(caracter=='\n')
{
taula[ind]='\0';
return(0);
}
return(1);
//retorn amb error
}
//----------------------------------------------------------------------//set_timer: Inicialitza els camps de la estructura
//
s_timer d'un soft timer concret
//----------------------------------------------------------------------int set_timer(int timer,double interval)
{
//interval esta en us
switch(timer)
{
case 0:
//timer soft decremental
{
s_timer[0].count=(interval/h_timer.tic)+0.5;
//trunca interval
s_timer[0].recarga=(interval/h_timer.tic)+0.5;
break;
}
case 1:
//timer soft decremental
{
s_timer[1].count=(interval/h_timer.tic)+0.5;
//trunca interval
s_timer[1].recarga=(interval/h_timer.tic)+0.5;
break;
}
case 2:
//timer soft incremental
{
s_timer[2].count=0;
s_timer[2].recarga=0;
break;
}
default:
//sino es cap dels 3 retorna
return(1);
//un error
}
Proyecto final de carrera
Página 99
Anexo C
return(0);
}
//retorn sense error
//------------------------------------------------------------------//ini_timers: Inicialitza tots els soft timers.
//
Demana a l'usuari els valors de temps per als
//
diferents timers
//
//NOTA:
Els valors introduits per l'usuari seran en ms
//------------------------------------------------------------------int ini_timers(double *valors)
{
//valors es una taula on hi ha el temps de cada timer
s_timer[0].incremental=0;
//timer decremental
s_timer[0].fun=control;
//funcio associada al timer 0
if (set_timer(0,valors[0]*1000)) return(1);
//inicialitza soft_timer 0
//valor en us
s_timer[1].incremental=0;
//timer decremental
s_timer[1].fun=pwm;
//funcio associada al timer 1
if (set_timer(1,valors[1]*1000)) return(1);
//inicialitza soft_timer 1
s_timer[2].incremental=1;
//timer incremental
s_timer[2].fun=funcio_velocitat;
//funcio associada al timer 2
if (set_timer(2,valors[2]*1000)) return(1);
//inicialitza soft_timer 2
return(0);
//retorn sense error
}
//------------------------------------------------------------------//ini_struct_hard_timer: Inicialitza la estructura h_timer
//
colúlocant informaci¢ del timer hard
//
que usem per realitzar la practica
//------------------------------------------------------------------void ini_struct_hard_timer(int interval)
{
h_timer.port=base_8253;
//adre‡a base del 8253
h_timer.timer=tmr0;
//selecciona el comptador 0 del 8253
h_timer.clock=clock_timer;
//freq encia a la que oscilúla el
//timer
h_timer.tic=interval;
//interval entre interrupcions
}
//--------------------------------------------------------------------// canvi_vector_irq: guarda l'antic apuntador de la posicio 8 de la
//
taula vectoritzada i hi colúloca el nou
//
//--------------------------------------------------------------------void canvi_vector_irq(void)
{
old_handler_timer=getvect(vector_irq_timer);
setvect(vector_irq_timer,irq_timer);
}
Proyecto final de carrera
Página 100
Anexo C
//-----------------------------------------------------------------// trans_interval_tic: Transforma els microseg al valor
//
per carregar el 8253, arrodoneix i trunca
//
el valor a carregar
//-----------------------------------------------------------------int trans_interval_tic(void)
{
return(((h_timer.tic)*(h_timer.clock)*1e-6)+0.5);
}
//-----------------------------------------------------------------//ini_8253:
Inicialitza el timer 0 de la placa base del Pc
//
en mode rate generator. Introdu‹m el valor de
//
la base de temps al registre count #0
//-----------------------------------------------------------------int ini_8253(void)
{
int valor=0;
valor=trans_interval_tic();
//transforma microseg. a tics
if ((valor<2)||(valor>0xFFFF)) return(1);
outportb(base_8253+3,0x3C);
//timer0, mode rate generator
outportb(base_8253,(unsigned char)(valor&0x00FF));
//carrega byte_L del 8253
outportb(base_8253,(unsigned char)(valor>>8));
//carrega byte_H del 8253
return(0);
}
//---------------------------------------------------------------------// restaura_ sistema: restaura l'antic vector de la taula vectoritzada
//
i restaura el valor origina del timer 8253
//---------------------------------------------------------------------void restaura_sistema(void)
{
disable();
setvect(vector_irq_timer,old_handler_timer); //restaura vector
outportb(base_8253+3,0x3C);
//timer0, mode rate generator
outportb(base_8253,(unsigned char)(0xFF));
//recarrega 8253 amb valor original
outportb(base_8253,(unsigned char)(0xFF));
enable();
pulse_off_a();
//para el motor
pulse_off_b();
reset_prn();
//restaura port paralel
printf("\n\nSortida del Programa");
}
//---------------------------------------------------------------// irq_timer: Rutina de servei al timer 8253
//---------------------------------------------------------------void interrupt irq_timer(void)
{
int ind;
for(ind=0;ind<3;ind++)
{
if(!(s_timer[ind].incremental))
Proyecto final de carrera
//Comprova els 3 soft_timers
//timer decremental
Página 101
Anexo C
{
if(s_timer[ind].count)
//si no es 0 es decrementa
s_timer[ind].count--;
//comprova per nivell si s_timer es
//0, si es 0 continua cridant la funcio
if(!s_timer[ind].count)
//temps exhaurit
{
//es crida la funcio associada
error_irq=(*s_timer[ind].fun)();
s_timer[ind].count=s_timer[ind].recarga; // recarrega el s_timer
}
}
else
{
//timer incremental
if((s_timer[ind].count)<2e31)
s_timer[ind].count++;
else
error_irq=1;
//error
}
}
sim_motor();
irq_8253++;
outportb(base_8259,EOI_NS);
// envia final irq no especific
}
//-----------------------------------------------------------------------// funcio get_timer: retorna el valor actual d'un soft_timer especific
//-----------------------------------------------------------------------double get_timer(int timer)
{
//transforma el valor a ms
return(((s_timer[timer].count)*h_timer.tic)/1000);
}
Proyecto final de carrera
Página 102
5
Anexo D: Referencias
[1]
[2]
Libro: Esteban del Castillo, Control de Procesos, Publicacions URV, Año 2008.
Libro: Felipe Espinosa Zapata, Análisis Diseño y Realización de Sistemas Electrónicos de Control
Contínuo, Universidad de Alcalá de Henares, Año 2006.
Libro: Manuel Mazo Quintas, Control de Motores Paso-Paso, dc con escobillas y brushless,
Universidad de Alcalá de Henares, Año 1997
[3]
Proyecto final de carrera
Página 103
Descargar