Documente Academic
Documente Profesional
Documente Cultură
#include <16f690.h>
#use delay (clock=8MHZ)
Estas 2 primeras instrucciones describen el microcontrolador a utilizar (en este caso el
16f690, pero se puede elegir el que se desee utilizar) .luego la frecuencia del oscilador
(cristal de cuarzo, oscilador interno que algunos pic disponen, circuito RC, cualquier
fuente que genere los pulsos para sincronizar las operaciones internas)
Unsigned int8 n_pls, r_pls, Kp,Ki;
Unsigned long duty, r_value, k;
Signed long uc, e_pls, Iold, Inew;
Luego de las instrucciones anteriores proseguimos a declarar las variables que vamos
a utilizar, en este caso son variables globales, es decir se pueden obtener sus valores
en cualquier parte del programa, no estn restringidas a un espacio (como por ejemplo
una funcin).Lo ms importante que hay que saber es que mediante la declaracin de
variables reservamos espacio en la memoria.
SIGNIFICADO DE CADA VARIABLE:
UNSIGNED INT8 n_pls, r_pls, Kp, Ki
Unsigned int8 define una variable sin signo (Unsigned), generalmente se est
hablando de valores positivos nunca negativos, el tamao de esta variable es un
entero de 8 bits (int8).
n_pls
Como se utiliza un encoder para poder sensar la velocidad de motor, es
necesario conocer la cantidad de pulsos que genera el encoder en un tiempo
determinado (tiempo de muestreo), esa cantidad de pulsos de almacenan en
esta variable. n_pls significa o es un acrnimo de nmero(n) de pulsos (pls).
r_pls
La velocidad del motor se modifica mediante un potencimetro (entrada de
referencia).Este potencimetro va conectado a uno de los conversores del pic
(ADC), de esta manera asociamos un valor del potencimetro con una
determinada velocidad. Recordar que en el caso de los ADC del pic 16f690
tienen una resolucin de 10 bits, esto quiere decir que puedo obtener 1024
valores. Por lo tanto podemos decir:
KP,KI
Estas variables son los parmetros del controlador PI. La constante
proporcional (KP) y la constante integral (KI).
Duty
Esta variable hace referencia al ciclo de trabajo (duty cicle) de la seal PWM,
necesaria para modificar la velocidad del motor (en realidad el objetivo de
todo el programa es poder variar automticamente este valor segn
convenga).
r_value
Esta variable almacena o toma los valores del potencimetro despus de haber
convertido el nivel de voltaje a un valor numrico (digital).Es decir y como ya
haba mencionado antes:
K
La variable k solo se utiliza para poder contar y poder visualizar el nmero de
interrupciones que se estn produciendo desde el momento en que comience
a funcionar todo el programa. Su valor no es muy importante para el
funcionamiento de todo el programa. Cmo dije es para darme una idea de
cuantas veces el pic se ha detenido a leer su entrada de referencia y actuar
conforme a ello (para esto son las interrupciones).
UC
e_pls
Iold,Inew
#int_TIMER1
Void TIMER1_isr (void)
{
INSTRUCCIONES A EJECUTAR
}
set_timer1(40535);
Esta instruccin me permite definir el tiempo de muestreo. El timer 1 del pic 16f690
(que es el que se ha utilizado en este caso) tiene una resolucin de 16 bits es decir que
puede tomar 65535 valores posibles.
Pero valores de qu?
En este caso de tiempo
Cunto dura cada valor?
Depende del valor del oscilador a utilizar. Cuando ya se ha definido el valor del
oscilador (4MHZ, 8MHZ, etc.), se tiene que necesariamente dividir este valor entre
4. Hecho esto, el resultado es el tiempo que dura cada uno de los 65535 posibles
valores del timer 1.
Ejemplo:
1. Utilizo un cristal de cuarzo de f=4MHZ
2. Lo divido entre 4 ,que sera f_1=1MHZ
3. Convierto esta frecuencia en tiempo T=
= 1 us
Este es el valor de cada uno de los 65535 valores del timer 1: 1 microsegundo
Por lo que deducimos que el timer 1 puede contar hasta: 65535x1 us=65535 us
Eleccin de la PRE_CARGA
Supongamos que ya defin o determine el valor que quiero como tiempo de muestreo
Tm=0.1 us (para este caso).
Aplico la siguiente relacin:
Tm=
( _)
set_timer0(0);
Esta instruccin inicializa el timer 0 en cero, lo que significa ceros pulsos contados por el
timer. Cada vez que se produce una interrupcin el timer registra en nmero de pulsos,
utiliza la informacin y luego inicializamos el timer a cero, para comenzar una nueva
cuenta, as sucesivamente.
r_value = read_adc();
El timer 0, habamos dicho que cuenta hasta una mximo de 255(hay que tenerlo en
cuenta, ya que es la razn de porque la divisin entre 5)
El valor digital mximo obtenido del potencimetro es 1024.
Ahora yo tendr que hacer la tarea que esos 1024 valores posibles del potencimetro
puedan entrar en 8 bits (que es la mxima resolucin del timer 0), todo se hace con el
objetivo de poder comparar el nmero de pulsos (n_pls) ledos por el timer 0 y el valor
ledo por el potencimetro (r_value).
As que divido el valor ledo por el potencimetro entre 5, y asigno el resultado a la
variable a r_pls.
Aqu calculo el error que hay entre mi referencia (r_pls) y los pulsos contados por el
timer 0 (n_pls).
La palabra que esta entre parntesis antes de cada variable (Signed long), me va a
permitir convertir las variables enteras de 8 bits r_pls y n_pls tomen el formato de
variables con signo de 16 bits. Esto se hace porque la variable e_pls tiene ese formato
y tenemos que asegurar que la resta de r_pls y n_pls den como resultado un valor de
tipo Signed long.
Inew = 400;
Toda esta parte describe la accin integral del controlador: Inew = Iold + Ki*e_pls/10;
Como vemos la nueva accin integral (Inew) depende del valor anterior (Iold), de la
constante integral (Ki) y del error (e_pls).La divisin entre 10 forma parte del diseo del
controlador, as que es posible cambiar este valor para ajustar el controlador segn
convenga.
La condicin:
uc = Kp * e_pls + Inew;
// implementar controlador PI
Esta parte es la expresin completa del controlador, es decir es la accin del controlador.
Iold = Inew;
Cada vez que se termina de ejecutar uc (accin de control), la accin integral calculada
(Inew), pasa a ser la antigua o anterior accin integral (Iold), esto es debido a que
nuevamente se tendr calcular una nueva accin integral.
printf("# = %Lu UC = %Ld \r\n",k,uc);
Me permite visualizar el valor de K y de UC por medio del puerto serial (en proteus
conecto un terminal virtual y podre observar peridicamente estos valores)
if(uc < 0)
uc = 0;
if(uc > 400)
uc = 400;
Como haba visto anteriormente el ciclo de trabajo del pwm no puede ser mayor de 400 y
tampoco ser menor a cero, con estas condiciones nos aseguramos que se cumpla.
duty = uc;
Al final la accin de control (uc), se asigna como valor del ciclo de trabajo de la seal pwm.
Lo que quiere decir que uc modifica el tiempo en el cual la seal pwm se mantiene en
alto.
set_pwm1_duty(duty);
Por ultimo mediante esta instruccin hacemos efectiva el cambio de la seal pwm segn
el valor de duty. Esta instruccin nos dice que establecemos el valor del ciclo de trabajo
de la seal pwm segn los valores que adquiere duty.
printf(" Ref = %u N de P. Med. = %u Error = %Ld Duty = %Lu \n\r",r_pls, n_pls, e_pls,
duty);
Nuevamente con esta instruccin podremos visualizar por medio del puerto serial los
valores que adquieren peridicamente las variables: r_pls, n_pls, e_pls, duty.
output_low(PIN_C0);
k = k +1;
Estn explicadas al comienzo.
setup_adc_ports( sAN0|VSS_VDD );
setup_adc(ADC_CLOCK_INTERNAL );
El ADC funciona con una seal de reloj, la fuente o de donde proviene esta seal
se indica mediante esta instruccin:
set_adc_channel( 0 );
Habilito el ADC 0 o mejor dicho el canal 0.
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_2);
Con esta instruccin configuramos el timer 0.El timer 0 se utiliza en este caso para
contar pulsos generados por el encoder (ondas cuadradas).Pero lo que el realmente
cuenta o detecta son los flancos de bajada o subida de los pulsos.
Entonces el pic detecta o bien el flanco de subida o el flanco de bajada. Cmo le digo
que flanco detecte? Esto se hace con la instruccin: RTCC_EXT_L_TO_H.
Esta instruccin indica que el timer 0 va a detectar flancos externos (EXT), que van
desde alto a bajo (L_TO_H), es decir un flanco de bajada.
La instruccin RTCC_DIV_2, indica que cada 2 flancos se van a contar como uno (DIV_2)
set_timer0(0);
Inicializo el timer 0 a cero
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
T1_INTERNAL; indica que utilizaremos la seal de reloj interna del pic
(INTERNAL), la cual equivale a la frecuencia del oscilador dividido entre 4.
set_timer1(40535);
Tosc = 1/Fosc
Dnde: Tosc periodo de la oscilador utilizado, Fosc frecuencia del oscilador
utilizado
setup_timer_2(T2_DIV_BY_1,99,1);
El pic contiene un mdulo llamado CCP (comparador, captura y pwm).Por lo tanto puede
trabajar a la vez con solo una de esas funciones. As que:
setup_ccp1(CCP_PWM);
set_pwm1_duty(200L);
setup_oscillator(OSC_8MHZ);
Esta instruccin ndica que voy a utilizar el oscilador interno del pic, es decir
que no voy a utilizar ningn cristal u oscilador externo. Esto es posible solo en
algunos microcontroladores, en este caso el 16f690, si lo permite.
En caso se quiera utilizar un cristal, esta instruccin no se coloca.
Kp = 5;
Ki = 5;
Iold = 0;
Inew = 0;
k = 1;