# ADC del PIC: ¿es normal esto?



## alejandro_oo (Dic 21, 2006)

Hola,

Estoy usando un canal AD del pic 16f877 configurado para resolucion de 8 bits y como prueba estoy visualizando el valor de la conversion en un LCD 16x2, lo muestro en formato decimal, pero lo que sucede es que nunca se queda estatico el resultado, digo estoy midiendo un voltaje de una bateria el cual no varia en absoluto, pero el resultado del convertidor AD si lo hace. Por ejemplo se la pasa oscilando del 133,134,135,138 a veces hasta el 140 y vuelve al 133 y asi.

Asi que me pregunto: ¿Es normal esto? y si no lo es: ¿como lo soluciono?

Hasta el momento no he usado niguna entrada para voltaje de referencia y se supone que la referencia la toma de la alimentacion 5v del PIC. No se si pueda ser ese el problema. Por que la verdad si me interesa que el resultado sea lo mas estable posible, presisamente para poder notar en caso de que haya verdaderas variaciones en el voltaje que estoy midiendo.

Saludos,


----------



## Loktar (Dic 21, 2006)

Pone un capacitor de 100 nF. Una patita de este en la entrada de la señal analógica y la otra a masa. Si no me equivoco, esto soluciona estos problemas.

Saludos


----------



## alejandro_oo (Dic 22, 2006)

Hola Loktar,

Pues ya le coloque el condensador como me indicas, y la variación sigue, nunca se queda estable. Otra cosa que probé es poner la entrada a masa, se supone que debería ponerse en 0, pero no, aun así se mantiene variando: 0, 1, 2, 4, etc.

De momento todo esto lo tengo montado en protoboard, no creo que ese sea el problema, pero pienso que es como una interferencia o algo así. Cualquier idea es bienvenida.

Saludos y gracias,


----------



## Loktar (Dic 22, 2006)

Mmm, a mi entonces me parece que se debe a un error en el mismo PIC. Pienso que puede ser el programa. Estás seguro que esperas todos los tiempos necesarios provisto por Microchip? Osea el tiempo de adquisición y eso. Y también comprobando que la conversión está lista?


----------



## Loktar (Dic 22, 2006)

Capaz sería bueno que nos pases el programa en ASM.


----------



## alejandro_oo (Dic 22, 2006)

Hola, y cuales son los tiempos mas adecuados ¿?, yo le hago así: Primero configuro las entradas que van a ser análogas, luego elijo el canal a leer y espero 5 ms, leo el valor del ADC, espero otros 5 ms, hago uso del valor y finalmente tengo un retardo de 100 ms entre cada conversión, esto en un ciclo infinito.

Eso de si la conversion esta lista, la verdad no estoy seguro, ya que no lo hago en ASM sino en C y pues no se si eso lo haga la funcion read_adc() por automatico.

¿Tendría que esperar más en algun punto?

Saludos,


----------



## alejandro_oo (Dic 22, 2006)

Perdón, no había visto tu segundo mensaje, pues no lo tengo en ASM pero igual pongo el C, para que lo chequen:


```
#include <16F877.h>
#device ADC=8
#fuses   HS,NOWDT,NOPROTECT,PUT,NOLVP,BROWNOUT
#use delay (clock=20000000)
#use standard_io(b)
#use standard_io(d)
#use standard_io(e)

int valor_bateria=0x00;
int valor_alimentacion=0x00;

/* Mandar un comando al LCD */
void lcd_comando(int comando)
{
   output_low(PIN_E0);     /* Modo registro en el LCD */
   output_b(comando);      /* Manda el comando por el puerto B */
   output_high(PIN_E2);    /* Habilita el LCD */
   delay_us(5);            /* 5 us */
   output_low(PIN_E2);     /* Deshabilita el LCD */
   delay_ms(1);            /* 1 ms */
}

/* Mandar un caracter al LCD */
void lcd_caracter(char caracter)
{
   output_high(PIN_E0);    /* Modo caracter en el LCD */
   output_b(caracter);     /* Manda el caracter por el puerto B */
   output_high(PIN_E2);    /* Habilita el LCD */
   delay_us(5);            /* 5 us */
   output_low(PIN_E2);     /* Deshabilita el LCD */
   delay_ms(1);            /* 1 ms */
}

/* Funcion para mandar el cursor a posicion reuqerida */
void lcd_posicion(int linea, int posicion)
{
   switch (linea)
   {
      case 1:
         lcd_comando(0x80+(posicion-1));  /* Linea 1 posicion requerida -1 */
      break;

      case 2:
         lcd_comando(0xC0+(posicion-1));  /* Linea 2 posicion requerida -1 */
      break;
   }
}

/* Iniciar el LCD 16x2 JHD */
void lcd_iniciar(void)
{
   set_tris_b(0x00);       /* Salidas en el puerto B */
   set_tris_e(0x00);       /* Salidas en el puerto E */
   output_e(0x00);         /* Puerto e bajo */

   lcd_comando(0x38);      /* LCD Linea 1 */
   lcd_comando(0x38);      /* LCD Linea 2 */
   lcd_comando(0x0C);      /* Cursor apagado */
   lcd_comando(0x80);      /* LCD linea 1 */
   lcd_comando(0x06);      /* Desplazamiento del cursor a la derecha */
}

/* Funcion para leer el ADC */
void medir_entradas(void)
{
   /* ADC0 */
   set_adc_channel(0);              /* Lectura del canal 0 */
   delay_ms(5);                     /* 5 ms */
   valor_alimentacion=read_adc();   /* Se lee el canal 0 y pasa a valor_alimentacion */
   delay_ms(5);                     /* 5 ms */

   /* ADC1 */
   set_adc_channel(1);              /* Lectura del canal 1 */
   delay_ms(5);                     /* 5 ms */
   valor_bateria=read_adc();        /* Se lee el canal 1 y pasa a valor_bateria */
   delay_ms(5);			    /* 5 ms */	
}

/* Principal */
void main(void)
{
   setup_adc(ADC_CLOCK_INTERNAL);         /* Configuracion del convertidor */
   setup_adc_ports(RA0_RA1_RA3_ANALOG);   /* RA0 como entrada analogica */

   lcd_iniciar();                         /* Iniciar el LCD 16 x 2 */

   do
   {
      medir_entradas();          /* Manda medir */

      lcd_comando(0x01);      /* Limpiamos pantalla   */
      lcd_comando(0x02);      /* Cursor a casa*/

      printf(lcd_caracter,"AD0=%U AD1=%U",valor_alimentacion,valor_bateria);

      delay_ms(100);

   }while(true);
}
```

Saludos,


----------



## Loktar (Dic 22, 2006)

Hola. En C nunca programe. Los tiempos de adquisición parecen suficientes. Cuando empiezas la conversión, tienes que verificar que el bit GO/DONE se ponga a cero. Eso te dirá que la conversión está lista. Lo que no sé es si la función en C te hace eso automáticamente. Prueba hacer esto: Luego de que empieces la conversión, haz un ciclo que verifique que el bit GO/DONE (bit 2 de la dirección 1FH), Si el bit está a cero es que la conversión está lista, si no, el bucle continúa hasta que el bit se ponga a cero.

También sugiero la opinión de alguien más experimentado.

Saludos.


----------



## alejandro_oo (Dic 22, 2006)

Hola,

Esa idea me gusta, de verificar el bit GO/DONE del ADCON0, solo que no veo en que punto meter tal verificación, esto por que la función read_adc() me deja sin control de esa parte. Ya que es ella quien me devuelve el valor de la conversión, pero como tu bien dices yo igualmente ignoro la estructura de esa función como para poder determinar si verifica el estado del bit GO/DONE o no.

Hasta ahorita no me he encontrado la referencia de esa función, así que si alguien sabe donde se puede checar esto pues no se quede callado.

Saludos,


----------



## alejandro_oo (Dic 22, 2006)

Hola de nuevo, pues no se pero creo que el problema es el montaje, pues muevo o pongo la mano sobre algunos de los alambres del protoboard y casi se queda quieto, digo casi por que la variación es mínima, de estar en 139 se mueve a 140, o sea muy poco e inclusive se llega a quedar estático. Debo decir que tiendo a dejar un poco largos los puentes, a tal grado que al final me queda como una araña de colores alrededor y sobre el PIC, pero no se si esto es una causa real del problema o ya me sugestione ¿?.

Saludos,


----------



## eidtech (Dic 22, 2006)

> Hola de nuevo, pues no se pero creo que el problema es el montaje, pues muevo o pongo la mano sobre algunos de los alambres del protoboard y casi se queda quieto, digo casi por que la variación es mínima



Si sucede algo asi me late que alguna referencia esta flotada, es decir no esta correctamente referenciada a tierra. Intenta medir con el multimetro que todas tus tierras estes conectadas entre si. Incluso ve si hay diferencias de potencial entre tierras.


----------



## thebearmac (Dic 23, 2006)

HOLA alejandro_oo:

YO HE MANEJO C PARA PROGRAMAR PICS, Y LA FUNCION DE ADC_READ(); SE EN CARGA DE TODO EL PROCESO DE CONVERCION, ASI QUE CON ESTA INSTRUCCION NO HAY PROBLEMA, AHORA SI ESTAS UTILIZANDO VARIOS CANALES  PARA LEER DATOS ANALOGOS, HAY PUEDE ESTAR EL PROBLEMA, POR QUE CUANDO SE HACE CAMBIO DE CANALES PARA LEER DATOS MUCHAS VECES EL CANAL SE QUEDA ESTATICO, ES DECIR QUE NO CAMBIA EL DATO SI NO QUE SE QUEDA LEYENDO EL DEL ANTERIOR CANAL, ESTO SUCEDE CUANDO LA CARGA DE ENTRADA DEL ADC NO CUMPLE CON LA EXIGENCIA MINIMA POR EL FABRICANTE, EN LA HOJA TECNICA DE MICROCHIP SE SUGIERE COLOCAR UNA RESISTENCIA DE 10k EN LA ENTRADA DE CADA ADC PARA REALIZAR UNA ADECUADA CIONVERCION SI ESTAS CONECTANDO LA BATERIA O LAS SEÑALES DIRECTAMENTE AL PUERTO SIN LAS RESISTENCIAS LO MAS SEGURO ES QUE EL PROBLEMA DE LA VARIACION SE DEBA A ESTO, DE IGUAL FORMA TRATA DE TRABAJAR CON FUENTES MUY BIEN FILTRADAS EN LO POSIBLE QUE NO SEAN "SWICHADAS", COMO LAS DE LOS PC POR ESTAS GENERAN DEMACIADO RUIDO


----------



## yamazaky1984 (Dic 26, 2006)

la respuesta que busca alejandroo es ; NO es normal, y para mi  el problemos es  que debes darle un mayor tiempo entre la adquisicoin de datos de adc0 y adc1, ya que actuelmente estas tomando los datos de manera seguida y el retardo es corto.


----------



## Turkito (Dic 26, 2006)

Hola panita, mira lo que creo q está pàsando es que la bateria a la que te estás conectando, puede estar variando ese potencial en unos cuantos mV,aunque no debería, pero que son lo suficientemente elevados para generar un salto en los registros ADRES..Como sabrás la resolución del ADC para producir un salto es de 4.8 mV, o sea que si tu entrada análógica varia en al menos 4.8mV, experimentarás un cambio en la salida................Para mi eso es lo que está pasando!!!


----------



## alejandro_oo (Dic 27, 2006)

Hola a todos, gracias por sus amables respuestas.

Les comento que las variaciones ya se venían dando inclusive cuando manejaba un solo canal (AN0). Y llegue a pensar que eso era normal, pero ahora que se que no lo es, me desconcierta bastante. 

La conexión de la batería la realizo por medio de un divisor de voltaje con resistencias, de este modo si tengo por decir 25 v a la entrada se divide entre 10 y me quedan 2.5 v los cuales conecto a la entrada del AD acompañado por el condensador de 100 nf a masa. Vigilo el máximo voltaje con un zener de 5.1 v. He puesto el esquema para que me corrijan en caso de estar mal en algún punto.

Por otro lado me gustaría que me recomendaran un voltaje de referencia de 5.0 v el mejor que se pueda. Por acá solo he sabido del LM336Z-5.0 no se que tan preciso sea, pues no lo he comprado, por eso pido sus opiniones.

Lo que pretendo es ir descartando todas las posibles causas para así lograr corregir el problema.

Turkito: pero mido el voltaje con mi multimetro y no se mueve para nada, a no ser que con este multimetro no se logre captar las variaciones de mV.

Saludos,


----------



## alejandro_oo (Ene 4, 2007)

Ahora lo he pasado al simulador y funciona y muy bien, ahí si que se queda estable el AD y todo, pero esto quiere decir que el problema esta en el montaje del protoboard ¿?

¿O simplemente funciona estable por ser un simulador?

Saludos,


----------



## Loktar (Ene 4, 2007)

Hola Alejandro. Una pregunta: ¿Qué simulador usas?

Saludos.


----------



## alejandro_oo (Ene 5, 2007)

Hola loktar,

Uso el Proteus 6 profesional (ISIS versión 6.9)

Saludos,


----------



## Trent (Ene 5, 2007)

K onda alejandro_oo, fijate que lo mismo me pasaba cuando lo montaba en el protoboard, note que a veces le acercas la mano y la conversion varia, Trata de  no pasar cables muy cerca del PIC, muchas veces esto mejoro un poco mis conversiones.

La otra es tratar de ir aproximando valores, tal vez tu conversion es muy pequeña que le afectan las pequeñas variaciones, a lo mejor si haces uso de metodos numericos para aproximar la recta que esperas


----------



## alejandro_oo (Ene 6, 2007)

Hola Trent, Voy a cuidar lo de los cables, a ver que tal, ahora que lo ensamble te platico.

Lo que no se es de donde puedo sacar los 5.0 v precisos para Vref+, en el simulador muy bonito que me los da de la alimentación general, pero en la realidad ¿Cómo?, una referencia de voltaje ¿Cuál?

Saludos,


----------



## rampage (Ene 11, 2007)

El año pasado hice un sensor de temperatura utilizando un micro AT89S52 y un ADC0804, y me encontre con el mismo problema que vos. No se si es una "verdadera" solucion al problema, pero yo hice lo siguiente: tomaba una medicion cada 200ms y la almacenaba en un vector. Luego cuando llegaba a las 5 mediciones (es decir 1 segundo) hacia el promedio y actualizaba el valor mostrado en el LCD.


----------



## alejandro_oo (Ene 11, 2007)

Hola a todos,

Pues debo comentarles que hoy he terminado de armarlo en tabla fenolica siguiendo todos sus consejos y hasta me daba algo de temor probarlo, pero al final lo hice, ¿y que creen?... ¡¡¡¡0 variaciones!!! Lo arme tal como lo puse en el simulador (imagen anterior) y quedo perfecto, claro cuidando que las conexiones quedaran lo mas limpias, cortas (como me recomendaron aquí ustedes) y bien hechas posibles.

Como referencia de 5.0v finalmente utilice el LM385Z, tal y como el fabricante recomienda para 5v. Solo tuve que pasarme como dos horas ajustándolo, (jajaja no es cierto, en unos minutos queda)

http://www.ortodoxism.ro/datasheets/nationalsemiconductor/DS005250.PDF

Finalmente les agradezco mucho a todos los que contribuyeron con soluciones, me han servido de mucho, sobre todo para formarme un mejor criterio sobre este problema que, por lo visto, no le es ajeno a nadie de los que trabajamos con los convertidores AD. Estoy seguro que este tema le servirá mucho a quien(es) en el futuro ande sobre lo mismo.

Loktar
eidtech
thebearmac
yamazaky1984
Turkito
Trent
rampage

Muchas gracias a ustedes.

Saludos,


----------



## mga_78 (Ene 20, 2007)

Hola alejandro, entonces, y resumiendo, qué crees que fueron lños puntos clave para solucionar el problema? reducir el tamaño de los cables?, usar el regulador de voltaje? alguna mas? por cierto, alguien me recomienda algún ADC de 16 bits que sea rápido y estable? GRACIAS A TODOS


----------



## alejandro_oo (Ene 20, 2007)

Hola mga_78,

Ya analizando, lo mas importante creo yo para lograr una lectura estable en mi caso, es que venia tomando Vref+ directamente de la salida de un L7805 el cual alimenta la carga del circuito en general que requiere 5v y por lo tanto es posible que hubiera pequeñas variaciones, situación que resolví (como bien mencionas) usando un circuito generador de referencia de voltaje de precisión, para ajustarla debes usar trimpots de 15 o 20 vueltas, a menos que quieras pasarte un mal rato o seas muy bueno con el pulso.

Luego yo lo tenía montado en una protoboard, que ya anteriormente me había dado dolores de cabeza por falsos contactos, y como comentaba en anterior mensaje: mis puentes eran algo largos, esto debido a la incomodidad que me presentaba el montaje de algunas de las piezas en la proto. Así que yo personalmente no recomendaría el montaje de un ADC en una proto, a menos que se estuviera seguro tanto del estado de los puentes como de la misma protoboard fueran óptimos, pero lo mejor es realizar el montaje de un dispositivo de estos directamente sobre alguna tabla fenolica perforada o de plano en circuito impreso, todo con el fin de asegurarse que los contactos sean perfectos, también debe usarse cableado en buen estado, nada de cables podridos, yo me fui a usar cable blindado para las salidas del circuto (las que toman las lecturas).

En cuanto a los tiempos de adquisición, hablando de PICs y del CCS, va bien con más de 50us entre el cambio de canal y la lectura del mismo. Un truco interesante para no abusar de los retardos es establecer el canal de lectura, luego correr alguna rutina intermedia para ganar tiempo y ahora si leer el canal, de este modo los retardos pueden ser mínimos, lo que hace más eficiente la aplicación. 

Algo que me ayudo bastante, es el poder simular el montaje para verificar el correcto funcionamiento. 

Ojala esto te ayude a evitar líos innecesarios.

Saludos,

PD: Espero que alguien te recomiende ese ADC de 16 que andas buscando.


----------



## mga_78 (Ene 20, 2007)

GRACIAS;  por cierto me daba un arror al publicar mi mensaje; parece que daba el error pero se posteaba; ,por eso hay varios mensajes iguales


----------



## Edu_RA (Ene 21, 2007)

Esto que cuentas suele pasar, y se suele solucionar manteniendo un promedio de las mediciones en lugar de tomar la última solamente.
Si mantienes un promedio, la medición será más estable. La estabilidad será mayor cuanto más mediciones promedies hacia atrás. Claro que también influye a qué repetición mides. Si estás midiendo cada 1 ms y promedias los últimos 10 valores, una medición que varíe muy rápido se achata en respuesta y tardará más o menos 5 ms en llegar a un valor correcto. Si mides algo que varía lentamente, no hay problema. Y sino lo que se puede hacer es medir más seguido o incluir menos mediciones hacia atrás en el promedio.
Otra cosa que se hace es descartar los valores que se alejan mucho del valor anterior.
De todos modos, también vale lo que ya se ha hablado en los mensajes, sobre reducir el ruido y filtrar la senal que se mide.
Edu


----------



## Mauricio2346 (Abr 22, 2008)

saludos:    si la variacion de la que se habla es poco significativa no hay problema.   hay que recordar que el micro tiene resolucion hasta de 10 bits, lo que significa que las variaciones permitidas son muy pequeñas.   además, el voltaje de la bateria o lo que se desee controlar por mas exacto que sea nunca es constante, sumandole además los ruidos de os pines... mucha suerte


----------



## dinamita666 (May 7, 2008)

Buenas me gustaria que colocaras el codigo en .asm del conversor analogo digital, para poder probarlo.
gracias


----------



## ral marqz (May 27, 2008)

soy nuevo en este foro, pues a mi me esta pasando algo similar, estoy tratando de visualizar temperatura con display y usando el pic16f877 pero la salida es inestable osea presenta oscilaciones y el valor no es fijo, ya he probado la configuracion del ADC Y parece que todo esta bien, pero no me esta funcionando, si alguno de ustedes me puede ayudar se lo agradeceria. (estoy programando en ASM)

GRACIAS


----------



## tuxandres (Mar 28, 2010)

Edu_RA dijo:


> Esto que cuentas suele pasar, y se suele solucionar manteniendo un promedio de las mediciones en lugar de tomar la última solamente.
> Si mantienes un promedio, la medición será más estable. La estabilidad será mayor cuanto más mediciones promedies hacia atrás. Claro que también influye a qué repetición mides. Si estás midiendo cada 1 ms y promedias los últimos 10 valores, una medición que varíe muy rápido se achata en respuesta y tardará más o menos 5 ms en llegar a un valor correcto. Si mides algo que varía lentamente, no hay problema. Y sino lo que se puede hacer es medir más seguido o incluir menos mediciones hacia atrás en el promedio.
> Otra cosa que se hace es descartar los valores que se alejan mucho del valor anterior.
> De todos modos, también vale lo que ya se ha hablado en los mensajes, sobre reducir el ruido y filtrar la senal que se mide.
> Edu


 
Bien por la info, me gustaria saber o si tiene un codigo sencillo de ejemplo sobre promediar las medicion ya que no se como iniciar o como es que se hace. es para haber si lo pruebo con un potenciometro que es donde tengo el problema.

Gracias.


----------



## pochan (Mar 28, 2010)

Estoy completamente seguro que lo que te pasa es porque lo tienes montado en una protoboard y tienes ruido en la entrada del conversor ADC. Si lo montas en una placa de fibra de vidrio de topos te funcionara perfectamente (ademas pon ese condensador de 10 o 100nF en la entrada del conversor hacia masa.

La protoboard es una fuente de ruido enorme, nunca se deberia usar mas que para hacerse una "ligera" idea de si el montaje funcionara.


----------



## High (Ene 26, 2011)

lo que te pasa es que no configuraste el tris a! de ahí el ruido que tenés.. by


----------



## enrique morales (Jun 1, 2011)

Lo que puedes hacer es promediar el resultado de varias mediciones del canal analogo y luego los muestras al display , y veras que tu medicion se establese


----------



## pont (Jun 22, 2012)

Excelente. 
Tambien a mi ha ayudado mucho esta discución XD. 
Lo mejor es no dejar cables como si fueran antenas. El monteje en protoboard, puede ser muy fastidioso, ya que por la inductancia puede variar levemente nuestros valores. lo mejor es aislar lo mas posible la señal que vamos a medir del circuito de alimentacion y poner condensadores lo mas serca posible de la entrada del ADC.


----------



## andyt (Ago 23, 2012)

hola : estoy haciendo el control de nivel de un tanque el cual lo represento con un potenciometro,
el problema que tengo es que al momento de montarlo  y probarlo  pasa de la maxima ala minima y no queda en niveles intermedios....
la simulacion me da perfecta .. pero en el montaje sucede el problema

muchas gracias por su colaboracion......


----------

