Gracias por visitar este blog dedicado a la programación de microcontroladores PIC, En esta ocasión veremos como trabaja el modulo conversor analógico a digital (ADC) de un PIC16F, tomaremos como ejemplo el microcontrolador PIC16F887.
El objetivo de esta sección es poder utilizar este modulo para capturar las señales continuas provistas por una gran variedad de sensores del tipo analógico, los cuales permiten medir magnitudes de presión, temperatura, humedad, luminosidad, ruido, etc presentes en nuestro medio.
La programación se realizara utilizando el software MPLABX y el compilador XC8, ambos disponibles para descarga gratuita en la pagina oficial de microchip: https://www.microchip.com/
Introducción al modulo ADC.
Muchas de las señales eléctricas que se obtienen mediante sensores o transductores poseen una naturaleza analógica, es decir son del tipo continuo y toman infinitos valores a lo largo del tiempo. El interés por convertir una señal analógica en un valor digital surge por varios motivos y necesidades que pueden resumirse en Almacenar, Procesar y Transmitir la información.
Los convertidores ADC son dispositivos electrónicos que establecen una relación biunívoca entre el valor de la señal en su entrada y un número digital obtenido en su salida. La relación se establece en la mayoría de los casos, con la ayuda de una tensión de referencia, existen varias técnicas utilizadas para la conversión que determinan la categoría o tipo de convertidor, algunos ejemplos son:
- Conversión directa FLASH. Utiliza un comparador para cada rango de voltaje decodificado, aunque la conversión rápida, normalmente la resolución no pasa los 8 bits debido a la gran cantidad de comparadores que se necesitan.
- Delta-Sigma. Compuesto por la combinación de un conversor FLASH y filtros que eliminan la señal de ruido no deseada e incrementan la resolución de salida.
- Codificación Delta. Utiliza un contador asociado a un DAC(convertidor Digital-Analógico) la salida del DAC es comparada con la señal de entrada para determinar el valor, estos convertidores poseen rangos amplios y alta resolución, pero el tiempo de conversión depende del nivel de la señal de entrada.
- Comparador tipo Rampa. También conocido como integrador o doble rampa, porque utiliza una señal diente de sierra para efectuar la comparación y captura de la entrada, estos convertidores requieren una menor cantidad de transistores y comparadores pero son sensibles a la temperatura debido a las variaciones del oscilador.
- Aproximación Sucesiva. Utiliza un comparador para rechazar rangos de voltaje en forma sucesiva hasta encontrar el valor final, realizan una búsqueda binaria donde la primera comparación debe decidir cual es bit mas significativo de la salida, luego la siguiente comparación decide el siguiente bit y así hasta llegar al bit menos significativo, poseen una buena velocidad y resolución.
Los PIC16F de gama media incorporan un módulo ADC de aproximaciones sucesivas con una resolución de 10 bits, es decir puede cuantificar una señal analógica en 1024 posibles valores, el modulo ADC de un PIC utiliza varios canales designados como ANx que están asociados a un pin de entrada, por ejemplo en el PIC16F887 cuenta con 13 canales distribuidos de la siguiente manera:
Fig1. Canales ANx asociado a pines E/S |
La configuración del modo se realiza mediante los registros ANSELH:L descritos a continuación:
Fig2. Registro de configuracion ANx |
Nota. Los PIC16F87x y algunos otros modelos mas antiguos no llevan registros ANSEL, en su lugar utilizan unos bits PCFG en el registro ADCON1.
Fig4. Formato del resultado binario |
La conversión digital se realiza dentro de las referencias establecidas en la configuración del modulo, por defecto estas referencias corresponden con valores de GND para la referencia negativa y VCC para la positiva, pero es posible utilizar referencias externas a través de los pines AN2/VREF- y AN3/VREF+. La configuracion de la referencias del modulo ADC permiten determinar la sensibilidad de cambio por cada bit aplicando la siguiente formula:
El uso de voltajes de referencia externas posibilitan una mejor adaptación del conversor ADC a las características de sensor a medir, pero esta configuracion debe ser realizada conforme a la hoja de datos proporcionado por el fabricante. En el caso del PIC16F887, con relación a este punto la sección 17, tabla 10, parámetro AD06 indica que el voltaje de referencia mínimo es de 2.7V.
La configuración inicial del modulo se realiza mediante los registros ADCON0:1 a continuación se muestra la descripción de los bits que por defecto están con un valor 0.
Fig5. Registros de configuración ADC |
La siguiente figura describe el tiempo de conversion total desde que se mide la magnitud de la señal analógica hasta que se obtiene el numero binario de 10-bits.
Fig6. Tiempo de conversion total |
- TAMP. Tiempo de ajuste del amplificador, el valor se indica en la hoja de datos, el PIC16F887 posee un valor nominal de 2uS y un máximo de 5uS.
- TC. Tiempo de carga del condensador de retención(CHOLD), que se calcula en base al modelo del circuito de entrada descrito a continuación:
Fig7. Modelo de la entrada ADC |
Fig8. Valor de resistencia de muestro Rss |
- TCOFF. Coeficiente de Temperatura es calculado con la siguiente ecuación:
Ahora nos queda definir los valores de la impedancia de entrada RS y la temperatura de ambiente TAMB, pero estos valores no son fijos porque el sensor o transductor conectado a la entrada no mantendrá fija la impedancia salvo que siempre se mida un valor constante y pasa lo mismo con la temperatura del ambiente, por esa razón se definen limites de operación máximos de ambos.
Tiempo de Conversión: Cuando el condensador de retención esta cargado es posible dar inicio a la conversión, para esto se deberá desconectar la entrada analógica e iniciar la secuencia de captura con el bit mas significativo hasta completar los 10 bits, en total el tiempo de conversión toma 11xTAD.
La espera de este tiempo se apoya en uso de bits ADIF y GO que indican el final de la conversión.
Tiempo de Espera:Se debe esperar un tiempo de 2TAD, después de completar la conversion, o cuando el proceso finalice antes de completar la conversion, en este tiempo el condensador de retención permanece desconectado de la entrada.
La figura 9 muestra el esquema de circuito utilizado en el desarrollo de nuestro del programa para el PIC16F887, con el objetivo de llevar a cabo mediciones de voltaje utilizando el modulo ADC, El esquema esta simplificado para mostrar únicamente las conexiones a los canales AN0/AN3 y los pines de comunicación TXD/RXD, se da por hecho las conexiones requeridas para la operación del microcontrolador, como ser fuente de alimentación, circuito de reinicio y programación..
El canal AN0 tendrá conectado un potenciómetro variable de 10k, actuando como un divisor de tensión controlado manualmente. El canal AN13 estará conectado a un MCP1700A, que es un sensor lineal de temperatura, teniendo como valor de salida 500mV a 0 °C (grados centígrados), y una sensibilidad de 10mV/°C.
Fig9. Esquema del circuito |
La configuracion utilizara los voltajes de referencia por defecto que son VCC y GND, con esta condición y considerando los 10 bits que tiene el ADC del PIC, la sensibilidad en mV por bit se calcula como: (Vref+ - Vref-) / 2^10-bits = (5V - 0V) / 1024 = 4.88 mV.
Por otro lado la comunicación serial con la PC, utiliza un convertidor USB a UART, en nuestro caso es un CP-2102, pero puede ser cualquier otro conversor, ya que solo requiere un par de conexiones a los pines TXD y RXD del PIC16F, a través de este medio se enviara un mensaje cada segundo con el resultado digital producto de la conversion realizada a los dos canales del circuito.
Configuración y Lectura de datos.
Con todo lo visto hasta este punto, pondremos en practica mediante la programación, la configuracion y uso del modulo ADC del PIC16F887. Los procedimientos y funciones utilizados se encuentran en un solo archivo main.c por lo que describiremos su estructura al inicio utilizando comentarios dentro de la codificación.Inicialmente se describe el procedimiento de configuración de los puertos, y los modulo requeridos para las siguientes operaciones:
- Modulo ADC: Para la captura de señal analógica provenientes de un divisor de tensión y un sensor de temperatura.
- Modulo USART: Utilizado para enviar la informacion con el resultado de las lecturas para el divisor y sensor de temperatura
- Modulo TIMER0: Permite el control de tiempo mediante interrupciones.
{
while(OSCCONbits.HTS == 0) {};
ANSEL = 0; //Desactiva los canales AN0-7
ANSELH = 0; //Desactiva los canales AN8-13
TRISAbits.TRISA0 = 1; //Pin RA0/AN0 como entrada
TRISBbits.TRISB5 = 1; //Pin RB5/AN13 como entrada
ANSELbits.ANS0 = 1; //Activa canal AN0
ANSELHbits.ANS13 = 1;//Activa canal AN13
ADCON0bits.ADCS = 0b01; //TAD=2us (Fosc/8)
ADCON0bits.ADON = 0; //Desactiva el modulo ADC
/* CONFIGURA USART A 9600 BPS*/
BAUDCTLbits.BRG16 = 0; //8-bit BaudGen
TXSTAbits.BRGH = 1; //Alta del Generador
TXSTAbits.TXEN = 1; //Activa el transmisor
RCSTAbits.SPEN = 1; //Habilita el modulo USART
SPBRG = 25; //Formula [4M/(16 * 9600)] - 1
/* CONFIGURACION TIMER0 1MS*/
OPTION_REGbits.T0CS = 0;//Modo Termporizador
OPTION_REGbits.PSA = 0; //Con prescala
OPTION_REGbits.PS = 0b010; //Prescala 1:8
TMR0 = 130; //255-(time/((pre)*(4/Fosc))) time=0.001s
INTCONbits.T0IF = 0; //Limpia bandera
INTCONbits.T0IE = 1; //Activa interrupción del TMR0
INTCONbits.GIE = 1; //Habilita las interrupciones
El código descrito a continuación corresponde a la función que permite realizara la lectura del canal analógico seleccionado, el resultado es un numero entero de 16-bit de los cuales solo 10-bit corresponden con la magnitud medida.
{
unsigned int res;
ADCON0bits.ADON = 1; //Activa el ADC
_delay(12); //Espera tiempo de Adquisición 11.5 us.
ADCON0bits.GO = 1; //Inicia conversion
while(ADCON0bits.GO) {}; //Espera fin de conversion
res = ADRESH; //Recupera los 8-bits de mas peso
res = res << 8; //Desplaza 8 bits a la izquierda
res = res | ADRESL; //Recupera los 2-bits de menor peso
res = res >> 6; //Desplaza 6 bits a la derecha
ADCON0bits.ADON = 0; //Desactiva el ADC
return res;
}
También se describe el código de la rutina de interrupción ISR en la que se observa el control de eventos por milisegundo utilizando el modulo TMR0.
void __interrupt() isr() //Rutina de interrupción
{
if(INTCONbits.T0IF) //Activa cada 1ms
{
tick1ms = 1; //Activa bandera 1ms
INTCONbits.T0IF = 0; //Limpia bandera
TMR0 = 130; //Reinicia contador
}
}
void putch(char byte) //requerido por <stdio.h>
while(PIR1bits.TXIF == 0) {};
TXREG = byte;
}
En este punto debemos contar con un circuito físico ya implementado para nuestras pruebas, también es posible utilizar un simulador como ISIS Proteus.
En particular he preferido llevar a cabo las pruebas en circuito físico utilizando una placa de pruebas y efectuado las conexiones mínimas sobre la misma, tal como se observa en la figura 10.
Fig10, Circuito de prueba PIC16F |
Tomaremos el siguiente circuito como ejemplo para hacer la lectura de dos potenciómetros conectados a los canales AN0 y AN13, el resultado de la conversion se enviara al puerto seria como un mensaje cada segundo.
Entonces el procedimiento principal de programa, sera el siguiente código
#include <xc.h>
#include <stdio.h>
unsigned int adres1, adres2, onesec = 0;
volatile char tick1ms;
void main()
{
setup();
while(1)
{
if(tick1ms == 1) //Verifica bandera de 1ms
{
tick1ms = 0; //Limpia bandera de 1ms
onesec++; //incrementa contador de ms
if(onesec > 999) //Se cumple cada segundo
{
onesec = 0; //Limpia contador
ADCON0bits.CHS = 0; //Selecciona Canal 0
adres1 = ADCRead(); //Lectura ADC
ADCON0bits.CHS = 13; //Selecciona Canal 13
adres2 = ADCRead(); //Lectura ADC
printf("AN0:%u AN1:%u\r\n", adres1, adres2);
}
}
}
}
Fig11. Mensajes recibidos por la terminal serial |
Como analisis de la informacion que muestra la terminal, se describe el siguiente resultado:
El canal 0, producto de la variación manual aplicado al potenciómetro va desde un mínimo AN:0 hasta un máximo AN;1022.
El canal 13, que en este caso se muestra como AN1 se observa un valor casi constante de AN1:165, este valor considerando la sensibilidad de 4.88mV/bit equivale a un voltaje de 806mV (165 * 0.00488). Ahora bien si el canal 13 tiene conectado un sensor de temperatura, ¿Que representa este resultado de 806mV?. Para responder esta cuestión sera necesario conocer las características del sensor, en este caso el MCP9700A, es un sensor lineal de temperatura con las siguientes características resumidas de la hoja de datos:
- Rango de operación de -40°C a +150°C,
- Relación de salida de 10mV/°C
- Voltaje de salida a 0°C de 500mV.
Se debe tomar en cuenta lo siguiente:
- El voltaje de referencia no debe ser inferior a 2.7V, ver hoja de datos;
- El tiempo de adquisición por bit TAD, se ajusta de acuerdo a la frecuencia de operación y el rango sera de 1.6 - 6us, ver hoja de datos;
- La impedancia de salida de la fuente de señal analógica no debe superar los 10k.
Sin mas que mencionar agradezco tu visita al blog y espero que el ejemplo visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atte. Pablo Zárate Arancibia
email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia