Autor Tema: problema raro con adc del 18f452  (Leído 1641 veces)

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

Desconectado fastyx2

  • PIC16
  • ***
  • Mensajes: 109
problema raro con adc del 18f452
« en: 12 de Marzo de 2015, 21:14:28 »
Amigos: he utilizado mil y una vez los adc del pic.nunca el del 18f452.

colocando un pote de 10k para hacer una lectura de su punto medio en A0 ,alimentado en 5 volts , obtengo una progresion del valor medido con el tester como si el pote fuera ultralogaritmico, el 80 % del giro para medir de cero a 0,30 vlots y luego el 20 restante hasta los 5 volts.Si le quito la carga al pote varia linealmente , pero en cuanto lo coloco a A0 ocurre lo anterior.Hice la prueba de colocar un operacional en seguidor de emisor y hace lo mismo. al seguidor de emisor lo desconecté de A0 y en la salida le fui colocando resistencias entre la salida y masa del op. hasta que simule lo mismo que le ocurre conectando a A0 : la resistencia equivalente que hace que el op empiece a mermar su salida es de 30 ohm.

Repasé configuraciones ,el pin del A0 esta en entrada , los tiempos de adquisicion de adc estan garantizados.Cambié el pic pensando e nalguna falla y nada.

Puede ser que el CCs (compilador ) se trague alguna configuracion ( bugg ) del puerto A y produzca esto?

Desde ya gracias!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: problema raro con adc del 18f452
« Respuesta #1 en: 12 de Marzo de 2015, 21:34:21 »
Creo que el programa seria util... pero no tiene nada raro. Si hay un problema con el programa alguien que sea CCS te lo podra responder. Yo sigo prefiriendo modificar los registros.

Por el comportamiento parece raro. Podrias indicar los valores que toman los registros ADCON0, ADCON1 y TRISA ? Al momento de leerlo.

Tenes que tener cuidado al colocar solamente un potenciometro solo ya que si pones a 5V directo el pin estarias quemando la entrada por que te pasarias de corriente, deberias de tener una resistencia limitadora entre el pin intermedio del del potenciometro y del PIC, esto afectaria a el tiempo de adquisicion pero te salvaria en caso que bajes la resistencia del potenciometro mucho.

Desconectado fastyx2

  • PIC16
  • ***
  • Mensajes: 109
Re: problema raro con adc del 18f452
« Respuesta #2 en: 17 de Marzo de 2015, 21:12:34 »
Gracias por contestar!

la verdad es que como siempre programé en C no conozco como consultar los valores de adcon :lol:

como envidio sanamente a la gente que programa en assembler  :D :D

respecto de los 5 volts a la entrada del A0.. si tengo una impedancia interna de 10k , por que habría de pasarse de corriente ? 5v/10kohm = 0.5 mA


coloco el programa por si alguien quiere ojearlo...

este es el archivo .C

include "C:\Documents and Settings\clo\Escritorio\voltimetro penta ok\voltimetro.h"
  #ZERO_RAM


void main()
{

   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   ///setup_adc(ADC_CLOCK_DIV_2);
   ///setup_psp(PSP_DISABLED);
   ///setup_spi(FALSE);
   ///setup_wdt(WDT_OFF);
   ///setup_timer_0(RTCC_INTERNAL);
   ///setup_timer_1(T1_DISABLED);
   ///setup_timer_2(T2_DISABLED,0,1);
   ///setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   ///set_adc_channel(0);
   porta = 0b00000000 ; trisa = 0b11100000 ;    //aqui A0 esta declarado como entrada
   portb = 0b00000000 ; trisb = 0b00000000 ;
   portc = 0b00000000 ; trisc = 0b00000000 ;
   portd = 0b00000000 ; trisd = 0b00000000 ;
   porte = 0b00000000 ; trise = 0b00000000 ;



   while (true)

   {  
     int x;
     set_adc_channel(0);delay_us ( 50 ) ; //esta es una redundancia ( elegir el chanel permanentemente)que la coloqué por las dudas...

    
      x ++ ;
      if ( x == 50 ) x = 0 ;
      if ( x == 5 )                        //con esto elijo el momento en que quiero que tome el valor ( frec de muestreo)
      {
      volt = read_adc () ; delay_us ( 50 ) ;                        //uso un valor de 1000 como maximo para limitar el int16 que es volt
      if ( volt > 999 ) volt = 999 ;
      }
      
      {
        
      unidad  = volt/100 ;

      decena  = (volt/10 )-(unidad*10 )  ;

      centena = volt - ( unidad* 100 ) - ( decena * 10 ) ;
      }
      //aqui tuve que desarrollar las funciones ya que esta version de ccs no me deja colocar el nombre e invocarla :5]
      {
      if      ( unidad == 0 ) { null ;cero   ;}
      else if ( unidad == 1 ) { null ;uno    ;}
      else if ( unidad == 2 ) { null ;dos    ;}
      else if ( unidad == 3 ) { null ;tres   ;}
      else if ( unidad == 4 ) { null ;cuatro ;}
      else if ( unidad == 5 ) { null ;cinco  ;}
      else if ( unidad == 6 ) { null ;seis   ;}
      else if ( unidad == 7 ) { null ;siete  ;}
      else if ( unidad == 8 ) { null ;ocho   ;}
      else if ( unidad == 9 ) { null ;nueve  ;}
      }
      
      
      on_uni = 1; delay_ms ( 2) ;
      
      on_uni = 0 ;
      
      {
      if      ( decena == 0 ) { null ;cero   ;}
      else if ( decena == 1 ) { null ;uno    ;}
      else if ( decena == 2 ) { null ;dos    ;}
      else if ( decena == 3 ) { null ;tres   ;}
      else if ( decena == 4 ) { null ;cuatro ;}
      else if ( decena == 5 ) { null ;cinco  ;}
      else if ( decena == 6 ) { null ;seis   ;}
      else if ( decena == 7 ) { null ;siete  ;}
      else if ( decena == 8 ) { null ;ocho   ;}
      else if ( decena == 9 ) { null ;nueve  ;}
      };
      
      
      on_dec = 1 ; delay_ms ( 2 ) ;
      
      on_dec =  0 ;

      
      {
      if      ( centena == 0 ) { null ;cero   ;}
      else if ( centena == 1 ) { null ;uno    ;}
      else if ( centena == 2 ) { null ;dos    ;}
      else if ( centena == 3 ) { null ;tres   ;}
      else if ( centena == 4 ) { null ;cuatro ;}
      else if ( centena == 5 ) { null ;cinco  ;}
      else if ( centena == 6 ) { null ;seis   ;}
      else if ( centena == 7 ) { null ;siete  ;}
      else if ( centena == 8 ) { null ;ocho   ;}
      else if ( centena == 9 ) { null ;nueve  ;}
      }
      on_cent = 1 ; delay_ms ( 2 ) ;
      
      on_cent =  0 ;


      ///printf ( "Volt    es:%lu\n\n\r" , volt    ) ; delay_ms ( 500 ) ;
      ///printf ( "unidad  es:%lu\n\r"   , unidad  ) ; delay_ms ( 500 ) ;
      ///printf ( "decena  es:%lu\n\r"   , decena  ) ; delay_ms ( 500 ) ;
      ///printf ( "centena es:%lu\n\r"   , centena ) ; delay_ms ( 500 ) ;
      ///printf ( "metros  es:%lu,%lu%lu\n\n\n\n\r" , unidad,decena,centena  ) ; delay_ms ( 2000 ) ;

   }
}


y este es el archivo .h

include <18F452.h>
#device adc=10
#fuses NOWDT,WDT128,HS, NOPROTECT, NOOSCSEN, NOBROWNOUT, BORV20, PUT, NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(crystal= 10000000)                    //lo cambié por las dudas ...nada
///#use delay(clock=10000000)
///#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


#include "ini18Fx.h"
#ZERO_RAM
int8 x  ;
float mt ;
int16   volt  , unidad , decena , centena ;

#bit       a = portd.7
#bit       b = portb.1
#bit       c = portb.2
#bit       d = portb.3
#bit       e = portb.4
#bit       f = portb.5
#bit       g = portd.6
#bit  on_uni = portc.0                               // port c0 c1 y c2 son los multiplexores del display
#bit  on_dec = portc.1
#bit on_cent = portc.2
//el decimal va fijo
#define cero   a = b = g = f = e = c = 1
#define uno    b = g = 1
#define dos    a = b = d = f = e = 1
#define tres   a = b = d = g = f = 1
#define cuatro c = d = b = g = 1
#define cinco  a = c = d = g = f = 1
#define seis   a = c = d = g = f = e = 1
#define siete  a = b = g = 1
#define ocho   a = b = g = f = e = c = d = 1
#define nueve  a = b = g = d = c = 1
#define null   a = b = g = f = e = c = d = 0

void unid    ( ) ;
void decen   ( ) ;
void cent    ( ) ;
void convert ( ) ;

unid ()
{
      if      ( unidad == 0 ) { null ;cero   ;}
      else if ( unidad == 1 ) { null ;uno    ;}
      else if ( unidad == 2 ) { null ;dos    ;}
      else if ( unidad == 3 ) { null ;tres   ;}
      else if ( unidad == 4 ) { null ;cuatro ;}
      else if ( unidad == 5 ) { null ;cinco  ;}
      else if ( unidad == 6 ) { null ;seis   ;}
      else if ( unidad == 7 ) { null ;siete  ;}
      else if ( unidad == 8 ) { null ;ocho   ;}
      else if ( unidad == 9 ) { null ;nueve  ;}
}
decen ()
{
      if      ( decena == 0 ) { null ;cero   ;}
      else if ( decena == 1 ) { null ;uno    ;}
      else if ( decena == 2 ) { null ;dos    ;}
      else if ( decena == 3 ) { null ;tres   ;}
      else if ( decena == 4 ) { null ;cuatro ;}
      else if ( decena == 5 ) { null ;cinco  ;}
      else if ( decena == 6 ) { null ;seis   ;}
      else if ( decena == 7 ) { null ;siete  ;}
      else if ( decena == 8 ) { null ;ocho   ;}
      else if ( decena == 9 ) { null ;nueve  ;}
}
cent ()
{
      if      ( centena == 0 ) { null ;cero   ;}
      else if ( centena == 1 ) { null ;uno    ;}
      else if ( centena == 2 ) { null ;dos    ;}
      else if ( centena == 3 ) { null ;tres   ;}
      else if ( centena == 4 ) { null ;cuatro ;}
      else if ( centena == 5 ) { null ;cinco  ;}
      else if ( centena == 6 ) { null ;seis   ;}
      else if ( centena == 7 ) { null ;siete  ;}
      else if ( centena == 8 ) { null ;ocho   ;}
      else if ( centena == 9 ) { null ;nueve  ;}
}

convert ( )
{
        
      unidad  = volt/100 ;

      decena  = (volt/10 )-(unidad*10 )  ;

      centena = volt - ( unidad* 100 ) - ( decena * 10 ) ;
}
« Última modificación: 17 de Marzo de 2015, 21:27:09 por fastyx2 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: problema raro con adc del 18f452
« Respuesta #3 en: 17 de Marzo de 2015, 21:35:32 »
Citar
unidad  = volt/100 ;

      decena  = (volt/10 )-(unidad*10 )  ;

      centena = volt - ( unidad* 100 ) - ( decena * 10 ) ;

Ese es tu problema. No sabes como calcular la tension.

Lo que te va a dar volt = read_adc ()
Va a ser un numero de 0 a 1023 en caso de ser de 10 bits
Que representa de 0V a 5V

Es decir 999 significa:  
(999/1024) * 5V = 4.87V

Para obtener el valor en volts (volt es una variable tipo float):
       volt = read_adc() * 5;
       volt = volt / 1024;

Lo que obtenes vos en tu codigo en la salida es solamente el resultado del ADC



Otra de las cosas... por que crear esto, con 7 variables ( 7 registros )

Código: [Seleccionar]
#define cero   a = b = g = f = e = c = 1
#define uno    b = g = 1
#define dos    a = b = d = f = e = 1
#define tres   a = b = d = g = f = 1
#define cuatro c = d = b = g = 1
#define cinco  a = c = d = g = f = 1
#define seis   a = c = d = g = f = e = 1
#define siete  a = b = g = 1
#define ocho   a = b = g = f = e = c = d = 1
#define nueve  a = b = g = d = c = 1
#define null   a = b = g = f = e = c = d = 0

Pudiendo hacer un array simple

Código: [Seleccionar]
const char SegCode[11] = {0x40,0x57,0x22,0x06,0x15,0x0C,0x08,0x56,0x00,0x04,0xFF};
   //                       0    1    2    3    4    5    6    7    8    9
Donde cada valor corresponde al numero en cuestion, cada bit seria un segmento y lo pones de acuerdo a tu conexion de HW. Podes usar el ultimo bit para el punto.

Luego vas a tener que sacar de ese valor "float" o entero ( si no te interesa la coma ) los valores de centena,decena, unidad ( depediendo la escala que uses)



En tu programa tenes esto:  //uso un valor de 1000 como maximo para limitar el int16 que es volt

Tu salida deberia ser de 10 bits, a no ser que esten justificados hacia la izquierda ( pero deberian de justificarcarse a la derecha ). De 10 a 16 bits hay mucho lo cual no deberias tener ningun problema., Incluso podrias promediar varios valores de esa forma obtenes una lectura mas estable. ( Si es que varia mucho )



A mi parecer:
Los .h son cabeceras, no deberian tener funciones como las que tenes, a lo sumo un macro.
Y toda la configuracion, directivas de preprocesamietno # , fuses, deberian estar en el main



Odio CCS por que te abstrae de los registros y no tenes ni idea de como esta configurado, por eso te pedi que me dieras como quedaba configurado el ADCON0/1 y TRISA
« Última modificación: 17 de Marzo de 2015, 23:08:13 por KILLERJC »