TODOPIC

FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: DarkVect en 05 de Febrero de 2008, 11:49:06

Título: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 11:49:06
Os comento: He montado un potenciómetro con una pata a 5V, otra a 0V y la central la conecto directamente al canal AN0 del PIC. Realizo la lectura y el valor es calcado al obtenido en un voltímetro conectado al mismo punto. Hasta aquí no hay problema.

Ahora cojo el sensor que debo medir, es un sensor potenciómetrico de tres cables. Un cable lo conecto a 5V, el otro a 0V y utilizo el común para realizar la lectura. Con el voltímetro obtengo una salida correcta, voy moviendo el potenciómetro y todo va perfecto pero a la que le conecto la entrada analógica del PIC ese pin se me va a 0V para la mayor parte del recorrido del potenciómetro y sólo varía hasta centenas de milivoltios en su punto máximo. El potenciómetro tiene un valor 20K. Qué puede estar pasando? Cómo me afecta el ADC a la medida?

Muchas gracias!!
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Azicuetano en 05 de Febrero de 2008, 13:02:53
Hola DarkVect!

Por si es un problema de adaptación de impedancias... podrías poner un operacional en modo seguidor de tensión a ver como tira la cosa. ¿?¿?


Un saludo desde Alicante.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 14:08:33
Es lo primero que he pensado, pero claro, es añadir otro componente más con su alimentación, etc...

El potenciómetro que utilizaba al principio era de 2K y la medida era correcta. Hice la prueba de poner un potenciómetro del mismo valor que el sensor (20K) y hace lo mismo que el sensor, es decir que por lo visto es demasiado para el PIC.

Pruebo lo del seguidor y comento a ver qué tal.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 14:54:58
Ya he colocado el AO seguidor y lo mismo. Sin conexión al ADC la Vout del AO coincide con la tensión que sale del cable de señal del potenciómetro, al conectar el canal analógico la tensión cae. El efecto con el AO no es tan bestia: antes obtenía siempre 0V y <1V en un pequeño rango donde la conversión funcionaba bien. Ahora la conversión funciona en un rango un poco mayor, llego a 1,4V y de ahí se corta a 0V.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: reiniertl en 05 de Febrero de 2008, 15:06:50
Puedes poner el circuito que usaste con el operacional?
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 15:14:19
El operacional es un TLC272 y el circuito es un seguidor tal cual. El cable común del potenciómetro lo conecto a la entrada + del AO (pin3), la pata - del AO (pin2) la llevo a la salida (pin1) y la alimentación es de 12V (pin8) y la masa en el pin4.

Esta configuración tal cual, sin el PIC, funciona perfectamente, la entrada se replica a la salida sin problema. Si mido el pin del ADC sin nada conectado leo 0V. Si conecto el ADC a la salida del AO (pin1) ese pin pasa a valer de 0 a 1V ´(sólo en un pequeño margen, en el resto vale 0) según donde esté el potenciómetro en lugar de dar de 0 a 5V. Parece como si el PIC impusiera la tensión en ese pin del AO. En la entrada + del AO sigue habiendo la tensión correcta.

Os pego el código por si acaso:

Código: [Seleccionar]
#include <16F818.h>                                //PIC a utilizar
#device adc=10                                     //numero de bits del ADC

#fuses XT                                          //configuracion de fusibles
#fuses NOWDT
#fuses PROTECT
#fuses PUT
#fuses NOBROWNOUT
#fuses MCLR
#fuses NOLVP
#fuses CPD
#fuses NOWRT
#fuses NODEBUG

#use delay (clock=3276800)                         //Fosc=3,2768Mhz

#define LED       PIN_A1                           //LED de funcionamiento
#define LCD_RS    PIN_B1                           //pinout del LCD
#define LCD_RW    PIN_B2
#define LCD_E     PIN_B3
#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#byte ADCON0=0x1F                                  //parametros ADC
#byte ADCON1=0x9F
#byte ADH=0x1E
#byte ADL=0x9E

#include <flex_lcd.c>                              //libreria LCD


int nClocks=0, nDelay=0, flag_seg=0;


#INT_TIMER2
void Interrupcion_Timer2()                         //interrupcion cada 5ms
{
   nDelay++;

   if(nDelay==200)
   {
      nDelay=0;
      flag_seg=1;
      output_high(LED);
   }
   else
   {
      output_low(LED);
   }
}


void main(void)
{
   int16 valor_adc=0;
   int decimales=0;
   int unidades=0;
   int wind_dir=0;

   disable_interrupts(GLOBAL);                     //deshabilitar interrupciones
   disable_interrupts(INT_EEPROM);                 //deshabilitar interrupcion EEPROM
   disable_interrupts(INT_RB);                     //deshabilitar interrupcion portb
   disable_interrupts(INT_TIMER0);                 //deshabilitar interrupcion del timer0
   disable_interrupts(INT_TIMER1);                 //deshabilitar interrupcion timer1
   disable_interrupts(INT_CCP1);                   //deshabilitar interrupcion CCP1
   disable_interrupts(INT_SSP);                    //deshabilitar interrupcion I2C / SPI
   disable_interrupts(INT_AD);                     //deshabilitar interrupcion ADC
   disable_interrupts(INT_EXT);                    //deshabilitar interrupcion RB0

   setup_TIMER_0(RTCC_INTERNAL | RTCC_DIV_1);      //preescaler=1
   setup_TIMER_1(T1_DISABLED);                     //desactivar timer1
   setup_TIMER_2(T2_DIV_BY_1,255,16);              //preescaler=16
   setup_CCP1(CCP_OFF);                            //desactivar modulo captura
   setup_SPI(SPI_SS_DISABLED);                     //desactivar SPI
   setup_ADC_PORTS(AN0);                           //entradas analogicas
   setup_ADC(ADC_CLOCK_INTERNAL);                  //activar modulo ADC

   set_adc_channel(0);
   set_tris_a(0b00000001);                         //porta todo como salida menos A0

   ext_int_edge(H_TO_L);                           //interrupcion externa en flanco de bajada

   port_b_pullups(TRUE);                           //pullups portb activadas

   ADCON0=0b11000001;                              //configurar ADC
   ADCON1=0b10001110;

   enable_interrupts(INT_TIMER2);                  //habilitar interrupcion timer2
   enable_interrupts(GLOBAL);                      //interrupciones activadas

   lcd_init();
   delay_ms(50);
   output_a(0b0001000);

   do
   {
      if(flag_seg==1)
      {
         flag_seg=0;
         valor_adc=read_adc();
         
         wind_dir=valor_adc/2,8417;

         printf(lcd_putc,"\f");
         lcd_gotoxy(1,1);
         printf(lcd_putc,"ADC=%lu", valor_adc);
         lcd_gotoxy(1,2);
         printf(lcd_putc,"Dirección=%u", wind_dir);
      }

   }while(TRUE);
}
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: reiniertl en 05 de Febrero de 2008, 15:24:02
No uses un seguidor tal cual, porque es evidente que afecta la resistencia equivalente vista desde el punto de vista del potenciómetro. recuerda que ahora no tienes una fuente de alimentación.

Utiliza un amplificador de ganancia unitaria con resistencias de al menos 50K, y mira a ver que es lo que pasa.

Saludos
Reinier
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 15:26:45
OK!! Voy a hacer la prueba y te comento.

De todos modos quisiera aclarar de forma más precisa lo que sucede:

Con el potenciómetro al mínimo (punto común a masa) leo 0V en el ADC. A medida que voy aumentando el valor de tensión el valor del ADC va creciendo hasta llegar a 1V aprox. (valor ADC=200) donde se queda clavado sin seguir subiendo por mucho que aumente la tensión.

EDITO: no puedo hacer un ampli de G=1 tal cual porque sólo es posible con una configuración inversora.
EDITO2: He probado con un no inversor (G=2) y sigue igual. Ahora para una entrada de 0 a 0,5V mide bien, pero se queda anclado ahí.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 15:55:39
SOLUCIONADO!!!!  :-/ :-/

No me preguntéis por qué, pero he quitado la línea set_tris_a(0b00000001); y todo ha vuelto a funcionar!! Ahora mismo lo tengo con el seguidor pero me jugaría algo a que funciona sin. Por qué esa línea me lo fastidiaba? Cómo configuro entonces el resto de pines del puerto?

EDITO: pues funciona sin seguidor perfectamente!! Maldita línea!! Alguien sabe cómo configuro el resto de pines? No he utilizado fast_io.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 05 de Febrero de 2008, 16:00:09
Sospecho que tenías el pin declarado como entrada digital, en lugar de como entrada analógica.
Por lo que veo en tu código mi única duda es con estas instrucciones, puesto que no he revisado la data:

   ADCON0=0b11000001;                              //configurar ADC
   ADCON1=0b10001110;

¿Será que tienes un fallo ahí?
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 16:09:03
Te comento la configuración tal y como sale en el Data:

ADCON0=0b11000001; el 11 es para seleccionar el reloj interno RC, los 3 ceros que siguen son para seleccionar el canal0, el siguiente cero es el GO/DONE, el siguiente bit no está implementado y el último 1 es el ADON para iniciar la conversión.

ADCON1=0b10001110; el primer 1 es justificación a la derecha, los 3 ceros siguientes no están implementados, y los últimos cuatro bits (1110) significan, según el Data: AN0=analógico y el resto digitales, con las Vref la alimentación.

Cuando se utilzia el ADC los tris cómo se configuran?
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 05 de Febrero de 2008, 16:19:50
Ah, jeje, creo que he visto el problema.

No has puesto #use fast_io(A)

Al no tenerlo, en el momento que haces  output_a(0b0001000); me apuesto lo que quieras a que eso desconfigura la entrada analógica y la pone en digital.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 05 de Febrero de 2008, 16:27:42
Entonces la cosa sería:

#use_fast_io(a);
set_tris_a(0b00000001);
ADCON0=0b11000001;                             
ADCON1=0b10001110;

Voy a probarlo!!

FANTÁSTCIO!! Ahora sí que sí!!

Ya que estás por aquí Nocturno, cómo puedo escalar el valor del ADC para que marque mi magnitud real? La conversión directa es:

real=val_ADC*0,3519 o real=val_ADC/2,8417

Ambas variables son int16 y teniendo en cuenta que val_adc puede llegar a valer 1023 sólo puedo hacer: val_adc*10/28 o val_adc*35/100 sin pasarme de los 2^16.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 05 de Febrero de 2008, 17:23:15
Yo en esos casos hago uso del cast a float:

real=(int16)((float)val_ADC*0,3519);
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 06 de Febrero de 2008, 09:57:01
Nocturno he probado eso y no me da. Al mostrar real en el LCD aparece 3519.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 06 de Febrero de 2008, 10:08:51
Es raro. Podrías probar a mostrar el valor de val_ADC, luego el valor de (float)val_ADC, posteriormente el valor de (float)val_ADC*0.3519 y por último el de (int16)((float)val_ADC*0.3519) hasta encontrar en que parte de la operación la estamos cagando.
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 06 de Febrero de 2008, 10:23:50
Lo tengo así:

int16 val_adc;
int16 real;

Cómo quieres que muestre lo que me has ido diciendo, a través de la variable real o directamente?

Si hago real=(float)val_adc; el valor es el mismo que val_adc.
Si hago real=(float)val_adc*0,3519; el valor que obtengo es cero.

Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 06 de Febrero de 2008, 10:28:12
prueba esto, a ver qué tal:

printf(LCD_PUTC, "%6.2f",(float)val_adc*0,3519);

y luego esto otro

printf(LCD_PUTC, "%6lu",(int16)((float)val_adc*0,3519));
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 06 de Febrero de 2008, 10:33:18
La primera me desborda la memoria de programa, lo probaré con valores fijos sin el resto del programa. Y la segunda me muestra 3519.

EDITO:

He probado la primera en un programa "vacío" con varios valores para val_adc y en todos me da .00
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 06 de Febrero de 2008, 10:42:01
¡Qué raro!

Veo que en vez de punto decimal (0.3259) escribí coma decimal (0,3259). ¿No será eso lo que provoca que sólo se quede con el 0 y por eso el resultado siempre sea 0?
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 06 de Febrero de 2008, 10:55:24
Es muy posible!! Lo copié directamente!!

Por la tarde lo pruebo. Gracias!!
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: DarkVect en 07 de Febrero de 2008, 15:52:09
He cambiado la , por el . y va perfecto!! Gracias!!
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: Nocturno en 07 de Febrero de 2008, 18:45:09
Olé
Título: Re: El ADC me modifica la tensión en el pin a leer
Publicado por: ComePic en 04 de Diciembre de 2010, 14:02:04
Ah, jeje, creo que he visto el problema.

No has puesto #use fast_io(A)

Al no tenerlo, en el momento que haces  output_a(0b0001000); me apuesto lo que quieras a que eso desconfigura la entrada analógica y la pone en digital.

Bueno antes que nada un saludo a todos....

Segun lo que entiendo del manual, el CCS por defecto usa #use standard_io(A) , el genera lineas de codigo en el compilado cuando se modificara el estado de un pin  para asegurar la direccion de uso del pin (I/O). Lo pueden comprobar con el archivo *.lst que se genera cuando compilan. Ahi esta el *.asm que se convertira en *.hex ....

Por lo de la operacion aritmetica mira como lo hago yo....
Código: [Seleccionar]
         
         unsigned long cont;
         int temp;
         duty(6);                       // es una funcion para asignar el ciclo del trabajo, ya que set_pwm1_duty() no tiene en cuenta los 2 bit menos significaivos
         while(!t(jp)){                // t lo tengo definido como bit_test .... es muy largo y no me gusta colocarlo en la preguntas. jp en un pin, ahi hay un boton
            vt=read_adc();         // aqui obtengo el valor entre 0 y 1023
            if(vt!=vt_ant)            // pregunto si es diferente al anterior y si lo es , que entre en el if
            {
               vt_ant=vt;            // hago la conversion anterior igual a la nueva
               cont=(0.13*vt)+6;   // Aqui hago una regla de tres para convertir 0-1023 a 6-138... la operacion real era cont=(vt*138)/1023 + 6
                                             // pero como se desbordaba la multiplicacion sobre los dos bytes que tiene cont, opte por  138/1023=0.13           
               temp=make8(cont,0); // Como cont es de 2 bytes solo necesito el byte menos significativo y con make8 saco el byte 0 de cont y lo llevo a temp
               duty(temp);
            }
Y por otro lado yo tambien tengo el problema del potenciometro, lo conecto de igual manera que Dark y por mas que muevo el pot solo me varian unos cuantos milivoltios a la entrada del pic. Cuando no  lo tengo a la entrada del pic, funciona de maravilla el divisor de tension del pot. Lo mas curioso es que cuando conecto la entrada del pic directamente a 0v(GND) ó 5v(Vcc) el pin si cambia el voltaje y registra lo 1023 ó 0 , correspondientes a la conversion.
Con esos datos tambien pense que el pot (50k) no esta dentro del permitido segun en el manual (10k a lo mucho) y le coloque un seguidor pero igual no me funciono. Luego lei aca en el foro y vi las posibilidad de modificar el codigo para asegurar la correcta configuracion, coloque el #use fast_io(a) y no funciono, yo no uso el set_tris_a() pero igual me dio por usarlo y tampoco.... bueno en fin programe tanto ese pic que me canse y opte por cambiar de pin y se soluciono el problema. Puede ser que estuviese quemado, pero coloque otro pic nuevo y pasaba lo mismo.... hablo del 12f683 el pin An3(#3) ...

Ojala alguien tenga idea de lo que pasa y puedar iluminarnos mas acerca del tema.
Un Abraso...