En otro tutorial vimos como
el módulo PWM funcionaba como una especie de conversor digital -> analógico
(DAC). El conversor analógico-digital (ADC) que equipa a muchos
microcontroladores hace justo lo contrario, convirtiendo un voltaje analógico externo
en un número, con el que podremos operar.
Como
siempre empezaremos con una introducción sobre los fundamentos de un conversor
AD y los registros usados para su manejo en los PIC. Tras entender el proceso, presentaremos
las rutinas de C18 para el manejo del ADC y escribiremos nuestras propias
funciones, que nos permitirán optimizar el rendimiento del ADC y no depender de
un compilador en particular.
En la
siguiente entrada veremos como al igual que pasaba con el puerto serie, usando
interrupciones podemos optimizar el rendimiento del PIC mientras estamos usando
el conversor AD.
Codigo asociado a esta entrada: adc1.c
------------------------------------------------------------------------------------------
Conceptos básicos de un ADC:
- Un ADC convierte mide el voltaje V en un pin (que tendrá que estar declarado como entrada con el correspondiente registro TRISA) y lo convierte en un número. El voltaje se mide en referencia a un voltaje mínimo, Vref(-) , y a un voltaje máximo, Vref (+):
V_norm = ( V –
Vref(-) ) / (Vref(+) –Vref(-) )
- La fórmula anterior corresponde a un voltaje normalizado. Si el voltaje V alcanza el máximo (Vref+) tendremos una salida de 1 y si se queda en el mínimo (Vref-) una salida de 0.
- Normalmente Vref- suele ser Vss=GND=0V y Vref+ = Vcc = 5V, pero pueden usarse otros voltajes de referencia. Si por ejemplo queremos medir una señal que sabemos que oscila entre 2 y 3 voltios usaríamos Vref-=2 y Vref+=3. Así aprovecharíamos mejor el rango dinámico del conversor.
- Como el microcontrolador no va a manejar números en coma flotante, el voltaje normalizado se expresa con un entero, convirtiendo el intervalo real [0,1] en el intervalo de niveles enteros entre [0 y Nmax-1]. La resolución del ADC es una característica fundamental y nos dice el número de niveles con los que cubrimos el intervalo [0,1]. Por ejemplo, en los PIC solemos tener una resolución de 10 bits, que representan 2^10=1024 niveles. El intervalo real [0,1) se aplicaría al intervalo [0,1023]. Si asumimos un rango de 5V, tendremos que la resolución de cada nivel es de r=5/1024 V=4.88 mV. Según la documentación de Microchip (esto puede variar para otros microcontroladores) cualquier voltaje entre [0 y r] (o por debajo de 0, lo que corresponde a V<Vref-) se cuantificaría en el nivel 0. Entre r y 2r tendríamos una salida de nivel 1. Así hasta llegar a nivel 1023 que cuantificaría voltajes por encima de 1023r = 1023x 5/1024 = 4.995V. Como se ve, voltajes por debajo de Vref- o por encima de Vref+ son posibles y se cuantifican como nivel mínimo 0 o máximo, 1023. Niveles por debajo de 0V o por encima de la tensión de alimentación (normalmente 5V) pueden ser dañar el PIC.
Nivel
|
Voltaje
|
0
|
<r
|
1
|
[r,2r]
|
2
|
[2r,3r]
|
…
|
…
|
1023
|
>1023r
|
- Aunque un PIC puede tener del orden de 8-12 posibles canales (pines) de entrada analógica, solo tiene normalmente un único módulo ADC, lo que significa que no podemos tomar medidas simultáneas de varios canales. Si es necesario, lo que podemos hacer es ir conectando (seleccionando) los sucesivos canales al ADC para ir midiendo sus voltajes.
- El proceso de una conversión ADC se divide en un tiempo de adquisición Ta (durante el cual un condensador interno se carga al voltaje exterior) y un tiempo de conversión Tc (durante el cual se desconecta el pin exterior y se cuantifica el voltaje del condensador).
- El tiempo de adquisición Ta depende de las características eléctricas del PIC (en particular de la capacidad del condensador). Si no se respeta este tiempo, el condensador no habrá alcanzado el nivel del voltaje exterior y la medida será incorrecta. Los datasheet de los PIC indican los Ta recomendados para diversas familias.
- Otro aspecto importante de la adquisición es recordar que Microchip recomienda una impedancia máxima para el sensor (o lo que sea) suministrador de voltaje que está conectado a nuestro pin. En la mayoría de los casos se recomienda que dicha impedancia no supere los 2.5 Kohmios. Según entiendo con mis escasos conocimientos de electrónica, impedancias mucho mayores harían que (debido a corrientes de pérdida siempre presentes) el condensador no llegara nunca a cargarse al voltaje de entrada o tardase mucho en hacerlo, lo que daría lugar a que la medida posterior fuese incorrecta. Si la impedancia de nuestra fuente es muy superior a la recomendada deberíamos plantearnos insertar un driver.
- El tiempo de conversión Tc depende fundamentalmente del número de bits del conversor. La unidad básica es el llamado Tad, aproximadamente el tiempo necesario para ganar un bit adicional. La conversión total tarda entre 11 y 14 Tad (contando con la descarga final del condensador para estar listo para otra medida. El reloj del ADC se debe ajustar (como una fracción del oscilador principal) para que dicho Tad no sea inferior a un valor mínimo especificado en los datasheet. Por ejemplo para la familia PIC18F252/452 el Tad mínimo es de 1.6 usec y Tc = 14 Tad. En cambio para la familia PIC18F2520/4520 tenemos un Tad mínimo de 0.75 usec y un Tc = 11 Tad.
Un
comentario final: aunque es muy conveniente tener un ADC integrado dentro del
microcontrolador, si lo pensamos en términos de nivel de ruido, etc. las
cercanías de un microcontrolador con la líneas de reloj, rápidos cambios en las
líneas digitales, comunicaciones, etc. no es el mejor sitio para ubicar un ADC.
Esto quiere decir que si estamos muy interesados en la precisión, tal vez sería
conveniente considerar un ADC aparte, que nos comunicaría los datos adquiridos a
través de SPI o similares. Una vez dicha la advertencia nos centraremos en como
usar de la forma más eficiente el ADC de un microcontrolador (en este caso un
PIC).
Los registros de control del ADC en
un PIC (familia 18F 2520/4520)
Para estos
ejemplos voy a usar código para la familia PIC18F2520/4520 con algunos
comentarios sobre la familia 252/452. El conversor AD es una de los módulos de
un PIC donde hay más diferencias entre modelos: distintos número de canales AD,
diferentes formas de programar que canales son digitales o analógicos, la
posibilidad o no de programar tiempos de adquisición, etc.
Esto hace
que la configuración del ADC sea bastante dependiente del modelo y siempre sea
bueno tener a mano la documentación ante comportamientos inesperados. Por
ejemplo, los registros asociados al puerto serie son los mismos entre una
amplia gama de dispositivos. Por el contrario, es fácil que el número de
registros de configuración cambie entre modelos.
La familia
PIC18F2520 tiene 3 registros de control asociados al ADC (ADCON0, ADCON1 y
ADCON2). Por el contrario, la familia 252/452, al tener menos funcionalidades,
sólo necesita 2 (ADCON0 y ADCON1). De todas formas, los nombres y funciones de
los bits comunes serán los mismos que los aquí descritos, aunque pueden estar
situados en diferentes registros.
Además de
los registros de control tenemos otros dos registros ADRESH y ADRESL (AD result
High/Low) donde se guarda el resultado de la conversión, pero estos si son
comunes entre dispositivos.
Veamos un
resumen de estos registros (de nuevo, los datasheet de Microchip son los
mejores manuales de usuario):
Registro ADCON0: permite seleccionar (CHS) el canal
del que tomaremos la medida. También tiene el bit que habilita el conversor
(ADON) y que arranca (GO) el proceso de conversión.
Bit #
|
Bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
Nombre
|
X
|
X
|
CHS3
|
CHS2
|
CHS1
|
CHS0
|
GO
|
ADON
|
Función
|
No usado
|
No
usado |
Selección
de canal:
desde 0 (0000) a 12 (1100) |
Lanza
ADC
|
ON/OFF
|
ADON: Encendido (1) o apagado (0) del
modulo ADC.
GO
: Se pone a 1 para iniciar el proceso de conversión. Cuando la
conversión ha terminado el módulo lo pone a 0. Así es como sabemos que podemos
recoger el resultado (en ADRESH/ADRESL)
CHS: selecciona cual de los posibles
13 canales analógicos se conecta al ADC para medir.
Registro ADCON1: dedicado a seleccionar cuales de
los posibles canales se van a usar como entradas analógicas y a programar el
uso o no de voltajes de referencia externos (distintos de los valores 0 y 5V
por defecto)
Bit #
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
Nombre
|
X
|
x
|
VCFG1
|
VCFG0
|
PCFG3
|
PCFG2
|
PCFG0
|
PCFG0
|
Función
|
No usado
|
No
usado |
Uso (1)
de
Vref (+),Vref(-) |
Reparto canales
digitales / analógicos |
VCFG1: por defecto (0) usamos Vss=Gnd=0V
como Vref-. Si es 1 se tomara como Vref-
el voltaje presente en AN2.
VCFG0: Lo mismo que el anterior pero
para Vref+. Por defecto usaremos Vdd (alimentación, típicamente 5 o 3.3V) como
Vref+. Si es 1 se usa el voltaje presente en AN3 como Vref+.
PCFG:
Posiblemente no necesitaremos todos los posibles canales analógicos.
Estos bits permiten decidir cuales de los pines se dedican a canales analógicos
y cuales permanecen como canales digitales. Los valores posibles van desde 0000
(todos analógicos) a 1111 (todos digitales).
Los
canales analógicos se denotan en la documentación como AN0, AN1, AN2, etc. Los
dispositivos con 8 canales (252/452) los reparten entre el puerto A y el E. Los
que tienen 13 canales usan también parte del puerto B (2520/4520). Mirar la
documentación, porque el orden no es consecutivo. Por ejemplo, para el 4520
Canal
|
AN0
|
AN1
|
AN2
|
AN3
|
AN4
|
AN5
|
AN6
|
AN7
|
AN8
|
AN9
|
AN10
|
AN11
|
AN12
|
Pin
|
RA0
|
RA1
|
RA2
|
RA3
|
RA5
|
RE0
|
RE1
|
RE2
|
RB2
|
RB3
|
RB1
|
RB4
|
RB0
|
Registro ADCON2: información para determinar los
tiempos Ta y Tc del conversor y la forma en la que el resultado (10 bits) se
guarda en ADRESH:ADRESL (16 bits).
Bit #
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
Nombre
|
ADFM
|
x
|
ACQT2
|
ACQT2
|
ACQT2
|
ADCS2
|
ADCS1
|
ADCS0
|
Función
|
Formato
|
No usado
|
Programación
T adquisición
|
Reloj
del ADC
|
ADFM: Formateo del resultado. El
conversor da 10 bits que se guardan en dos registros (ADRESH:ADRESL) de 8 bits,
por lo que 6 de los 16 bits estarán vacíos. Si ADFM=1 el resultado está
desplazado a la derecha, por lo que los 6 bits más significativos de ADRESH
estarán vacíos. Si es 0 se justifica a la izquierda y son los 6 bits menos
significativos de ADRESL los que están vacíos.
El caso ADFM=1 se suele usar cuando nos interesan los 10 bits. El
resultado se puede pasar a un entero de 16 bits como:
res = (ADRESH<<8)+ADRESL;
El caso
ADFM=0 se suele usar si sólo queremos los 8 bits más significativos. En ese
caso basta hacer: res = ADRESH;
ACQT: bits para la programación del T
de adquisición. Recordar que el tiempo de adquisición es el que debemos esperar
después de seleccionar (conectar) un canal al ADC mientras se carga el
condensador cuyo voltaje posteriormente mediremos. Si escogemos 000 el usuario
es responsable de la espera (de unos pocos usec, especificada en la
documentación) entre la selección del canal (poner los bits CHS adecuados en
ADCON0) y el inicio del proceso de conversión (poner a 1 el bit GO de ADCON0).
El modo
manual (000) era la norma entre familias anteriores, que de hecho no contaban
con estos bits de configuración. En la familia 2520/4520 es posible programar
dicho tiempo de espera. De esta forma tras seleccionar el canal podemos
inmediatamente lanzar la conversión (ADCON0.GO=1) y el módulo esperara el
tiempo programado antes de iniciar la conversión. Esto permite optimizar el
aprovechamiento del ADC como veremos.
El tiempo
de adquisición es la suma de varios factores, siendo los principales la
capacidad del condensador a cargar y el tiempo que tarda el amplificador del
ADC en estabilizarse. Es importante consultar el datasheet si queremos
optimizar el muestreo porque podemos encontrarnos bastantes diferencias entre
diversos modelos.
ADCS: seleccionan la velocidad del reloj del ADC como una fracción (div = 2, 4, 8, 16, 32, 64)
del reloj principal (aunque también es posible asociarlo a un oscilador RC
independiente). El inverso de la frecuencia del ADC determina el llamado Tad,
que viene a ser el tiempo dedicado a obtener cada bit del resultado:
F_ad = Fosc / div
Tad = 1/F_ad = div / Fosc
(en microsec si Fosc está en MHz)
Obviamente
deberíamos escoger un divisor bajo para obtener la frecuencia más alta (Tad más
pequeño) posible para tardar lo menos posible en cada conversión. Sin embargo
hay una limitación: el Tad no puede ser menor que un cierto tiempo mínimo dependiente
del modelo. Por ejemplo para la familia 252/452 se recomienda que Tad sea como
mínimo 1.6 usec. En cambio para la 2520/4520 podemos bajar a 0.75 usec.
Eso
significa que si tenemos un cristal de 20 Mhz, el divisor escogido sería:
1:32 si tenemos un 452, ya que Tad = div / Fosc = 32/20
Mhz = 1.6 usec = recomendado
1:16 si
tenemos un 4520 ya que Tad = div / Fosc = 16/20 MHz = 0.8 usec > 0.75 usec
recomendados
Nuestro primer programa con el ADC
El proceso
a seguir para una conversión (según se describe en la documentación de Microchip)
es el siguiente:
- Configurar el ADC con la asignación de canales (PCFG), programar el reloj del ADC (bits ADCS), seleccionar o no voltajes de referencia (VCFG), etc.
- Una vez configurado, habilitar el ADC (ADON=1)
- Escoger canal (bits CHS) a usar (el pin dado se conecta al condensador)
- Esperar (delay) Ta mientras se carga el condensador (este paso puede ser evitado programamos la espera)
- Lanzar la conversión (GO=1)
- Esperar a completar a que la conversión concluya (GO=0).
- Extraer el resultado de ADRESH:ADRESL
- Si hemos terminado con el ADC, apagarlo para reducir consumo.
Ahora que
conocemos los detalles escribiremos el primer programa para un PIC18F4520 usando
las rutinas de C18 y no tendremos dificultades en imaginar que está haciendo
cada rutina por debajo.
Las
rutinas básicas para operar en C18 con el ADC pueden verse en este código
ejemplo del manual de C18:
OpenADC(ADC_FOSC_16&ADC_RIGHT_JUST,
ADC_INT_OFF&ADC_VREFPLUS_VDD&ADC_VREFMINUS_VSS,7); // (1)-(2)
SetChanADC(ADC_CH0); // Paso 3)
Delay10TCYx(5); // Paso 4) -> delay de
adquisición
ConvertADC(); // Paso 5)
while( BusyADC()
); // Paso 6)
-> delay de conversion.
res = ReadADC(); // Paso 7)
closeADC(); // Paso 8)
Vemos que
C18 tiene casi una función para cada paso del proceso. Por ejemplo, el
compilador MikroC Pro es mucho más monolítico, lo que lo hace más simple pero
menos adaptable. En MikroC Pro, todo lo anterior se resume en una sola llamada:
res = ADCRead(0); que configura, selecciona canal 0, espera,
lanza conversión y cuando termina devuelve res.
Los
parámetros que recibe OpenADC son esencialmente los valores de ADCON0, ADCON1 y
ADCON3. Como siempre la ventaja es que damos valores a dichos registros
combinando diversas banderas más fáciles de recordar. Para aquellos
dispositivos con sólo disponen de ADCON0 y ADCON1 la función sólo usa dos
parámetros en vez de tres. Con SetChanADC seleccionamos (ADC_CH0) AN0=RA0 como
el pin cuyo voltaje vamos a medir.
Normalmente
la configuración del ADC se hace una sola vez y luego se hacen sucesivas
conversiones (posiblemente de diferentes canales). Podemos agrupar el código
anterior en una función que reciba como argumento el canal a muestrear y haga
todas las etapas (aunque como veremos más adelante, en ciertas circunstancias
es más eficiente "romper" la función para no tener una función
bloqueante):
uint16 ADC_read(uint8
ADC_channel)
{
uint16 ad_res;
SetChanADC(ADC_channel);
Delay10TCYx(5);
ConvertADC();
while(BusyADC());
ad_res = ReadADC();
return ad_res;
}
Una
llamada al código anterior mide el voltaje del canal deseado una sola vez. Si
el voltaje en el canal analógico está cambiando rápidamente, querremos muestrearlo
muchas veces por segundo para seguir sus cambios. Supongamos que queremos tomar
2000 muestras por segundo. A esto es a lo que se suele denominar una frecuencia
de muestreo de 2000 Hz. Con este ritmo, deberemos lanzar tomar una muestra cada
1/2000 seg = 0.2 msec = 200 usec/muestra.
El código
quedaría:
TRISB=0; TRISC=0; TRISAbits.TRISA0=1;
while(1)
{
PORTCbits.RC0=1; res=ADC_read(ADC_CH0);
PORTCbits.RC0=0;
PORTB=res>>2;
Delay10TCYx(250);
}
Declaramos PORTB y PORTC como salidas y RA0 como entrada.
Dentro del bucle, tras el código de la conversión, simplemente esperamos 500
usec (2500 ciclos @ 20 MHz) antes de una nueva conversión. Hemos dejado fuera
la configuración del ADC (misma línea de antes) y el apagado del módulo (porque
lo estamos usando continuamente).
Para ver
si está funcionando hemos conectado un potenciómetro en RA0 y una tira de LEDS
en PORTB, donde mostramos los 8 bits más significativos del resultado. Moviendo el potenciómetro veremos cambiar los
LEDs.
La orden
de poner RC0 a 1 al arrancar la conversión y de bajarlo al terminar es para
controlar el tiempo que tardamos. Con un
osciloscopio podríamos ver claramente el tiempo dedicado a la conversión como
la parte en la que este alta la señal del pin RC0. Como ya hemos hecho en otras
ocasiones, incluso con un simple voltímetro podemos estimar dicho tiempo de
forma bastante aproximada. En particular para este programa he medido un
voltaje en RC0 de 0.56V. El voltaje que el mismo voltímetro me da para Vcc es
de 4.86V. El voltaje medido en RC0 dividido por 4.86 representa el porcentaje
en el que RC0 está en alto del total del periodo. Por lo tanto podemos escribir
que si t es el tiempo dedicado a la conversión entonces:
t / (t + 500) = fracción de tiempo en alto = 0.56/4.5
= 0.11 (11%)
Despejando
obtenemos un valor aproximado para t de unos 60 usec.
Obviamente
esto funcionará cuando el periodo sea lo suficientemente rápido para que el
voltímetro responda con el valor medio del voltaje a lo largo del periodo.
La captura
de la izquierda muestra varios pulsos de conversión. Vemos que el espaciado
entre pulsos no son los 500 usec sino unos 560. La razón es que además de los 500
usec programados en el delay, precisamos otros 60 usec para completar la
conversión AD (lo que concuerda con la estimación del voltímetro). Vemos que el
espaciado entre terminar una conversión y empezar otra si son los 500 usec
exactos que hemos programado.
A la
derecha, en un zoom del pulso de captura vemos con mayor precisión el
tiempo dedicado a la conversión, unos 55 usec.

Si en el
programa anterior cambiamos el delay entre muestras a Delay10TCYx(1); (equivalente a 2 usec) veremos que
el voltaje del pin RC0 sube a 4.42V, lo que corresponde a una ocupación del 92%
(4.42/4.86). En la figura adjunta se aprecia gráficamente dicha dedicación casi
exclusiva al proceso de conversión. El espaciado entre muestras es de 59 usec
(55 + delay) lo que corresponde a unas 17000 muestras por segundo (16950 en la
medida del osciloscopio)
Aunque
15000 muestras por segundo pueden ser más que adecuadas, vamos a ver que es
posible mejorar dichos resultados, aprovechando lo que hemos visto de la
programación del ADC en base a registros de control y el estudio de las
especificaciones detalladas del micro que estamos usando.
Modificaciones del código:
En primer
lugar escribiremos una función equivalente a la anterior (ADC_read2) pero
evitando usar las llamadas a las funciones de C18. De esta forma nos damos
cuenta de que implementar dichas funciones es muy sencillo y nos evitamos
llamadas a funciones (lo que esperamos que mejore el tiempo necesario):
#define select_ADC(ch) { ADCON0 &= 0b11000011; ADCON0 |= (ch<<2); }
uint16 ADC_read2(uint8 ch)
{
uint16 ad_res;
select_ADC(ch); //SetChanADC(ADC_channel);
Delay10TCYx(5);
ADCON0bits.GO=1; //ConvertADC();
while(ADCON0bits.GO); //while(BusyADC());
ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; //ad_res = ReadADC();
return ad_res;
}
Si
repetimos el bucle anterior con esta función vemos que el tiempo baja a unos 45
usec, una ganancia del 15%.
Podemos
mejorar un poco más si nos ajustamos a las especificaciones del PIC usado
(18F2520/4520). La documentación indica que para esta familia basta un tiempo
de adquisición (entre seleccionar canal y lanzar conversión) de unos 3 usec, lo
que a 20 MHz equivale a unos 15 ciclos . Claramente los 50 ciclos (10 usec) de
antes son excesivos. Nos bastaría con especificar un retrado de p.e. 20 ciclos:
uint16 ADC_read2b(uint8 ch)
{
uint16 ad_res;
select_ADC(ch); //SetChanADC(ADC_channel);
Delay10TCYx(2);
ADCON0bits.GO=1; //ConvertADC();
while(ADCON0bits.GO); //while(BusyADC());
ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; //ad_res = ReadADC();
return ad_res;
}
Con esto
bajamos a unos 40 usec, otro 10% adicional. Notad que dependiendo del PIC usado
este código tendría que ser modificado.
Finalmente
podemos usar una característica adicional de la familia 18F2520/4520. El tiempo
de adquisición puede ser preprogramado, lo que hace que podamos lanzar la
conversión nada más seleccionar el canal. Tras poner a 1 el bit GO, el módulo
ADC no lanza la conversión inmediatamente sino que espera el tiempo programado.
El tiempo se especifica en unidades de Tad y hay que programarlo en la
configuración (OpenADC) del módulo:
OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST
& ADC_4_TAD,
ADC_INT_OFF & ADC_VREFPLUS_VDD
& ADC_VREFMINUS_VSS, 7);
En este
caso preprogramamos un delay de 4 x Tad. Como Tad = 16/20 = 0.8 usec eso
equivale a 3.2 usec, que es superior al tiempo de adquisición mínimo
recomendado para estos PIC. La función de conversión queda ahora:
uint16 ADC_read2b(uint8 ch)
{
uint16 ad_res;
select_ADC(ch); //SetChanADC(ADC_channel);
ADCON0bits.GO=1; // Launch conversion without delay
while(ADCON0bits.GO); //while(BusyADC());
ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; //ad_res = ReadADC();
return ad_res;
}
Como vemos
no tenemos que preocuparnos del delay, ya que el módulo lo respetará. Con este
nuevo código la duración de la llamada a la función es de unos 24 usec. Las
ganancias se pueden detectar con la bajada del voltaje del pin RC0 o más
gráficamente, monitorizando RC0 con el osciloscopio. En la figura se adjuntan
las capturas de la duración de la función para el original y las
tres modificaciones propuestas (de arriba abajo y de izquierda a derecha). Vemos que hemos conseguido reducir a la mitad
el tiempo, pudiendo llegar hasta unas 40000 muestras/segundo (24 usec por conversion).
En otra
entrada veremos como combinar el uso del ADC con interrupciones. En primer
lugar veremos como usar una interrupción de un temporizador para lanzar la
conversión AD a intervalos exactos. En segundo lugar veremos como usar la
interrupción del propio módulo ADC para evitar que la función anterior sea
bloqueante. El uso de la interrupción AD nos permite no tener que esperar
(línea
while(ADCON0bits.GO)) hasta que el módulo termine: la
interrupción nos avisará cuando el resultado este listo en ADRESH:ADRESL.
Antes de
explorar esta combinación de ADC + INTS, vamos a ver un pequeño proyecto (brújula
electrónica ) en el que usaremos lo que
ya sabemos del ADC. Consiste en leer el voltaje de dos sensores magnéticos (en
dos ejes perpendiculares) y combinar su información para obtener una desviación
en grados respecto al norte magnético.
Si, excelente explicacion.
ResponderEliminarguai!
ResponderEliminarexcelentes todos los tutoriales! super utiles y amenos para los que, al igual que yo, se inician en el uso del pic8f...mil gracias!
ResponderEliminarExcelente tutorial muy masticable pero tengo una pregunta cuando yo caracterizo y linealizo un sensor resistivo el me genera una ecuacion como hago para introducir esa ecuacion en el micro (teniendo en cuenta que es un pi18fxxx)
ResponderEliminarMás que excelente!!! Me sirve para todas las prácticas y me hace su realización 10.000 veces más fácil!!!
ResponderEliminarGracias, gracias, gracias! :)
Excelente!!!
ResponderEliminarTe hago una consulta, si hago la conversión nuevamente a tensión en un programa C, qué fórmula debería usar ADC*5/1024 ó ADC*5/1023. Siempre he tenido esa duda. Por lo que vos explicás acá, nunca se llegaría a los 5V, que serían cuantificados en 1023, entonces 1023*5/1024=4.995. Me podrías dejar clara esta duda por favor. Mil gracias
ResponderEliminarCreo que esto resuelve mi duda: http://ww1.microchip.com/downloads/en/AppNotes/Achieving%20Higher%20ADC%20Resolution%20Using%20Oversampling%2001152A.pdf
ResponderEliminarla fórmula correcta es ADC*5/1023. Efectivamente sí convierte los 5V en 1023, y los 4.995 en 1022.
Buenos días, si yo quisiera sensar 2 señales a la vez a 50KHz, seria posible? a mi parecer no por que como hay un único ADC, debo asignar a 2 canales diferentes, y para ello debo esperar un tiempo (tiempo de adquisición) el cual es del orden de microsegundos, alguien que me aclare si es posible o no. gracias
ResponderEliminarseleccionar un tiempo de adquisición bajo
ResponderEliminar[Hola,excelente trabajo nunca habia visto un blog con estos temas bien explicados,espero que puedas continuar con demas temas sobre pics, espero ver algo sobre I2C y algo sobre Tivas de TI etc... ]
ResponderEliminarQuisera saber como configurar un acelerometro o gyroscopio, he leido que toca a frecuencias bajas para su configuracion .como es esto? ,pero mi integrado(IMU 6DOF digital) no da señales de vida,no se si sera la comunicacion I2C, y no se como empezar a probar
podrias decirme algo asi como un numeros de pasos(1.. 2... 3.. 4..) para empezar a trabajar este IMU con un pic en general
¿El tiempo de conversión Tc depende fundamentalmente del número de bits del conversor? Esto no es del todo correcto, aunque influye en ello, el tiempo depende fundamentalmente de la frecuencia de muestreo a la que puede operar un adc
ResponderEliminarReferente a tu comentario final:
ResponderEliminaresta demostrado que si tu usas un chip alejado de otro chip el ruido es mayor debido a las grandes capacidades que se generan, de echo los mejores adc tienen todas sus funciones extras integradas en el mismo chip para minimizar capacidades
Este comentario ha sido eliminado por el autor.
ResponderEliminarEste comentario ha sido eliminado por un administrador del blog.
ResponderEliminarEste comentario ha sido eliminado por un administrador del blog.
ResponderEliminar