Ejemplo ADC

Cite varios ejemplos de como jugar con el puerto analogico y note que me faltaba algo.... Hay un tema muy importante a todo esto, que es la configuracion del puerto analogico y del funcionamiento en si de este en nuestro programa.... sin la previa configuracion de estos registros y declaraciones, el microcontrolador no funciona correctamente... veamos las funciones y registros de los que hablo y tengan en cuenta que los registros cambian segun el microcontrolador a emplear (ver siempre la hoja de datos)

DEFINE ADC_BITS 8               ;Definir el número de BITS en el resultado (8, 10 o 12)

DEFINE ADC_CLOCK 3             ;Definir EL CLOCK (RC = 3)

DEFINE ADC_SAMPLEUS 50      ;Definir el tiempo de muestreo en microsegundos

Por ejemplo:

ADCON0 = %11000001    ; ADCON0 controla la operación del módulo A/D

 

significa:

Bit 7-6: clock del ADC es RC.

Bit 5-3: canal analógico 0. (AN0.)

Bit 2: bit de estado de conversión. 0 significa que la conversión no está en progreso.

Bit 1: no se usa.

Bit 0: 1 significa inicio de operación del módulo A/D.

 

ADCON1 = %00001110   ;configuración de las funciones de los pines de los puertos del A/D

significa:

Bit 7: 1 es justificación a la izquierda.

Bit 6-4: no se usan.

Bit 3-0: solo un canal analógico, V de referencia + es VDD y V de referencia – es VSS.

Con este ultimo registro, no solo configuramos los puertos como analógicos o digitales, si no que tambien el uso o no de voltaje de referencia externo.

Para conocer un poco mas como funcionan los registros de cada PIC, nunca esta de mas tener la hoja de datos a manos... anexo un articulo del amigo ricardo, donde nos muestra como trabaja en los pic de la familia 16F87X.

 Ahora vamos a la practica; Tomemos como ejemplo el ADC de los micros de la series 16F873/76/77 que se puede trabajar en 8 o 10 bits.

El valor leído por el puerto analogico debe ser multiplicado por la resolución para obtener el valor analógico que se está capturando.

Por ejemplo:

Valor Analogico= ADCIN x ADC_resolución

donde

 

ADC_resolucion= Vref/2numbits

 Vref/1024 (en caso de ser 10bits)

 Vref/256 (en caso de ser 8 bits)

tomando como ejemplo una referencia de 4,88v, mas simplificado seria algo asi

ADC_resolucion= 4,88/1024 = 0,004765625 osea 4,7mV

o sea, si el sensor trabaja de 0 a 5V (4,88V), cada paso ira de 4,7 en 4,7 milivoltios. Si deseas hacer la inversa, un regla de tres te ayudara facilmente a saber cualquier incognita...

Por ejemplo Vref =  0,004765625 * 1024 = 4,88V

Para aplicarlo en un proyecto, ya tenemos los datos mas relevantes... Vref y ADC_resolucion, entonces la operacion seria:

ADCIN 0, LECTURAadc

TEMP1 = 488 * LECTURAadc   ; (4,88v * LECTURAadc)

LCDOUT $fe,1,"CONV. ADC = ",DEC LECTURAadc

LCDOUT $fe,$c0,DEC2 LECTURAadc

Queres mas resolucion en el display?

LECTURAadc VAR WORD

VAL VAR WORD

TEMP1 VAR byte

ADCIN 0, LECTURAadc

TEMP1 = 488 * LECTURAadc                       ; 1024*488=499712

VAL = DIV32 10

LCDOUT $fe,1,"CONV. ADC= ",DEC VAL DIG 3,DEC VAL DIG 2,".",DEC VAL DIG 1, DEC VAL DIG 0,$DF,"C"

Vamos a otro ejemplo mas completo... vamos a leer un sensor de temperatura LM35 y veremos ese dato en el display; Como adicional, implementaremos el dato de grados enteos, para controlar las salidas del puero D, y que estas se enciendan cada 5 grados secuencialmente.

'**************************************************************************************

'*  Name    : Plantella1.PBP                                         

'*  Author  : [Alejandro Martin Torres - prof.martintorres@educ.ar]  

'*  Notice  : Copyright (c) 2015 [ETI - Educación Técnica Informal]  

'*          : All Rights Reserved                                    

'*  Date    : 11/10/2015                                             

'*  Version : 1.0                                                    

'*  Notes   :                                                        

'***************************************************************************************

define osc 4                    ; definimos la velocidad del oscilador en 4 mhz

;===============================================================

;seteo de entradas y salidas...

;===============================================================

;Con TRIS configuramos quienes se comportan como salidas (0) o entradas (1)

TRISA = %11111111               ; Todo el puertoA se comporta como entrada

TRISB = %11111111               ; Todo el puertoB se comporta como entradas

TRISC = %00000000               ; Todo el puertoC se comporta como salida

TRISD = %00000000               ; Todo el puertoC se comporta como salida

CMCON=7

ADCON1=%10001110         ; definimos puerto 0 como analogico

Define    ADC_BITS    10             ' Establece el número de bits en el resultado

Define    ADC_CLOCK    3             ' Ajuste el reloj de origen (rc=3)

Define    ADC_SAMPLEUS    100         ' Establezca el tiempo de muestreo en uS

;=============================================================

;Definicion de variables y puertos

;=============================================================

P_ADC_0 var portA.0   ; nombramos al puerto A.0

 

boton1 var portB.0

boton2 var portB.1

boton3 var portB.2

boton4 var portB.3

boton5 var portB.4

boton6 var portB.5

boton7 var portB.6

boton8 var portB.7

; el puerto C lo vamos a usar para controlar el display LCD

DEFINE LCD_DREG      PORTC       ;bus del LCD DB4-DB8 - portC.4 en adelante

DEFINE LCD_DBIT      4       

DEFINE LCD_RSREG  PORTC       ;pin RS LCD conectado a portC.2

DEFINE LCD_RSBIT  2   

DEFINE LCD_EREG      PORTC       ;pin E lcd conectado a portC.3

DEFINE LCD_EBIT   3       

DEFINE LCD_BITS      4                    ;control del LCD en modo 4 bits

DEFINE LCD_LINES  2                     ;display lcd de 2 lineas

; el puerto D lo vamos a usar como salida (ver TRISD que esta en -0-)

salida1 var portD.0

salida2 var portD.1

salida3 var portD.2

salida4 var portD.3

salida5 var portD.4

salida6 var portD.5

salida7 var portD.6

salida8 var portD.7

ADVAL VAR WORD

SUM VAR WORD

DIV_10 VAR WORD

N VAR BYTE 

ENTERO VAR BYTE

DECIMAL VAR BYTE

AUX VAR BYTE

portd=0

;*****************************************************************************

;************************  PROGRAMA PRINCIPAL    ***********************

;*****************************************************************************

LECTURA:

pause 100

LCDOUT $FE,1

LCDOUT $FE,$80,"LM35 ADC.0"

LCDOUT $fe,$C0,"Temp: ",dec2 entero,",",dec decimal

gosub leer

gosub salida

if boton7 = 0 then

    gosub borrarlcd

    LCDOUT $FE,$80,"retornamos al"

    LCDOUT $fe,$C0,"menu inicio"

    pause 1500

    gosub inicio

    endif

    

goto lectura

leer:

 Sum = 0

   For N = 1 to 64                         ' efectuamos 64 lecturas y las sumamos

      adcin 0, ADVal

      Sum = Sum + ADVal

   Next

   ADVal = Sum / 64                        ' calculamos el promedio de las 64 lecturas

   DIV_10 = ADVal * 4                    ' 4.88 * ADVal

   DIV_10 = ADval * 8 / 10 + DIV_10

   DIV_10 = ADval * 8 / 100 + DIV_10

   ENTERO = DIV_10 / 10                    ' Valor entero centrirgado

   DECIMAL = DIV_10 // 10                  ' Valor decimales centrigrados

 return 

 salida:  

if entero >= 0  and entero < 5  then high salida1

if entero >= 5  and entero < 10 then high salida2

if entero >= 10 and entero < 15 then high salida3

if entero >= 15 and entero < 20 then high salida4

if entero >= 20 and entero < 25 then high salida5

if entero >= 25 and entero < 30 then high salida6

if entero >= 30 and entero < 35 then high salida7

if entero >= 35 and entero > 35 then high salida8

pause 100

portd=0

return