Autor Tema: [Solucionado] problema de rango de voltage en convertidor ADC  (Leído 3333 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado alraid

  • PIC10
  • *
  • Mensajes: 7
hola foreros,

estoy haciendo mi proyecto final de carrera que consiste en disenyar e implementar un medidor de campo magnético con un sensor para despues tratar la señal en un PIC 16F876 y mostrar el resultado por una pantalla LCD. El programa ya lo tengo hecho y siulado por Proteus funciona perfectamente pero a la hora de montarlo es donde surgio el problema.

El rango de la señal que entro al PIC para la conversión A/D por la entrada analógica es de 0 a 5 Voltios, que es el voltage con el que alimento el PIC. El caso es que a la hora de representar el resultado por la pantalla LCD no me calcula valores más altos de 4 Voltios ni más pequeños de 1 Voltio, como si el rango del PIC fuera de 1 a 4 Voltios en vez de 0 a 5. A partir del valor equivalente a 4 Voltios ya no me da más resultado aunque le introduzca al PIC en la entrada analógica un valor de 4,5.

Como en la silución por proteus sale perfecta y como en la entrada analógica realmente entran valores de 0 a 5 Voltios creo que es un problema del propio PIC y me tiene bastante desconcertado.

Muchas gracias
« Última modificación: 25 de Enero de 2013, 08:21:37 por alraid »

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: problema de rango de voltage en convertidor ADC
« Respuesta #1 en: 21 de Enero de 2013, 09:00:32 »
Alraid!
Eso pudiera pasar si la impedancia del elemento que estas conectando a la entrada del adc es muy alta, creo que el fabricante del pic recomienda que esta sea menor de 10Kohm.
Prueba utilizando un potenciometro de 5 o 10Kohm, como divisor de tension y nos comentas  :mrgreen:

Saludos

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: problema de rango de voltage en convertidor ADC
« Respuesta #2 en: 21 de Enero de 2013, 10:41:05 »
Usas un amplificador operacional como etapa amplificadora?
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado alraid

  • PIC10
  • *
  • Mensajes: 7
Re: problema de rango de voltage en convertidor ADC
« Respuesta #3 en: 22 de Enero de 2013, 07:02:43 »
Sí ppyote. Utilizo un amplificador operacional para adaptar mi señal al rango del PIC. Concretramente una etapa amplificadora restadora de ganancia 1.

Ralf2 viendo tu comentario he calculado con un tester la resistència que provoca esa etapa i es de 5,5kohms. Luego he quitado un condensador cerámico de 100nF que tenia en paralelo entre la salida del operacional y la entrada del PIC que tenía colocado para acabar de filtrar la señal pero aún así el problema persiste.

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: problema de rango de voltage en convertidor ADC
« Respuesta #4 en: 22 de Enero de 2013, 07:48:11 »
Mide la salida de la etapa amplificadora puesto que podía ser problema de esta. Podría ser  que estas teniendo problemas con el offset del amplificador operacional, a mi me pasó lo mismo ya que del amplificador sólo me cubría el rango de 1v y 4v 
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: problema de rango de voltage en convertidor ADC
« Respuesta #5 en: 22 de Enero de 2013, 08:32:33 »
Alraid si conectas directamente los 5V de la alimentacion del pic a la entrada del adc no te aparecen los 5V en la lcd?
Haz probado con otro pic?
En caso tal que hallas hechos todas esas pruebas y verificado los voltajes con un tester, entonces podrias colocar el hardware y el software que hiciste para verlo?

Saludos

Desconectado alraid

  • PIC10
  • *
  • Mensajes: 7
Re: problema de rango de voltage en convertidor ADC
« Respuesta #6 en: 22 de Enero de 2013, 08:46:51 »
la salida de voltage del operacional es la correcta de 0 a 5V. Mañana probarén conectar directamente 5 Voltios por la entrada analògica sin pasar por la etapa amplificadora haber que pasa. Si persiste el problema mañana os cuelgo el codigo de programa.

Gràcias por vuestro interés.

Desconectado flacoclau

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1692
    • El Micro Reactor
Re: problema de rango de voltage en convertidor ADC
« Respuesta #7 en: 22 de Enero de 2013, 15:29:44 »
Me parece que el término que quiso utilizar ppyote es "Swing" y es el rango de tensión que puede cubrir la salida del operacional de acuerdo a la alimentación. Generalmente un operacional alimentado con 5V no llega a esta tensión a la salida debido a cuestiones de los transistores de salida, hay sin embargo un tipo de operacional que se denomina "Rail to rail" el cual puede llevar la tensión de salida a valores muy próximos a los de alimentación. Yo generalmente utilizo los LM358 (Dual AO) que es una especie de semi rail to rail, ya que su valor mínimo llega muy próximo a los 0V, pero no así a la tensión superior. También tiene estas características el LM324 (quad AO).

Lo que me extraña es que el rango sea tan corto, en una de esas todo sea cuestion de programación o de algún error de diseño.
Las personas con buena ortografía me atraen textualmente.

El Micro Reactor

Córdoba capital - Argentina.

Desconectado KALLITOS

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1256
Re: problema de rango de voltage en convertidor ADC
« Respuesta #8 en: 22 de Enero de 2013, 16:01:09 »
Verifica en el seteo del micro y los pines de voltaje de referencia.
por alli podria estar el problema.

saludos.
A un microcontrolador hay que sacarle hasta el ultimo byte....(YO)

Cómo puede ser que un pic24EP512 me quede corto de memoria, señores de MICROCHIP saquen pics con más memoria flash

Más de 45 mil lineas de codigo y aun no termino el equipo, asu mare!!

S34ML08G1TFI200 no necesito mas memoria externa.

Desconectado soymoe

  • PIC18
  • ****
  • Mensajes: 456
    • El blog de Moe
Re: problema de rango de voltage en convertidor ADC
« Respuesta #9 en: 22 de Enero de 2013, 16:06:34 »
anda por parte, saca la etapa de acondicionamiento de señal y reemplazala por un divisor de tension para obtener todo el rango de tensiones de 0 a 5v y verifica que funcione la rutina de conversion.

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: problema de rango de voltage en convertidor ADC
« Respuesta #10 en: 22 de Enero de 2013, 16:20:51 »
Cita de: flacoclau link=topic=39996.m :lol:sg333054#msg333054 date=1358879384
Me parece que el término que quiso utilizar ppyote es "Swing" y es el rango de tensión que puede cubrir la salida del operacional de acuerdo a la alimentación. Generalmente un operacional alimentado con 5V no llega a esta tensión a la salida debido a cuestiones de los transistores de salida, hay sin embargo un tipo de operacional que se denomina "Rail to rail" el cual puede llevar la tensión de salida a valores muy próximos a los de alimentación. Yo generalmente utilizo los LM358 (Dual AO) que es una especie de semi rail to rail, ya que su valor mínimo llega muy próximo a los 0V, pero no así a la tensión superior. También tiene estas características el LM324 (quad AO).

Lo que me extraña es que el rango sea tan corto, en una de esas todo sea cuestion de programación o de algún error de diseño.

a eso precisamente me refería, pero por no enrollarme escribiendo y editando con el móvil lo he dejado así
gracias por una mejor explicación flacoclau
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: problema de rango de voltage en convertidor ADC
« Respuesta #11 en: 22 de Enero de 2013, 16:50:02 »
alraid
Lo que indican los amigos sobre las limitaciones del op amp son correctas el operacional tiene unos voltajes de saturacion que limitan el maximo voltaje de salida y el minimo de estos, como sabes, por eso no tendras los 5V a la salida si los almentas con 5V, ni 0V,  a menos que sean del tipo rail to rail, creo  :mrgreen:

Aqui, puedes ver un ejemplo   :mrgreen:

No obstante como te indique arriba y como los compañeros señalan, elimina la etapa acondicionadora y metele 5V directo o por un divisor de tension al pic debes leer 5V en la lcd, sino saca por la lcd tambien el valor del adc que deberia ser 1023 si operas a 10bits o 255 si operas a 8 bits.
Haber si el problema esta en otra parte y si tienes un pic de sobra prueba tambien con el.

Saludos
« Última modificación: 23 de Enero de 2013, 04:13:31 por RALF2 »

Desconectado alraid

  • PIC10
  • *
  • Mensajes: 7
Re: problema de rango de voltage en convertidor ADC
« Respuesta #12 en: 23 de Enero de 2013, 08:06:43 »
Gràcias a todos por las respuestas pero acabo de probar de alimenar directamente la entrada analógica con 5V sin la etapa amplificadora y el problema persiste, aunque le entre 5V el PIC ve 4V. Además el problema de swing ja lo tuve en su momento y por eso alimento el operacional com -8V y 8V.

Despues de la prueba de hoy de conectar directamente 5V y que no funcione veo que el problema es del PIC o de la programación. Os dejo el codigo del programa.

#include <16f876.h>                                                           
#device adc=10                                                                 
#FUSES XT,NOWDT                                                               
#use delay (clock=2000000)                                                   
#include <lcd420.c>                                                           

                                                                             
   float b;                                                                   
   float valor;                                                               
   float G=1.0;                                                               
   int8 unitat=1;                                                             
   short n=0;                                                                 
                                                                             
////////////////////////////////////////////////////////////////////////////////
//                         Funciones del programa                                    //
////////////////////////////////////////////////////////////////////////////////
                                                                             
void menu2()                                                                 
{                                                                             
    printf(lcd_putc, "1-GAUSS  2-TESLA\n");                                   
    printf(lcd_putc, "3-VOLT   4-ANT\n");                                     
}                                                                             
                                                                             
void menu1()                                                                 
{                                                                             
   printf(lcd_putc, "1-MESURA\n");                                           
   printf(lcd_putc, "2-UNITATS  3-SEG\n");                                   
}                                                                             
                                                                             
void menu3()                                                                 
{                                                                               
   printf(lcd_putc, "1-GUANY    3-ANT\n");                                   
   printf(lcd_putc, "\n");                                                   
}                                                                             
                                                                             
void ant4()                                                                   
{                                                                             
   printf(lcd_putc, "\n           4-ANT");                                   
}                                                                             
                                                                             
void menys()                                                                 
{                                                                                 
 printf(lcd_putc, "\fG=%01.2f  4-ANT" , G);                                   
 printf(lcd_putc, "\n1:- 2:0.1 3:0.01");                                     
 delay_ms(250);                                                               
}                                                                             
                                                                             
void mes()                                                                   
{                                                                             
 printf(lcd_putc, "\fG=%01.2f  4-ANT\n" , G);                                 
 printf(lcd_putc, "1:+ 2:0.1 3:0.01\n");                                     
 delay_ms(250);                                                               
}                                                                             
                                                                             
////////////////////////////////////////////////////////////////////////////////
//                      Función principal del programa                             //
////////////////////////////////////////////////////////////////////////////////
//                                                                                               //
////////////////////////////////////////////////////////////////////////////////
//                      Inicialización del programa                                   //
////////////////////////////////////////////////////////////////////////////////
                                                                             
void main() {                                                                 
                                                                             
   setup_adc_ports(all_analog);                                               
   setup_adc(ADC_CLOCK_INTERNAL);                                             
   lcd_init();                                                               
   printf(lcd_putc, "   BENVINGUTS\n");                                       
   delay_ms(2000);                                                             
   printf(lcd_putc, "\f");                                                                                       
   printf(lcd_putc, "   GAUSSIMETRE\n");                                     
   printf(lcd_putc, "     DIGITAL");                                         
   delay_ms(2000);                                                           
   inici:                                                                     
   printf(lcd_putc, "\f");                                                   
                                                                             
  for (;;)                                                                   
  {                                                                           
  menu1();                                                                                       
                                                                             
///////////////////////////////////////////////////////////////////////////////
//                      Programa para la  medida                                  //
////////////////////////////////////////////////////////////////////////////////
      if(input(pin_c0)==0)                                                   
         {                                                                   
         while (input(pin_c0)==0)                                             
            {                                                                 
            menu1();                                                                                 
            }                                                                 
           while (input(pin_c3)==1)                                           
               {                                                                             
               set_adc_channel(0);                                           
               valor=read_adc();                                             
               delay_ms(20);                                                 
               set_adc_channel(1);                                           
               b=read_adc();                                                 
               delay_ms(20);                                                 
               b=2.0*b/1024.0;                                               
               valor=(5.0*valor/1024.0);                                     
                                                                             
                  if (input(pin_c4)==1)                                       
                     {                                                       
                     if (unitat==1)                                           
                        {                                                     
                        valor=((G*200.0*valor)-(b*500));                     
                        printf(lcd_putc, "\f  %04.2f Gauss", valor);         
                        ant4();                                               
                        delay_ms(250);                                       
                        }                                                     
                     else if (unitat==3)                                     
                        {                                                     
                        printf(lcd_putc, "\f   %01.2f Volts", valor);         
                        ant4();                                               
                        delay_ms(250);                                       
                        }                                                     
                     else if (unitat==2)                                     
                        {                                                     
                        valor=((G*200.0*valor)-(b*500));                         
                        valor=valor*0.1;                                     
                        printf(lcd_putc, "\f  %04.2f mTeslas", valor);       
                        ant4();                                               
                        delay_ms(250);                                       
                        }                                                     
                     }                                                       
                  else if (input(pin_c4)==0)                                 
                     {                                                       
                     if(unitat==1)                                           
                        {                                                     
                        valor=((G*1000.0*valor)-(b*2500.0));                 
                        printf(lcd_putc, "\f  %04.2f Gauss", valor);                                                                             
                        ant4();                                                 
                        delay_ms(250);                                       
                        }                                                     
                     else if (unitat==3)                                     
                        {                                                     
                        printf(lcd_putc, "\f   %01.2f Volts", valor);         
                        ant4();                                               
                        delay_ms(250);                                       
                        }                                                     
                     else if (unitat==2)                                     
                        {                                                     
                        valor=((G*1000.0*valor)-(b*2500.0));                 
                        valor=valor*0.1;                                     
                        printf(lcd_putc, "\f  %04.2f mTeslas", valor);       
                        ant4();                                               
                        delay_ms(250);                                       
                        }                                                     
                     }                                                       
               }                                                             
      goto inici;                                                             
         }                                                                   
                                                                             
///////////////////////////////////////////////////////////////////////////////
//                   Programa para el cambio de unidades                      //
////////////////////////////////////////////////////////////////////////////////
      if(input(pin_c1)==0)                                                   
         {                                                                   
         while (input(pin_c1)==0)                                             
            {                                                                 
            menu1();                                                         
            }                                                                 
         printf(lcd_putc, "\f");                                               
            for(;;)                                                           
               {                                                             
               menu2();                                                       
                  if(input(pin_c0)==0)                                       
                     {                                                             
                       while (input(pin_c0)==0)                               
                        {                                                     
                        menu2();                                             
                        }                                                     
                                                                             
                     printf(lcd_putc, "\f");                                 
                     unitat=1;                                               
                     printf(lcd_putc, "  MESURA GAUSS\n");                   
                     delay_ms(1000);                                         
                     goto inici;                                             
                     }                                                       
                  if(input(pin_c1)==0)                                       
                     {                                                       
                     while (input(pin_c1)==0)                                 
                        {                                                     
                        menu2();                                             
                        }                                                     
                     printf(lcd_putc, "\f");                                 
                     unitat=2;                                               
                     printf(lcd_putc, "  MESURA TESLAS\n");                   
                     delay_ms(1000);                                         
                     goto inici;                                             
                     }                                                       
                  if(input(pin_c2)==0)                                       
                     {                                                       
                     while (input(pin_c2)==0)                                 
                        {                                                     
                        menu2();                                             
                        }                                                     
                     printf(lcd_putc, "\f");                                 
                     unitat=3;                                               
                     printf(lcd_putc, "  MESURA VOLTS\n");                   
                     delay_ms(1000);                                           
                     goto inici;                                             
                     }                                                       
                  if(input(pin_c3)==0)                                       
                     {                                                       
                     goto inici;                                             
                     }                                                       
               }                                                             
         }                                                                   
                                                                             
///////////////////////////////////////////////////////////////////////////////
//                   Programa para la variación de la ganancia                //
////////////////////////////////////////////////////////////////////////////////
      if(input(pin_c2)==0)                                                   
         {                                                                   
         while (input(pin_c2)==0)                                             
                  {                                                           
                  menu1();                                                   
                  }                                                           
         printf(lcd_putc, "\f");                                             
          for(;;)                                                             
            {                                                                 
            menu3();                                                         
            if(input(pin_c0)==0)                                             
               {                                                             
               while (input(pin_c0)==0)                                       
                  {                                                           
                  menu3();                                                   
                  }                                                           
               tornar:                                                       
               printf(lcd_putc, "\f");                                       
                  if(n==0)                                                   
                  {                                                           
                     for(;;)                                                 
                     {                                                       
                     mes();                                                   
                        if (input(pin_c0)==0)                                 
                        {                                                     
                           while (input(pin_c0)==0)                           
                           {                                                 
                           mes();                                             
                           }                                                 
                        n=1;                                                 
                        goto tornar;                                         
                        }                                                     
                        else if (input(pin_c1)==0)                           
                        {                                                     
                           while (input(pin_c1)==0)                           
                           {                                                 
                           mes();                                             
                           }                                                 
                        G=G+0.1;                                             
                        goto tornar;                                         
                        }                                                     
                        else if (input(pin_c2)==0)                           
                        {                                                     
                           while (input(pin_c2)==0)                           
                           {                                                 
                           mes();                                             
                           }                                                 
                        G=G+0.01;                                             
                        goto tornar;                                         
                        }                                                     
                        else if (input(pin_c3)==0)                           
                        {                                                     
                           while (input(pin_c3)==0)                           
                           {                                                 
                           mes();                                             
                           }                                                 
                        goto inici;      &n

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: problema de rango de voltage en convertidor ADC
« Respuesta #13 en: 23 de Enero de 2013, 08:26:50 »
Me parece (confirmarlo antes) que All_Analogs ()  habilita las dos Referencias también, es decir, que en ref+ deberías conectarle 5V y en ref- deberías conectarle gnd.
Ese puede ser tu problema...
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: problema de rango de voltage en convertidor ADC
« Respuesta #14 en: 23 de Enero de 2013, 10:03:20 »
  Yo creo que All_ANALOG dejaba todos como entradas analógicas pero utilizaba las referencias internas. He visto que cuando hace la selección de canal no espera el tiempo prudencial para hacer la lectura. Tal vez sea ese el error.

  En su código veo esto....

Código: C
  1. set_adc_channel(0);                                            
  2. valor=read_adc();                                              
  3. delay_ms(20);                                                  
  4. set_adc_channel(1);                                            
  5. b=read_adc();

  Y la espera debería estar entre la selección del canal "set_adc_channel(xxxx)" y la lecutra "x=read_adc()"
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything