lunes, 24 de octubre de 2011

Convertidor A/D con pic16f887 y LCD JHD 162A (PIC C CCS)

Pequeño pero practico programa para usar el convertidor Analogico - Digital por medio del Pic 16f887 y una pantalla lcd de 16x2


Codigo:

#include <16f887.h>                   //Nuestro pic
#device adc = 10                       //Convertidor AD a 10bits
#use delay (clock=8000000)            //Fosc=8Mhz
#include <lcd.c>                      //Libreria de la lcd

//Declaracion de variables publicas
//int bits_frecuencia;
//int bits_dutyCicle;
float Frecuencia;
float DutyCicle;

//Prototipos de Funciones
void Refresh_lcd();
float Get_Lectura(int channel);



void main()
{
   setup_oscillator(OSC_8MHZ|OSC_INTRC);  //Programamos oscilador interno del Pic a 8MHZ
   set_tris_b(0);                         //Puerto B como salida
   lcd_init();                            //Inicializamos LCD
   lcd_putc("Iniciando...");                //"Hola Mundo"
   DutyCicle = 0.0;
   Frecuencia = 0.0;
   delay_ms(5);
   
   while(1)
   {
      output_toggle(PIN_B5);              //Parpadeamos Led, output_toggle cambia el estado logico del pin pasado de parametro
      
      Frecuencia = Get_Lectura(0);
      DutyCicle = Get_Lectura(1);
      
      Refresh_lcd();
      
      delay_ms(250);                     //Esperamos a lo sonso 250 ms
   }
}


float Get_Lectura(int channel)
{
   float medicion=0;                     //variable entera que contendra la medicion del convertidor AD
   int1 done = 0;                        //Contendra 1 si el convertidor terminó de convertir
   
   setup_adc (adc_clock_internal);     //Usando el oscilador interno 
   setup_adc_ports (all_analog);       //Todo el puerto analogico como entrada analogica    
   set_adc_channel (channel);          //Establecemos el canal de lectura analogica
   delay_ms(1);                       //a small delay is required after setting the channel
   medicion=read_adc ();               // Hace conversión AD 
   done = adc_done();                  //done = 1 si el convertidor termino de convertir
   while(!done)
   {
      done = adc_done();               //Mientras no acabe de convertir se seguira ciclando
   }
   setup_adc (adc_off);                //detenemos al convertidor
   return medicion;                    //Regresamos la medicion
}

void Refresh_lcd()
{
   lcd_putc("\f");
   printf(lcd_putc,"Frec: %5.1f",Frecuencia);
   lcd_putc("\n");
   printf(lcd_putc,"DC: %5.1f",DutyCicle);
   
}



Esquematico:

Esquematico para el 16f887


Descargas:

DSN Isis Proteus: dsn
Codigo para Pic C de CCS: codigoC
xadecimal para Pic: hexa

_________________________________________________________________________________
USANDO EL PIC16F877A

El PIC16f887 es mas nuevo, mas barato y con unas cuantas mejoras con respecto a su compatriota algo ya anciano el PIC16f877X dígase también PIC16f877A.

Bueno, pero parace ser que muchos siguen usando estos ultimos PIC, por ello y por petición en un comentario en esta entrada he decidido ampliar este ejemplo usando un 16f877a.

Aquí está chan chan chan:

(La única diferencia en el código es comentar la línea 20 "setup oscillator()", porqué? porque el PIC 16F877A no la soporta ya que NO POSEE OSCILADOR INTERNO, solo es cuestion de ver la datasheet y el .h del PIC)

Esquemático:

Esquematico para el 16f877a


DSN Isis Proteus: dsn
Codigo para PicC de CCS: codigoC
Hexadecimal: hexa

15 comentarios:

  1. donde puedo conectar un aparato para medir su voltaje ?

    ResponderEliminar
  2. como hago para que ese mismo circuito me pueda medir el voltaje de de entrada y me lo de en la LCD

    ResponderEliminar
    Respuestas
    1. Es el mismo circuito, colocas la terminal de donde deseas medir el voltaje (0V-5V) a uno de los pines de entrada del ADC

      Multiplicas lo que te arroje el ADC por el factor correspondiente y listo.

      El factor no es mas que una regla de 3, para el convertidor de 10bits (1023 unidades)usado en este ejemplo:

      factor = (5V / 1023 unidades) = 0.00488 V/unidades

      por tanto:

      Voltaje medido = factor * unidades del ADC

      Ejemplo (se obtienen 1000 unidades)

      Voltaje medido = (0.00488 V/unidades) * 1000 unidades
      Voltaje medido = 4.88V

      You get it?

      Saludos

      Eliminar
  3. no puedo usar el programa en el pic16f877a como hago para que funcione en ese pic

    ResponderEliminar
    Respuestas
    1. Saludos Hans Rojas, el pic que mencionas es exactamente el mismo (no tan exactamente pero debería funcionarte, en serio!!!).

      Apuesto a que anda un cable suelto por allí.
      Suerte

      Eliminar
  4. Nada mi hermano, ni cuando lo simulo en proteus me sale iniciando, y cuando quiero quemar el archivo hexa en el pic16f877a sale un warming

    ResponderEliminar
    Respuestas
    1. En esta otra entrada alguien menciona algo parecido
      http://hzsquare.blogspot.fr/2011/10/hola-mundo-con-pic16f887-y-lcd-jhd-162a.html

      Anónimo17 de septiembre de 2012 23:44
      No se si fue porque yo utilice otro pic(16f886) pero tuve que definir los pins en el archivo lcd.c
      // define the pinout.
      // only required if port access is being used.
      #define LCD_ENABLE_PIN PIN_A0 ////
      #define LCD_RS_PIN PIN_A1 ////
      #define LCD_RW_PIN PIN_A2 ////
      #define LCD_DATA4 PIN_A4 ////
      #define LCD_DATA5 PIN_A5 ////
      #define LCD_DATA6 PIN_A6 ////
      #define LCD_DATA7 PIN_A7

      de otro modo solo me salian cuadritos. pero me ayudo mucho tu tutorial, saludos!

      Pero acabo de revisar y los dos pic tienen el mismo PIN OUT, no debería salirte el error

      Eliminar
    2. Añadí una parte de interes a esta entrada, checala y comentas.

      Saludos

      Eliminar
    3. Orales, está bueno el blog,

      estoy empezando con esto de los pics no soy muy bueno pero poco a poco voy aprendiendo algo nuevo.
      gracias por enseñarnos lo que sabes :)
      voy a tratar de cambiarlo por un PIC 18f4550 no se si es sencillo o complicado, pero are el intento, para empezar creo que revisare los datasheet creo que es un buen inicio

      Saludos

      Eliminar
    4. regresando a este blog despues de hacer una revisión rápida, arme el cto con el pic 18f4550 y fue más fácil de lo que me esperaba, eh aprendido algo el día de hoy wiiiiiiii, estoy feliz :)

      Gracias de nuevo me gusta tu blog :)

      Eliminar
  5. Con el cambio del oscilador si funciona gracias por el aporte, saludos.

    ResponderEliminar
  6. COMO PUEDO COLOCAR NUMEROS DECIMALES EN EL LCD

    ResponderEliminar
    Respuestas
    1. Hola Camilo Soto.

      A que te refieres con Números decimales?
      Si deseas por ejemplo que un numero flotante 32bits (ya sea con parte entera cero ejem 0.1416 con parte entera mayor a cero ejem 3.1416)
      que pueda ser expresado en la LCD solo ocupas cambiar la manera en que imprimes en la LCD:

      printf(lcd_putc,"Frec: %5.1f",Frecuencia);
      En la linea anterior del codigo %5.1f nos indica que ocupas 5 digitos enteros y 1 digito "decimal".

      Asi por ejemplo, el numero 93648.047476083020973716690184919 (el cual viene de pi^10) daria en la LCD:
      "Frec: 93648.0".
      Si lo cambiaras a %5.3f
      "Frec: 93648.0474"

      Espero eso conteste a tu pregunta.

      (ref: p37 y p189 https://www.ccsinfo.com/downloads/ccs_c_manual.pdf)

      Eliminar
  7. Que tal. Estoy trabajando con la pic16f887. Al querer compilar el ejercicio con salida del sensor LM35 y dos voltajes (mediante divisor de voltaje) en diferentes puertos (Utilizando solo el Puerto A para todos) y visualizarlo en una pantalla LCD me sale el error UNDEFINED IDENTIFIER AN0_AN1_AN3 en la linea de código que tengo setup_adc_ports(AN0_AN1_AN3); . Era para que me diera una orientación con respecto a esto.

    ResponderEliminar