Sunteți pe pagina 1din 11

INTERPRETACION DEL CODIGO

#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:

5 voltios (valor mximo) es igual 1024


0 voltios(valor mnimo) es igual a 0
De esta manera podemos asociar cualquier voltaje del potencimetro
con su respectivo valor digital.

r_pls significa o es un acrnimo de pulsos (pls) de referencia(r).Lo que trae la


idea que mediante el potencimetro le comunico al pic cuantos pulsos quiero
que comience a registrar o a contar el encoder, todo esto se traduce a: que
velocidad del motor deseo.

KP,KI
Estas variables son los parmetros del controlador PI. La constante
proporcional (KP) y la constante integral (KI).

UNSIGNED LONG duty, r_value, k;


Unsigned long define una variable sin signo (Unsigned), generalmente se est
hablando de valores positivos nunca negativos, el tamao de esta variable es un
entero de 16 bits (long), tambin pudo ser int16 (es lo mismo).

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:

Si el voltaje en el potencimetro es 5 voltios su equivalente en


digital seria 1024.Por lo tanto r_value sera igual a 1024.
r_value=1024 y as con los dems valores

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).

SIGNED LONG uc, e_pls, Iold,Inew


Signed long define una variable con signo (Signed), estamos hablando de valores
positivos o negativos, el tamao de esta variable es un entero de 16 bits (long),
tambin pudo ser int16 (es lo mismo).

UC

Esta variable es la accin de control del controlador PI, se utiliza para


almacenar el resultado de la accin proporcional y la accin integral.
Es el resultado total de todo el cdigo del programa (mejor dicho todo se basa
en obtener este valor, por qu es quien modifica el ciclo de trabajo de la seal
PWM)

e_pls

e_pls significa o es un acrnimo de pulsos (pls) de error (e).En esta variable


almacenamos el error obtenido entre mi entrada de referencia (r_pls) y el valor
obtenido en el encoder (n_pls).

Iold,Inew

En estas dos variables almacenamos el valor de la accin integral. La nueva


accin integral (Inew) y la antigua o anterior accin integral (Iold).Las dos estn
relacionadas, ya que el nuevo valor de la accin integral se logra calcular con
el valor anterior de la accin integral.

#int_TIMER1
Void TIMER1_isr (void)
{
INSTRUCCIONES A EJECUTAR
}

La directiva #int_Timer1 es la funcin de interrupcin, es decir el espacio del programa


en donde yo, voy a describir (programar) que es lo que va hacer el microcontrolador cada
cierto tiempo (tiempo de muestreo).Mejor dicho el pic se va a detener cada cierto tiempo
para realizar lo que hay dentro de esta funcin (instrucciones a ejecutar), luego de haberse
ejecutado, seguir con su normal funcionamiento y as todo el tiempo. Para saber dnde
comienza y acaba este bloque tengo que identificar las llaves ({}), que inicializan y
terminan esta parte.
La parte void TIMER1_isr (void) describe lo siguiente:

El primer void (vaco) significa que la funcin de interrupcin no va a


devolver ningn valor, es decir que ningn valor de alguna variable o
resultado que se encuentre dentro de este bloque, se va pasar a otra
funcin, para que sea utilizada.
El segundo void (vaco), el que est entre parntesis significa que la
funcin no va a recibir ningn parmetro o valor proveniente de otra
funcin.

TIMER1_isr, es el nombre que quieres que lleve la funcin (puedes poner


cualquier nombre como identificador).El nombre que aparece aqu, es el
que te pone por defecto pic c.

AHORA VAMOS A DESCRIBIR QUE HAY EN EL INTERIOR DE LA FUNCIN EXPLICADA


ANTERIORMENTE (INSTRUCCIONES A EJECUTAR):
output_high(PIN_C0);
Esta instruccin que significa poner en alto el pin C0 del microcontrolador, sirve para
poder visualizar o detectar cuando se produce las interrupciones y cunto tiempo
duran (menciono cuanto tiempo duran porque al final de la funcin de interrupcin
se visualiza otra instruccin contraria a esta, llamada output_low (PIN_C0); que lo
que hace es poner en bajo el pin C0 del microcontrolador.
As que yo puedo medir el tiempo que dura o hay entre su estado alto y bajo del pin
C0.Por ejemplo mediante un osciloscopio.
Si no coloco esta instruccin afecta en algo el funcionamiento del programa?
No, ya que solo es una manera para comprobar que los tiempos de interrupcin son
correctos.

set_timer1(40535);

// Init timer1 to get Fm = 10 Hz. Tm = 0.1 sec

NOTA ANTES DE SEGUIR:


LA INSTRUCCIN POR DEFECTO ES:
Set_timer_1 (PRE_CARGA)
Para este caso PRE_CARGA=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=

( _)

El PRE-ESCALADOR es un factor de divisin de frecuencia. Para TIMER1 puede tomar


valores de: 1, 2, 4 y 8, y para TIMER2 valores de 1, 4 o 16.
Reemplazando tiempo de muestreo, frecuencia de oscilador y escogiendo el
pre_escalador igual a 8, obtenemos:
PRE_CARGA=40535

n_pls = get_timer0(); // READ AND RESET ITMER0


El nmero de pulsos del encoder se leen mediante el timer 0 del pic. Esta instruccin me
dice que el timer 0 va a contar el nmero del pulsos (flancos de una onda cuadrada) del
encoder y el valor obtenido se almacenara en la variable n_pls.
El timer 0 del pic (16f690), tiene una resolucin de 8 bits, por lo tanto 255 valores o
cuentas como mximo.

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();

// read reference volts

Esta instruccin me indica que el valor obtenido del potencimetro se almacenara en la


variable r_value.read_adc () significa leo el valor del ADC.

r_pls = (unsigned int8)(r_value/5);

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.

e_pls =(signed long)r_pls - (signed long)n_pls;

// error en nmero de pulsos

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 = Iold + Ki*e_pls/10;


if(Inew > 400)

// implementar el termino integral


// stop wind up

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:

If (Inew > 400)


Inew = 400;

Por qu si Inew es mayor a 400 su valor ser de Inew = 400?


El ciclo de trabajo de la seal pwm o mejor dicho el tiempo en el cual la seal esta en
alto tiene como valor mximo 400(es el 100%).As que para asegurarnos, que en caso
Inew alcance valores mayores a este, le asignamos el valor mximo.

Por qu 400 y no otro valor?


Puede tomar otro valor, pero para este caso ha sido configurado como valor mximo del ciclo
de trabajo (duty cicle) del pwm en 400.
Cmo se obtuvo este valor? Se ver ms adelante en la configuracin del pwm del
microcontrolador.

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 no puede ser negativo ni mayor de 400

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;

// d= 0% equ a duty = 00, d = 100% is duty = 400

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.

AHORA PASAREMOS A EXPLICAR LA PARTE QUE CORRESPONDE A


LA CONFIGURACION DEL MICROCONTROLADOR
void main()
{
CONFIGURACION
While (1) { }
}
Esta es la funcin principal de todo programa hecho en pic. Todo programa debe tener
un void main (), es lo primero que ejecuta el microcontrolador al encenderse. El inicio
y fin de esta funcin estn dadas por las llaves ({}).
El While(1) {},es para crear un bucle infinito (que se repita continuamente),su
significado es mientras sea verdadero(1),que siga ejecutndose lo que se haya
definido que haga el microcontrolador.

CONFIGURACION DEL CONVERSOR ANALOGICO-DIGITAL

setup_adc_ports( sAN0|VSS_VDD );

Con esta instruccin configuro el conversor analgico-digital del pic (ADC).Como


un pic puede tener varios ADC en varios pines del microcontrolador, con esta
instruccin le indico que voy a utilizar solo el ADC 0 (sAN0).

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:

Para este caso estamos indicamos que vamos utilizar la seal de


reloj interna del pic (ADC_CLOCK_INTERNAL).

Tambin puede ser externa(de algn circuito externo que genere


una seal de reloj :ADC_CLOCK_EXTERNAL)

set_adc_channel( 0 );
Habilito el ADC 0 o mejor dicho el canal 0.

CONFIGURACION DEL TIMER 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

CONFIGURACION DEL TIMER 1

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);

// Fm = 10 Hz. Tm = 0.1 sec;

Esta explicado anteriormente.

CONFIGURACION DEL TIMER 2


Los registros del timer 2 se utilizan para configurar el mdulo PWM.Asi que tendremos
que determinar la frecuencia de la seal pwm, su periodo y el duty cicle o ciclo de
trabajo de la seal(es decir el rango que puede tomar el duty cicle).

Para lo cual utilizaremos las siguientes expresiones:

PRESCALER: para TIMER2 valores de 1, 4 o 16.

Tosc = 1/Fosc
Dnde: Tosc periodo de la oscilador utilizado, Fosc frecuencia del oscilador
utilizado

setup_timer_2(T2_DIV_BY_1,99,1);

La instruccin por defecto es: setup_timer_2 (T2_DIV_BY_1, PR2, PRESCALER);


Ahora lo que tengo que hacer es solo reemplazar los valores de PR2 y del PRESCALER

CONFIGURACION DEL MODULO CCP

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);

Indico que el mdulo CCP, trabajara como PWM.

set_pwm1_duty(200L);

Inicializo el ciclo de trabajo del pwm en la mitad de su valor mximo (400), es


decir 200.Lo que equivale a decir que el ciclo de trabajo est al 50% de su valor.
OTRAS CONFIGURACIONES
enable_interrupts(INT_TIMER1);
enable_interrupts (GLOBAL);
La primera instruccin me permite habilitar la interrupcin del timer 1.
Con la segunda instruccin habilito las interrupciones globales (siempre que
se vaya a utilizar cualquier interrupcin se tiene necesariamente que poner
esta instruccin.

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.

// TODO: USER CODE!!

Kp = 5;
Ki = 5;
Iold = 0;
Inew = 0;
k = 1;

De esta manera inicializamos las variables Kp, Ki, Iold, Inew, K

HASTA AQU ES TODO

S-ar putea să vă placă și