Autor Tema: Problema ADC en Pic18f4550  (Leído 2257 veces)

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

Desconectado scheder

  • PIC10
  • *
  • Mensajes: 2
Problema ADC en Pic18f4550
« en: 04 de Febrero de 2015, 20:38:12 »
Hola buena tarde, espero me puedan ayudar con el siguiente problema, tengo un pic 18f4550, al cual le ingreso un voltaje de 3.5v en la patita AN0, esperando visualizar ese voltaje en un lcd16x2, sin embargo mis niveles (que van desde 0 a 1023, ya que uso el adc=10) cambian mucho y mi lcd me manda valores de 3.78, 3.72, 3.75, 3,80, y no se queda fijo

Ya me he roto la cabeza pero no puedo estabilizar la lectura de los niveles, cabe mencionar que el voltaje de entrada de 3.5 viene de una fuente de poder fija y estable que aparentemente no varia pues se mide a la par con el multimetro

Aqui mi codigo

#include <18f4550.h>         
#device adc=10
#FUSES HSPLL,PLL2,USBDIV,CPUDIV1,NOWDT,NOPROTECT,NOLVP
#use delay(clock=48M)

#define LCD_RS_PIN      PIN_B1                                    ////
#define LCD_RW_PIN      PIN_B2                                    ////
#define LCD_ENABLE_PIN  PIN_B3                                    ////
#define LCD_DATA4       PIN_B4                                    ////
#define LCD_DATA5       PIN_B5                                    ////
#define LCD_DATA6       PIN_B6                                    ////
#define LCD_DATA7       PIN_B7                                    ////
#include <lcd.c>

int16 nivel;
float voltaje;

void main()
{
lcd_init();
delay_ms(100);

setup_adc_ports(an0);
setup_adc(adc_clock_internal);

   for(;;)
   {
   delay_ms(10);
   set_adc_channel(0);
   delay_us(20);
   nivel=read_adc();
   voltaje=(5.0*nivel)/1023.0;
   delay_ms(1);
   
   lcd_gotoxy(1,1);
   printf(lcd_putc,"nivel=%lu",nivel);
   delay_ms(1);
   
   lcd_gotoxy(1,2);
   printf(lcd_putc,"voltaje=%fv",voltaje);
   delay_ms(1);
   }
}

Desconectado Daikataro

  • PIC10
  • *
  • Mensajes: 22
Re: Problema ADC en Pic18f4550
« Respuesta #1 en: 15 de Febrero de 2015, 21:54:59 »
Me imagino que estás armando todo en proto, y te digo por experiencia que los circuitos en protoboard son una antena gigantesca de atraer toda clase de ruido e interferencias; una vez que transfieres el circuito a una PCB, mucho de ese ruido se esfuma como por arte de magia.

Ahora, para ayudarte a estabilizar los valores, una buena práctica es el promediado, en el cual básicamente vas metiendo valores a una variable, y luego divides el total entre el número de veces que promediaste, por experiencia te digo que reduce mucho el error y estabiliza las mediciones. No me gusta el C, pero el algoritmo sería algo así:

FOR x 0 to 49 (indizado cero)
-tomo valor ADC
-acumulo lectura a una variable (variable + resultado)
NEXT x
-resultado = variable/50
-reinicio x a cero

Desde luego puedes repetir el ciclo más o menos veces que 50, dependiendo de tus necesidades, sólo ten en cuenta que cada llamada ADC consume tiempo de procesamiento.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Problema ADC en Pic18f4550
« Respuesta #2 en: 16 de Febrero de 2015, 01:26:48 »
Tomar semejante cantidad de muestras y sumarlas haria que necesites una gran cantidad de bits para almacenar ese numero. Ademas de estar dividiendolo por algo que no es potencia de 2.
Creo que con 16 seria bastante razonable

Desconectado Daikataro

  • PIC10
  • *
  • Mensajes: 22
Re: Problema ADC en Pic18f4550
« Respuesta #3 en: 20 de Febrero de 2015, 13:06:20 »
Tomar semejante cantidad de muestras y sumarlas haria que necesites una gran cantidad de bits para almacenar ese numero. Ademas de estar dividiendolo por algo que no es potencia de 2.
Creo que con 16 seria bastante razonable

El resultado ADC es expresado como un número de 10 bits, lo cual significa que va de 0 a 1023. Suponiendo el peor escenario, absolutamente todas las muestras reportan el máximo valor, con lo cual se suma 1023 50 veces, o lo que es lo mismo, 50 x 1023 = 51,150

Ignoro cómo maneja C las variables, pero en BASIC un tipo word es un entero de 16 bits, o lo que es lo mismo, un límite superior de 2^16 = 65,536

De lo anterior podemos deducir que una sola variable de tipo word (2 bytes) es más que suficiente para almacenar todos y cada uno de los valores ADC en un muestreo de 50 tomas. Para iteraciones más numerosas (no lo recomiendo sin cristal de 20MHz) necesitaríamos una variable long, capaz de almacenar 2^32 = 4,294,967,296.

Ahora en términos de trabajo, el PIC es completamente capaz de realizar operaciones aritméticas sencillas. Como ninguna de las variables es del tipo single, lo único que pasará es que la parte decimal se perderá y, dependiendo del compilador, se redondeará (si es .5 o mayor se añade 1 y si no, no) o se truncará (puede ser .99 y se eliminará el decimal sin añadir nada).

De manera que por recursos de memoria o manejo de datos, no hay que parar. Precisamente el lenguaje de alto nivel está pensado para no tener que visualizar siempre las cosas en lenguaje máquina (potencias de dos) y dejarle el trabajo pesado al microcontrolador y al lenguaje.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Problema ADC en Pic18f4550
« Respuesta #4 en: 20 de Febrero de 2015, 13:42:44 »
Si C podes maneja 16 bits.

Pero son micros de 8 bits. lo cual te lleva aproximadamente unas 4/5 intrucciones como minimo en la suma, al hacerlo por un valor mas chico no estarias consumiendo tantos ciclos
y la division una iteracion de 50 veces una resta, una suma + salto. que tranquilamente podrias reemplazar por 4 rotaciones o 5 si usas 32

Citar
De manera que por recursos de memoria o manejo de datos, no hay que parar. Precisamente el lenguaje de alto nivel está pensado para no tener que visualizar siempre las cosas en lenguaje máquina (potencias de dos) y dejarle el trabajo pesado al microcontrolador y al lenguaje.

Entiendo perfectamente, pero nunca tenes que olvidarte de la base y que estas trabajando con un microcontrolador con flash y RAM limitadas, no es una PC. Si luego tenes un programa que pesa 50Kb cuando podria pesar 12Kb y ejecutarse en la mitad del tiempo es culpa enteramente del programador. Puede que no te moleste por que tenes flash por demas o por que te sobra el tiempo. Pero pienso que es una mala practica ( o falta de optimizacion, o desperdicio de rendimiento ) del programador por no ser consciente del micro que esta usando. Fuera un micro de 16 bits perfecto la suma seria perfecta aun asi la division deberia ser potencia de 2 a no ser que posea un modulo que divida por HW en algunos ciclos razonables para usar uno u otro.

Por otra parte me confundi al decir que necesitaria una gran cantidad de bits, no se por que pense como 12 bits el A/D.

En fin y continuando con el tema.

Como dijeron podrias promediarlo lo cual podrias usar el AD apenas este disponible
o Podrias hacerlo cada cierto intervalo de tiempo asi por ejemplo cubris 8 muestras en 1 segundo y actualizas la lectura cada 1 segundo, ya que el multimetro no tiene una tasa de refresco muy rapida tampoco.
« Última modificación: 20 de Febrero de 2015, 14:17:46 por KILLERJC »