Autor Tema: Como activar los valores de ADC 10 bits  (Leído 13669 veces)

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

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Como activar los valores de ADC 10 bits
« en: 03 de Noviembre de 2010, 16:44:25 »
Hola, estoy tratando de asignarle a una variable int16 un valor de 10 bits del ADC de un 16f876a
Pero me devuelve solo ocho bits.

mi codigo en el header (16f876a.h) es el siguiente:
#device PIC16F876A
#device ADC=10

Mi programa es el siguiente

#if defined(__PCM__) //.
#include <16F876A.h>
#include <stdlib.h>
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT
#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)

int16 temp;
int value;
float tempan1;
float voltsan0;
void main(void){


set_tris_b (0x00);
while (TRUE){
setup_adc (adc_clock_div_32);
setup_adc_ports (ALL_ANALOG);
set_adc_channel (0); //Elige canal a medir RA0
delay_us (20);
value=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)

set_adc_channel (1); //Elige canal a medir RA0
delay_us (20);
temp=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)

   voltsan0 = 5.0 - (value * (5.0 / 256.0 ));
   tempan1 = temp * (5.0*100.0/256.0);

   
   printf("Valor volts, temp, hextempout:: %1.2f, %2.2f , %4X\n\r", voltsan0, tempan1, temp);
   output_high(PIN_B1); //(34)
   delay_ms(500);
   output_low(PIN_B1);
   delay_ms(500);
}
}   

gracias

Desconectado manwenwe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2211
Re: Como activar los valores de ADC 10 bits
« Respuesta #1 en: 03 de Noviembre de 2010, 16:51:10 »
Hola,

no programo en CCS pero por lo pronto me parece interesante que "castees" los enteros a float antes de operar con ellos... es probable que el "casteo" por defecto de CCS te coja por defecto un INT8 cuando se trata de un entero....

voltsan0 = 5.0 - ((float)value * (5.0 / 256.0 ));
tempan1 = (float)temp * (5.0*100.0/256.0);

No te aseguro que sea esto...

Saludos
Ojo por ojo y todo el mundo acabará ciego - Mahatma Gandhi -

Desconectado AKENAFAB

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3227
Re: Como activar los valores de ADC 10 bits
« Respuesta #2 en: 03 de Noviembre de 2010, 17:02:53 »
temp si lo tienes como int16 pero value lo tienes como int .


Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como activar los valores de ADC 10 bits
« Respuesta #3 en: 03 de Noviembre de 2010, 17:05:11 »
En teoría no es necesario hacer cast porque según las reglas de promoción automática de expresiones , el compilador hará las conversiones necesarias para llevar todos los operandos al tipo mayor, y al indicar 5.0, 256.0, el tipo mayor es float, pero bueno es CCS así que se puede esperar cualquier cosa  :D Lo que veo si, es que Value es de 8 bits, en cambio Temp si es de 16-bits.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado manwenwe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2211
Re: Como activar los valores de ADC 10 bits
« Respuesta #4 en: 03 de Noviembre de 2010, 17:14:15 »
En teoría no es necesario hacer cast porque según las reglas de promoción automática de expresiones , el compilador hará las conversiones necesarias para llevar todos los operandos al tipo mayor, y al indicar 5.0, 256.0, el tipo mayor es float, pero bueno es CCS así que se puede esperar cualquier cosa  :D Lo que veo si, es que Value es de 8 bits, en cambio Temp si es de 16-bits.


Saludos!

Estoy de acuerdo... pero a veces el cast automático te juega malas pasadas; p.e. si no casteas un literal en una operación con una variable... el resultado va efectivamente al tipo "mayor": al de la variable. Es decir: si un int8 como var= 100 ==>> 10*var = (1000%255) en vez de 1000... no se si me explico???

Saludos
Ojo por ojo y todo el mundo acabará ciego - Mahatma Gandhi -

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Como activar los valores de ADC 10 bits
« Respuesta #5 en: 03 de Noviembre de 2010, 18:12:57 »
HOla, gracias por las respuestas tan rapidas.
Converti las la variable temp a int16 y sigue igual

De paso lei en la ayuda del compilador una constante que se llama con getenv y te devuelve el valor de bits ADC
getenv("ADC_RESOLUTION");

La ejecute y me esta devolviendo 10, asi que el pic esta funcionando a 10 evidentemente, ahora el tema es que me devuelve 8.
Me dijeron que en asembler hay que tomar los 2 bytes por separado.
Puede ser?
gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Como activar los valores de ADC 10 bits
« Respuesta #6 en: 03 de Noviembre de 2010, 18:15:03 »
Value es la variable de 8-bits  :mrgreen:
No contesto mensajes privados, las consultas en el foro

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Como activar los valores de ADC 10 bits
« Respuesta #7 en: 03 de Noviembre de 2010, 19:55:48 »
Hola lopb, estuve mirando tu programa y le veo algunas inconsistencias.   Sabiendo que el valor que va a devolver read_adc() es de 10 bits,  debes configurar a las dos variables que va a leer el ADC como long temp, value;.  La instrucción de configuración set_tris() no debe ir dentro del bucle y finalmente en los cálculos para 10 bits los debes hacer basado en 1024 (10 bits) y no en 256 (8bits).  Te ordené un poco el código para que lo ensayes y nos cuentes como te va:

Código: [Seleccionar]
#include <16F876A.h>
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=20000000)

#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)

long temp, value;
float tempan1, voltsan0;

void main(void)
{
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   set_tris_b (0x00);

   while (TRUE)
   {
      set_adc_channel (0); //Elige canal a medir RA0
      delay_us (20);
      value=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)
  
      set_adc_channel (1); //Elige canal a medir RA0
      delay_us (20);
      temp=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)

      voltsan0 = 5.0 - (value * (5.0 / 1024.0 ));
      tempan1 = temp * (5.0 * 100.0 / 1024.0);

  
      printf("Valor volts, temp, hextempout:: %1.2f, %2.2f , %4X\n\r", voltsan0, tempan1, temp);
      output_high(PIN_B1); //(34)
      delay_ms(500);
      output_low(PIN_B1);
      delay_ms(500);
   }
}

Por curiosidad, para que es la variable tempan1?

Saludos!
« Última modificación: 03 de Noviembre de 2010, 23:47:52 por bmb »

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Como activar los valores de ADC 10 bits
« Respuesta #8 en: 04 de Noviembre de 2010, 11:52:30 »
Hola lopb, estuve mirando tu programa y le veo algunas inconsistencias.   Sabiendo que el valor que va a devolver read_adc() es de 10 bits,  debes configurar a las dos variables que va a leer el ADC como long temp, value;.  La instrucción de configuración set_tris() no debe ir dentro del bucle y finalmente en los cálculos para 10 bits los debes hacer basado en 1024 (10 bits) y no en 256 (8bits).  Te ordené un poco el código para que lo ensayes y nos cuentes como te va:

Código: [Seleccionar]
#include <16F876A.h>
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=20000000)

#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)

long temp, value;
float tempan1, voltsan0;

void main(void)
{
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   set_tris_b (0x00);

   while (TRUE)
   {
      set_adc_channel (0); //Elige canal a medir RA0
      delay_us (20);
      value=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)
  
      set_adc_channel (1); //Elige canal a medir RA0
      delay_us (20);
      temp=read_adc(); //Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)

      voltsan0 = 5.0 - (value * (5.0 / 1024.0 ));
      tempan1 = temp * (5.0 * 100.0 / 1024.0);

  
      printf("Valor volts, temp, hextempout:: %1.2f, %2.2f , %4X\n\r", voltsan0, tempan1, temp);
      output_high(PIN_B1); //(34)
      delay_ms(500);
      output_low(PIN_B1);
      delay_ms(500);
   }
}

Por curiosidad, para que es la variable tempan1?

Saludos!
EDITADO:
Bmb, te pasaste en darme un codigo  :)
Sos muy amable.

Bueno, en conclusion les cuento que los valores aun oscilan. Tengo temperaturas desde 19 grados a 24, con este ultimo codigo.
Habia puesto una respuesta anterior que funcionaba, pero me equivoque y tenia conectada la entrada analogica a un divisor resistivo que me entrega media fuente para ver si la salida hexa se imprime en 10 bits. Pero no, sigue trabajando en ocho bits, a pesar de que se que esta en 10 bit por la funcion getenv("ADC_RESOLUTION");

 :huh:
« Última modificación: 04 de Noviembre de 2010, 13:03:09 por lopb »

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Como activar los valores de ADC 10 bits
« Respuesta #9 en: 04 de Noviembre de 2010, 18:04:39 »
Bueno, en conclusion les cuento que los valores aun oscilan. Tengo temperaturas desde 19 grados a 24, con este ultimo codigo.

Ensaya cambiando esta instrucción: setup_adc(ADC_CLOCK_DIV_32); por esta: setup_adc(ADC_CLOCK_INTERNAL);

Que tipo de sensor de temperatura le tienes? Como está conectado?  Si puedes subir el circuito mejor.

Saludos!

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Como activar los valores de ADC 10 bits
« Respuesta #10 en: 05 de Noviembre de 2010, 16:51:21 »
Bueno, en conclusion les cuento que los valores aun oscilan. Tengo temperaturas desde 19 grados a 24, con este ultimo codigo.

Ensaya cambiando esta instrucción: setup_adc(ADC_CLOCK_DIV_32); por esta: setup_adc(ADC_CLOCK_INTERNAL);

Que tipo de sensor de temperatura le tienes? Como está conectado?  Si puedes subir el circuito mejor.

Saludos!
Es un lm35, el circuito no lo tengo aun, estoy haciendo pruebas.
El lm35 tiene 3 patitas, dos son alimentacion y una va directo a an1 del 16f.
Los valores oscilan bastane, yo supongo porque esta trabajando en 8 bits o hay un error de quantizacion.
voy a probar con eso que me dijiste =

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Como activar los valores de ADC 10 bits
« Respuesta #11 en: 05 de Noviembre de 2010, 19:16:03 »
Mmmmhh, creo que mejor le das una mirada a este enlace donde el colega dogflu66 plantea un acondicionador de señal para el LM35.

Saludos!

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Como activar los valores de ADC 10 bits
« Respuesta #12 en: 08 de Noviembre de 2010, 10:54:55 »
Mmmmhh, creo que mejor le das una mirada a este enlace donde el colega dogflu66 plantea un acondicionador de señal para el LM35.

Saludos!
No se si armar ese circuito... a mi me parece que el problema viene por otro lado.
El conversor esta trabajando en 10 bits pero a la variable se le asignan unicamente los primeros 8 bits, debe ser algun error muy simple.
pero no se me ocurre que.

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Como activar los valores de ADC 10 bits
« Respuesta #13 en: 08 de Noviembre de 2010, 13:50:42 »
Por lo que puedo ver en la hoja de datos del LM35 está dando 10 mV por grado centígrado.  Teniendo en cuenta que el voltaje de referencia de ADC que tienes actualmente configurado es el mismo de la fuente del PIC (5V) y suponiendo que la temperatura es de 25ºC:

Salida del LM35 = 25º * 0.01V = 0.25 Voltios
1024 / 5 * 0.25 = 51 aprox.

Como puedes ver para una temperatura de 25 grados centígrados el ADC del micro te estará entregando un valor de aproximadamente 51 que es por supuesto un valor de 8 bits y que con cualquier mínima variación se va a ver reflejada en el valor de la temperatura debido a la muy baja resolución.  Por eso es que se hace necesario implementar un acondicionador de señal.  Otra solución es que le pongas al PIC un voltaje de referencia muy bajo correspondiente digamos al valor máximo de salida que te va a dar el LM35.

Saludos!

Edito: por cierto me acabo de dar cuenta que el voltaje en AN0 no sería: voltsan0 = 5.0 - (value * (5.0 / 1024.0 )); sino que sería: voltsan0 = value * 5.0 / 1024.0;

« Última modificación: 08 de Noviembre de 2010, 14:21:50 por bmb »

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Como activar los valores de ADC 10 bits
« Respuesta #14 en: 08 de Noviembre de 2010, 15:48:34 »
Por lo que puedo ver en la hoja de datos del LM35 está dando 10 mV por grado centígrado.  Teniendo en cuenta que el voltaje de referencia de ADC que tienes actualmente configurado es el mismo de la fuente del PIC (5V) y suponiendo que la temperatura es de 25ºC:

Salida del LM35 = 25º * 0.01V = 0.25 Voltios
1024 / 5 * 0.25 = 51 aprox.

Como puedes ver para una temperatura de 25 grados centígrados el ADC del micro te estará entregando un valor de aproximadamente 51 que es por supuesto un valor de 8 bits y que con cualquier mínima variación se va a ver reflejada en el valor de la temperatura debido a la muy baja resolución.  Por eso es que se hace necesario implementar un acondicionador de señal.  Otra solución es que le pongas al PIC un voltaje de referencia muy bajo correspondiente digamos al valor máximo de salida que te va a dar el LM35.

Saludos!

Edito: por cierto me acabo de dar cuenta que el voltaje en AN0 no sería: voltsan0 = 5.0 - (value * (5.0 / 1024.0 )); sino que sería: voltsan0 = value * 5.0 / 1024.0;


Hola, error mio!
resulta que la fuente no tenia filtrado y el micro estaba conmutando mientras leia y caia un poco la tension, por ende el valor de referencia del micro en este caso vref+ y - variaban un poco de modo que la salida final tambien variaba.
Ahora esta filtrado con un capacitor para altas y bajas, y ya se estabilizo la medicion.
Respecto a el valor de 10 bits, pude imprimir la variable, pase todas a float y la converti en una cadena y la imprimi sobre el display (porque desactive el rs232).
Gracias por su ayuda.
Lo unico que no entendi es que estaba imprimiendo el valor en hexa de temp y me daba ff cuando estaba lleno y 3f a media fuente, lo cual me dio la impresion de que la variable estaba en 8 bits, pero despues lo reviso bien y les cuento.

Para que quede, use getenv("ADC_RESOLUTION") para ver si estaba en 10 bits el micro.

salu2