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