sábado, 23 de noviembre de 2019

LABORATORIO NRO. 13

MICROCONTROLADORES

Laboratorio Nº 13

Lectura de Entradas analógicas

1. CAPACIDAD TERMINAL:
● Utilizar al microcontrolador en aplicaciones de control electrónico.
● Desarrollar y ejecutar programas en un microcontrolador PIC
● Programar y configurar interfaces básicas del microcontrolador.


2. COMPETENCIA ESPECÍFICA DE LA SESIÓN:
 Lecturas analógicas de un canal del PIC
● Configuración de un Sensor de Temperatura
● Lectura analógica en una pantalla LCD

3. CONTENIDOS A TRATAR: 
Entradas analógicas
● Sensor de Temperatura

4. RESULTADOS:

●Diseñan y optimizan sistemas y procesos para cumplir con las condiciones establecidas y gestionando adecuadamente los recursos materiales y humanos.

5. MARCO TEÓRICO:
ENTRADAS ANALÓGICAS:
El PIC 16F877A, entre sus varios periféricos, posee un conversor análogo a digital (CAD) para ello el PIC cuenta con pines por donde le llegará la señal analógica, el conversor analógico digital PIC cuenta con un circuito que carga un condensador interno al PIC con la tensión analógica que le está llegando a la entrada analógica, luego la tensión almacenada en el condensador lo convierte en un número binario de 10 bits que representará la tensión almacenada en el condensador, como la resolución que puede leer los voltajes presentes en los pines marcados como AN0 hasta AN7.




La lectura de estos se hace de forma multiplexada, una a la vez. Como buen sistema digital, las lecturas son tratadas como muestras tomadas a intervalos regulares de tiempo, las que son retenidas por un capacitor interno. La cantidad de muestras por segundo o velocidad de lectura son un submultiplo de la velocidad de oscilación del PIC por lo cual se debe cuidar que esta no resulte ser mayor que el tiempo que el capacitor interno demora en cargarse.

Una mala elección de velocidad de lectura, puede resultar en mediciones erróneas, por debajo de las magnitudes que se pretenden medir. Según Microchip, el tiempo de adquisición de los datos debe ser mayor a 19.72us.

Registros Involucrados en la conversión A/D:
La conversión análogo-digital, se configura y controla con los registros ADCON0 y ADCON1, donde es posible configurar aspectos como el canal (pin del PIC) en que se hará la lectura, velocidad de muestreo, estado de la conversión, pines análogos o digitales, entre otros. Por otro lado, la conversión resultante se alberga en los registros ADRESH y ADRESL La gráfica lo explica de mejor manera.


El bit ADFM y como leer el resultado:
El resultado de la conversión, finalmente será un numero de 0 a 1023 correspondiente a los 0 a 5 volts, tal como se muestra en la primera Imagen bajo el título principal. Este número al ser de 10 bits no cabe en un solo registro y es por eso que se utilizan dos (ADRESH y ADRESL) en binario puede parecer difícil de entender, pero en el lenguaje C de XC8 basta con sumar ambos registros y almacenar el resultado en un INT para tener el número entre 0 y 1023 correspondiente a la conversión.

6. TAREA GUIADA DENTRO DEL LABORATORIO:
1. Simule y pruebe en el entrenador el programa del LCD de acuerdo al circuito y código siguiente. Asegúrese que el PIN RW esté conectado a GND (jumper sin conectar) y que el LCD esté conectado al PUERTO D mediante interruptores rojos debajo del mismo:


//Desactivar dip switch de DISPLAYS para correcto funcionamiento.
//Entrada analógica en el puerto A3.

#include <16f877a.h>             // Incluimos archivo con PIC a utilizar
#device adc=8                    // Utilizamos 8 bits de RESOLUCION de lectura
#use delay (clock=20M)           // Indicamos al compilador que trabajaremos a 20Mhz
#fuses HS, NOPROTECT, NOWDT      // Configuración básica de los fusibles

#define LCD_ENABLE_PIN        PIN_D3   //Definimos los pines a ser utilizados por la
#define LCD_RS_PIN            PIN_D2   //pantalla LCD
#define LCD_RW_PIN            PIN_A0  
#define LCD_DATA4             PIN_D4
#define LCD_DATA5             PIN_D5
#define LCD_DATA6             PIN_D6
#define LCD_DATA7             PIN_D7 
#include <lcd.c>                 // Incluimos librería para manejar Pantalla LCD

int lectura=0;

void main ()
{
   lcd_init () ;                       // Inicializamos pantalla LCD
   printf (lcd_putc, "\fLECTURA ANALOGICA") ;  // Mandamos mensaje por única vez

   //Configuración del puerto analógico
   setup_adc_ports (AN0_AN1_AN3);
   setup_adc (ADC_CLOCK_INTERNAL);
   set_adc_channel (3); //lectura del canal analogico 3
   delay_us (20);
  
   WHILE (true)
   {
      lectura = read_adc ();        // Leemos Canal A0
      delay_ms (20) ;               // esperamos para una correcta lectura
      lcd_gotoxy(1,2);              // ubicamos cursos en LCD
      printf (lcd_putc, "Puerto A3: %4u", lectura); // imprimimos valor
      delay_ms(100);                // esperamos
     
    }
     }


2. Realice los cambios sugeridos a continuación y muestre sus resultados

a. Donde dice “#device adc=8” cambie por “#device adc=10”; convierta la variable “lectura” en entero de 16 bits y la línea printf cambie “%4u” por “%4lu”. ¿Cuál es el cambio mostrado en la pantalla LCD? ¿por qué?.
El cambio que se da, es que la pantalla LCD logrará mostrar el valor de todo el registro mediante la variación del potenciómetro, siendo en este caso de 0 a 1023 el valor mostrado, y el valor del registro es 210 = 0 a 1024.
Debido a que se está empleando un adc = 10, al ser mayor que 8 (int), se emplea el siguiente de 16 bits (int16). 


b.    Convierta el valor leído en valor de voltaje de 0 a 5 voltios. Para esto cambie la variable “lectura” a variable tipo float y configure su forma de mostrarse en el LCD. Luego, en la función While(true),  añada la instrucción “lectura = lectura /  204.6”. Cambie las instrucciones para que en la pantalla del LCD aparezca algo así “Tension: 3.456 v”. 





c.    Finalmente agregue una condición IF para que si el valor de voltaje supera 4.5   voltios, mostrar el mensaje “WARNING” en la primera línea del LCD.
     //Desactivar dip switch de DISPLAYS para correcto funcionamiento.
    //Entrada analógica en el puerto A3.



7. TAREA A SER EVALUADA:
TERMOSTATO DIGITAL CON CONTROL ON-OFF:
Se trata de un circuito que deberá controlar el encendido y apagado de un relé (el cual se supone que conecta/desconecta un elemento calefactor) dependiendo de la temperatura leída en el sensor y de la temperatura seteada por los pulsadores respectivos. La pantalla LCD y los leds muestran el estado del termostato.

Este proyecto deberá contar con las siguientes partes:


Textos a mostrar en la pantalla LCD:


Condiciones de funcionamiento:
  • La pantalla inicial deberá mostrarse al principio durante 2 segundos, luego deberá mostrarse la pantalla normal.
  • Para aumentar o disminuir la temperatura SET, deberá presionarse los pulsadores respectivos, pero aún no debe controlar la salida de relé, sino hasta presionar “aceptar”. El botón “cancelar” ejerce la función de RESET y detiene todo el proceso.
  • El sensor de Temperatura será emulado mediante un potenciómetro (RA3) y su rango será de 0 a 100 grados centígrados.
  • El rango de temperatura OK será de 10 grados. Ejemplo: si SET=80, el led verde debe encender si Temp varía entre 75 y 85 grados. (Opcional).


8. EVIDENCIA DE TRABAJO EN LABORATORIO:




Link del video: https://youtu.be/FLXDBQNQJU0

9. OBSERVACIONES:
  • Cada vez que se quiera escribir un texto diferente sobre la pantalla, es preferible borrar esa línea o limpiar todo el LCD, para de esta manera evitar la sobrescritura y combinación de textos o acoplamiento.
  • No es necesario realizar alguna configuración de comando de inicialización para emplear las luces LED. Su habilitación se da desde el mismo módulo físico.
  • Las variables empleadas antecedidas con "int" tendrán un registro de 8 bits (256 valores) por lo que se debe parametrizar y poner condiciones al momento de operar cada acción.
  • Pese a restricciones de que cuando el SET esté en un valor de cero no disminuya y se quede en ese valor, el programa procedía a mostrar un valor de 255, empleando tanto condicionales como: SET<0, SET<=0,SET<=1,entre otros.
10. CONCLUSIONES:
  • Se logró realizar la programación para realizar el control de un registro de temporizador, empleándolo para que ejecute la acción de un contador.
  • Se dan casos de errores al momento de probar la programación, no siempre el problema radica en la misma sino puede ser también en el software o en el módulo.
  • Se simuló el modo de control ON/OFF, siendo el operador quien manipule la variable de variación de la temperatura, y a su vez se programaron ciertos indicadores de acciones que tendrían una simbolización en lo físico, como el relé reemplazado por una luz LED.

viernes, 15 de noviembre de 2019

LABORATORIO NRO. 12

MICROCONTROLADORES

Laboratorio Nº 12

Manejo del Timer 

y las Interrupciones

1. CAPACIDAD TERMINAL:
● Utilizar al microcontrolador en aplicaciones de control electrónico.
● Desarrollar y ejecutar programas en un microcontrolador PIC
● Programar y configurar interfaces básicas del microcontrolador.


2. COMPETENCIA ESPECÍFICA DE LA SESIÓN:
 Conocer el funcionamiento y la configuración de las Interrupciones. 
● Conocer el funcionamiento y la configuración del Timer cero.
● Aplicar estos conocimientos en la realización de un cronómetro.
3. CONTENIDOS A TRATAR: 
Interrupciones.
● Timer cero.

4. RESULTADOS:

●Diseñan y optimizan sistemas y procesos para cumplir con las condiciones establecidas y gestionando adecuadamente los recursos materiales y humanos.

5. MARCO TEÓRICO:

INTERRUPCIONES:
Las interrupciones con el PIC son eventos que hacen que el programa principal se detenga, para que el microcontrolador PIC se dedique ha realizar otras tareas, mientras no ocurra una interrupción el microcontrolador solo realizará las tareas indicadas dentro del programa principal.
Para habilitar el uso de las interrupciones con el PIC se utiliza el registro INTCON, cada microntrolador PIC tiene su registro INTCON, algunos tendrán más de uno, es necesario revisar su hoja de datos para verificar para que se utilizan cada uno de sus bits, pero lo que si es común en ellos es el bit7 o bit GIE.


El siguiente es el registro INTCON para el PIC16F877A:

TEMPORIZADOR:
Un temporizador contador PIC es un registro que aumenta su valor en una unidad con cada 4 ciclos de reloj al cual se encuentre funcionando el microcontrolador PIC, si por ejemplo la frecuencia del oscilador es de 20MHz, entonces  el ciclo de trabajo del microcontrolador PIC será de 50ns, por lo que el temporizador contador PIC aumentará  su  valor de uno en uno en cada 50 nanosegundo; por ejemplo cuando el temporizador aumenta su valor en 10 unidades habrán transcurrido 0,5us.
El temporizador contador PIC puede producir interrupciones.

Los microcontroladores PIC suelen tener varios temporizadores, como ejemplo se utilizará el PIC16F877A, el cual tiene 3 temporizadores que son llamados timer0, timer1 y timer2, el tiempo que tarda el temporizador contador PIC en aumentar su valor de unidad en unidad, se puede modificar por programa mediante el uso de prescalers, siendo de esta manera mucho mas provechosos; dependiendo del modelo de microcontrolador PIC utilizado, no todos los temporizadores pueden ser utilizados como temporizador y también como contador.


El temporizador contador PIC puede aumentar sus valores de 0 a 255 si es de 8 bits como el timer0, o de 0 a 65535 si es de 16 bits como el timer1, cada vez que estos registros alcanzan su máximo valor se reinician, volviendo a contar desde su valor mínimo hasta su máximo, ademas pueden ser programados para provocar interrupciones.
Para el uso del temporizador contador PIC se cuenta además con un grupo de registros mediante los cuales se puede lo puede configurar de acuerdo a las necesidades que se tengan.

INTERRUPTOR TIMER 0:
Mediante la interrupción timer0 PIC se puede detener el programa  principal con el cual este trabajando el microcontrolador PIC, para indicarle al microcontrolador que se dedique a realizar otras tareas, al finalizar la interrupción timer0 PIC, se seguirá con el programa principal desde donde fue interrumpido.
Del registro INTCON se pondrá su bit7 GIE a 1 para habilitar el uso de las interrupciones, su bit5 TMR0IE se pondrá a 1 para habilitar el uso de la interrupción timer0 PIC por desborde, su bit2 TMR0IF es la bandera que detecta que se ha producido la interrupción del  timer0 por desborde y se tendrá que poner a 0 para que haga la detección, cuando ocurre la interrupción este bit se pone automáticamente a 1, y para seguir detectando mas interrupciones externas en al rutina de atención a las interrupciones se tendrá que poner nuevamente a 0 este bit.

Del registro OPTION_REG se pone a 0 su bit5 T0CS para indicarle al PIC que se utilizará el timer0 como temporizador, el bit4 se pone a 0 ya que este se usa cuando el timer0 es utilizado como contador, mediante su bit3 PSA=0 se indica a quien será asignado el prescaler, y con sus bits PS2:PS0 se indica de cuanto será el prescaler.


6. TAREA GUIADA DENTRO DEL LABORATORIO:
1. Simule y pruebe en el entrenador el programa mostrado de acuerdo al circuito y código siguiente. Asegúrese que el LCD esté conectado al PUERTO D mediante interruptores rojos debajo del mismo:


   #include <16f877a.h>             // Incluimos archivo con PIC a utilizar
#device adc=8                    // Utilizamos 8 bits de RESOLUCIÓN de lectura
#use delay (clock=20M)           // Indicamos al compilador que trabajaremos a 20Mhz
#fuses HS, NOPROTECT, NOWDT      // Configuración básica de los fusibles

#define LCD_ENABLE_PIN        PIN_D3   //Definimos los pines a ser utilizados por la
#define LCD_RS_PIN            PIN_D2   //pantalla LCD
#define LCD_RW_PIN            PIN_A0  
#define LCD_DATA4             PIN_D4
#define LCD_DATA5             PIN_D5
#define LCD_DATA6             PIN_D6
#define LCD_DATA7             PIN_D7 
#include <lcd.c>                 // Incluimos librería para manejar Pantalla LCD

int centesimas=0,segundos=0,minutos=2;




#int_TIMER0                      // FUNCION DE INTERRUPCION POR
void TIMER(VOID)                 // DESBORDAMIENTO DEL TIMER 0
{
   ++centesimas;                 // incrementar una centésima
   if (centesimas>99)
      {
      ++segundos;                // si llegamos a 100, incrementar un segundo
      centesimas=0;
      }
   if (segundos>59)
      {
      ++minutos;                 // si llegamos a 60, incrementar un minuto
      segundos=0;
      }
   if (minutos==3)                // si llegamos a 3 minutos, hacer alguna acción
      {
      minutos=0;
      disable_interrupts (INT_TIMER0);          //habilita interrupcion de timer0
      // agregar cualquier otra acción necesaria.
      }
  
   set_timer0 (61);              //reinicar cuenta desde 61
}

void main ()
{
   lcd_init () ;                                // Inicializamos pantalla LCD
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);   //configuracion del timer0
   set_timer0 (61);                             // interrupción cada centésima
   enable_interrupts (INT_TIMER0);              //habilita interrupcion de timer0
   enable_interrupts (GLOBAL);                  //todas las interrupciones activadas
  
   printf (lcd_putc, "\f***CRONOMETRO***") ;    // Mandamos mensaje por única vez
  
   WHILE (true)
   {
      lcd_gotoxy(2,2);
      Printf(lcd_putc,"Tiempo %02u:%02u",minutos, segundos);
    }
}
      
  



7. TAREA A SER EVALUADA:
A partir del código mostrado, realice los cambios necesarios para realizar un programa que CUENTE EN FORMA DESCENDENTE, (temporizador regresivo), bajo  las siguientes condiciones:

a. Al presionar pulsador en D0, incrementar en 1 MINUTO y el pulsador E0, incrementa. el temporizador aún no debe estar contando el tiempo. (sirve para configurar tiempo de cuenta).
b. Al presionar pulsador en D1, iniciar CUENTA REGRESIVA desde los minutos previamente configurados.
c. Si la cuenta llega a 00:00, congelar la cuenta y sonar BIP 3 veces.

Para verificar que una variable de tiempo (digamos “minutos”) llegó a cero, hacerlo con la instrucción “if (minutos==-1)”

     
#include <16f877a.h>             // Incluimos archivo con PIC a utilizar
#device adc=8                    // Utilizamos 8 bits de RESOLUCIÓN de lectura
#use delay (clock=20M)           // Indicamos al compilador que trabajaremos a 20Mhz
#fuses HS, NOPROTECT, NOWDT      // Configuración básica de los fusibles

#define LCD_ENABLE_PIN        PIN_D3   //Definimos los pines a ser utilizados por la
#define LCD_RS_PIN            PIN_D2   //pantalla LCD
#define LCD_RW_PIN            PIN_A0  
#define LCD_DATA4             PIN_D4
#define LCD_DATA5             PIN_D5
#define LCD_DATA6             PIN_D6
#define LCD_DATA7             PIN_D7 
#include <lcd.c>                 // Incluimos librería para manejar Pantalla LCD

int centesimas=0,segundos=0,minutos=0;
int i=0,z=0;
int enclave=0;
int habilitador=0;

void BIP()
{
  FOR (i=0;i<=100;++i)
  {
    output_high(PIN_E1);    // Pone a "1" el pin E1 (envía 5 voltios)
    delay_ms(1);
    output_low(PIN_E1);     // Pone a "0" el pin E1
    delay_ms(1);
  } 
}

#int_TIMER0                      // FUNCION DE INTERRUPCION POR
void TIMER(VOID)                 // DESBORDAMIENTO DEL TIMER 0
{
  IF (!input(PIN_D0))
      {
         minutos++;
         while (!input(PIN_D0))     // Rutina ANTIRREBOTE por software
         {}
      }
  IF(!input(PIN_E0)& (segundos<55))
      {
         segundos = segundos + 5;
         while (!input(PIN_E0))     // Rutina ANTIRREBOTE por software
         {}
         IF(segundos>=55)
         {
            segundos=59;
         }
      }
 
  IF(!input(PIN_D1))
  {
  habilitador=!habilitador;
  }
   if(habilitador==1){
   ++centesimas;                 // incrementar una centésima
   if (centesimas>99)
      {
      --segundos;                // si llegamos a 100, incrementar un segundo
      centesimas=0;
      }
   if (segundos==-1)
      {
      --minutos;                 // si llegamos a 60, incrementar un minuto
      segundos=59;
      }
   if (minutos==-1 && enclave==0)
      {
       minutos=0;
       segundos=0;
       FOR (z=0;z<=2;z++)
       {
        BIP();
        delay_ms(500);
       }
        enclave=1;
        disable_interrupts (INT_TIMER0);
      }
    }
    set_timer0 (61);              //reinicar cuenta desde 61
}

void main ()
{
   lcd_init () ; // Inicializamos pantalla LCD
   minutos = 00;
   segundos = 00;
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);   //configuracion del timer0
   set_timer0 (61);                             // interrupción cada centésima
   enable_interrupts (INT_TIMER0);              //habilita interrupcion de timer0
   enable_interrupts (GLOBAL);                  //todas las interrupciones activadas
  
   printf (lcd_putc, "\f***CRONOMETRO***") ;    // Mandamos mensaje por única vez
  
   WHILE (true)
   {
      lcd_gotoxy(2,2);
      printf(lcd_putc,"Tiempo %02u:%02u",minutos, segundos);
    }
}

8. EVIDENCIA DE TRABAJO EN LABORATORIO:



Link del video: https://youtu.be/zLBit0xiogc

9. OBSERVACIONES:
  • Se mostraba en el LCD valores como 256, 128 entre otros; sucediendo cuando se realizó las condiciones dentro del bucle void main y cuando superaba el valor escrito en la programación al no tener un límite.
  • Es importante tener habilitado la interrupción global, ya que si no está activada y la específica si, no se dará su ejecución correcta, debido a que la global tiene control sobre toda interrupción.
10. CONCLUSIONES:
  • La interrupción de Timer0 trabaja con un registro de valor de 256 (0-255), el cuál es configurable para que se obtengan tiempo más aproximados al que se estima o requiera.
  • El set timer (61) toma ese valor del registro de 256 para iniciar la cuenta desde 61 hasta 255, por medio de este conteo progresivo y cíclico se obtuvo el valor de las centésimas, que al ir cumpliéndose cada ciclo incrementaba los segundos y progresivamente los minutos.
  • Se llama interrupción a aquello que hace cambiar la dirección de la atención (en este caso del microcontrolador PIC), así sea sea por un tiempo mínimo, se les emplea cuando se requiere ejecutar una acción prioritaria.
  • Se puede realizar tanto un conteo ascendente como descendente, siendo la diferencia en los segundos y minutos; las centésimas continuarán su cuenta normal (ascendente) al completar su cíclo en el conteo ascendente incrementará un segundo, pero en caso del descendente disminuirá en uno. Para los minutos, cada vez que los segundos tengan el valor de 59 su valor incrementa en uno y cuando llegase a 0 disminuirá.
  • Las interrupciones citadas se pueden habilitar y deshabilitar cuando se requiera, por ende es necesario saber en que momento se debe cambiar de estado.
  • Se puede introducir valores prestablecidos para mostrar en la pantalla LCD, antes de la citación de la reserva de espacios para cada valor.