Vref de ADC en PIC18F4550

#1
Hola de nuevo !

Esta vez trabajo en un controlador de velocidad para un motor DC por medio de PWM, a su vez controlado por un potenciómetro conectado al PIC.
Tengo la idea de la respuesta que da el ADC, (un número del 0 al 1023 depende del voltaje en la entrada analógica) pero no entiendo como funciona el Vref o como se configura, etc.
¿Si conectó el potenciometro asi sin más, se usa un Vref interno de 5V automáticamente, o de cuanto es ese Vref interno? ¿Tengo que poner algún voltaje en Vref+ o Vref-? si es así, de cuanto?
Agradecería mucho esta explicación.

Trabajo con el 18F4550 en MickroC.

Saludos !
 
#2
El voltaje de referencia (Vref) depende de como haya sido configurado el registro ADCON1. Revisa este registro en la hoja de datos del PIC18F4550 para que te saques de dudas.
Saludos
 
#3
Gracias por responder ;)

Oooh, es decir que si configuro los voltajes de referencia como Vss y Vdd, el rango será de 0 a 5V, cierto? y ahí variaran los valores dependiendo del voltaje en la entrada analógica, 0=0V, 1023=5V.
Es eso correcto?
suponiendo que use la conversion a 10 bits
 
Última edición:
#5
Buenas tardes. Soy nuevo en este foro, así que esta es mi primera publicación, y si no es mucha molestia quisiera que me pudieran ayudar con un problema.

Lo que estoy haciendo es usar el adc del pic18f4550, ya que en la entrada del pic tengo un potenciómetro y a la salida un led, y lo que debo de hacer es que si giro el potenciómetro a la derecha, se prenda el led, y si lo giro a la izquierda, se apague.
No importa en que posición esté o cuanto lo gire.

Ya hice el código en ccs compiler, lo simulé en proteus y todo funcionaba bien, pero a la hora de probarlo en la protoboard no funciona.

Aquí les dejo el programa y de ante mano, muchas gracias.

Código:
#include <adc.h>
#use delay(clock=20000000)
#define     BITS     8
//#define     ADC_SAMPLEUS 50

void main() {

         int valor_default;
         int valor_1;
        
         setup_adc_ports(AN0_ANALOG);
         setup_adc(ADC_CLOCK_INTERNAL);                                                                                                                                                                                                                                                                                 
         set_tris_a(0xFF);
         set_tris_b(0x00);
        
         set_adc_channel(0);
         valor_default=read_adc();
        
         while(true){
                    valor_1=read_adc();
                   
                    if(valor_1>valor_default){
                                 
                                  output_high(pin_b0);
                                  valor_default=valor_1;
                                 
                    }
                   
                    if(valor_1<valor_default){
                       
                                  output_low(pin_b0);
                                  valor_default=valor_1;
                   }
         }
}
 
Última edición por un moderador:
#6
Si estás usando el ADC a 8 bits, la mitad sería 127 por fijar un valor medio sobre 255.
Entonces cuando se lea un valor superior a 127 puedes encender el LED y cuando sea menor, apagarlo.

Algo sencillo, sería así:
PHP:
#include <18f4550.h>
#fuses   NOWDT,NOFCMEN,CPUDIV1,PLL1,NOUSBDIV,NOVREGEN
#use     delay(internal = 4MHz)


#define  led   pin_b7

void main (void)
{

int8 valor_adc;

   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
   delay_us(50);
   
   while (true)
   {
      valor_adc = read_adc();
      
      if(valor_adc > 127)
         output_high(led);
      else
         output_low(led);
   }

}
Mira la palabra de configuración que es para usar el oscilador interno a 4MHz.
Y que no se estableció el ADC a 8 bits, porque si se omite #device adc = bits, el compilador asume 8 bits por defecto.

Tampoco es necesario que uses librerías extras ni nada fuera de lo normal para manejar el ADC.
 
#7
Gracias por tu tiempo y por responder, el problema es que si se podria hacer asi pero la manera en la que me lo piden es que por ejemplo, si esta el potenciometro(de 20K) posicionado en 5k o en cualquier valor y lo giro a la derecha 1 ohm se debe prender y si se sigue moviendo 1 ohm o los que sean pero a la derecha se sigue prendiendo (no deja de estar prendido), pero si en cualquier momento ese potenciometro retrocede (a la izquierda) un ohm o los que sean pero a la izquierda el led se apaga y seguira apagado mientras el potenciometro gire a la izquierda. No debe ser por intervalos como me sugerias de mitad a mitad sino que con que cambien un poco el valor del potenciometro (mientras se gire a la derecha)se debe de prender y si retrocede (a la izquierda )un poco asi sean ohms o micro ohms se debe a pagar. Espero haberme dado a explicar bien y lo de #include <adc.h> no es una libreria , es que como use ccs compiler el programa lo guarde como adc y asi lo pone, solo es el nombre del programa.
El caso es que el problema no es como hacerlo ya que en proteus lo simule y funciono perfectamente, lo raro es que cuando lo quiero pasar al pic y lo pruebo en la proto no funciona.
 
#8
¿a qué te refieres con "no funciona"?. En mi opinión hay que modificar un poco el código para que si se hace la comparación y la diferencia entre ambas muestras es < ó > a cierto rango (por ejemplo 5) se proceda, entonces, a ejecutar el encendido o el apagado del LED, con esto se hace un poco más inmune al ADC del ruido que puede introducir el potenciómetro

Salu2
 
#9
Pues lo que pasa es que al poner el pic y encenderlo lo unico que hace es que si el potenciometro (20 k)esta en su maxima resistencia el led se apaga pero si es menor a eso desde 19.9(por asi decirlo) hasta 0 el led sigue prendido pero si lo miras de cerca se ve que parpadea muy rapido.
y si estaba pensando ponerle cierto rango para que no haga la comparacion con todos los valores del potenciometro ya que serian demasiadas, nada mas que no se muy bien como ponerle rango. antes habia pensado solo que hiciera la comparacion con ciertos valores.
como:

if(valor_1>valor_defautl && valor_1==50||100||150||200||250){
output_high(pin_b0);
valor_defautl=valor_1;
}
 
#15
Podrías probar guardar el valor del ADC, en el momento que haces la medición, es decir:

Potenciómetro estático: el ADC, mide y guarda su valor (8 bits por ejemplo) en una variable.

Paso siguiente: mueves el potenciómetro a la derecha: el ADC, vuelve a medir y guarda su valor en otra variable que sirve para hacer una comparación, como será mayor que la variable guardada anteriormente, el LED permanecerá encendido. Ahora la primer variable guarda el valor actual del ADC.

Paso siguiente: mueves el potenciómetro a la izquierda: el ADC, vuelve a medir y guarda su valor en la segunda variable, se vuelve a hacer la comparación, como ahora, dicha variable es menor que la otra, el LED se apaga. También la primer variable guarda el valor actual del ADC.

Creo que eso fue lo que entendí, por favor alguien que me corrija si me equivoco.

Saludos.
 
#16
Ya probé con int16 pero sigue haciendo lo mismo.

Código:
#include <adc.h>
#use delay(clock=20000000)
#define  BITS  8

void main() 
{
   
   int16 valor_default;
   int16 valor_1; 
   
   setup_adc_ports(AN0_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);                                                                                                             
   set_tris_a(0b00000001);
   set_tris_b(0x00);
   
   set_adc_channel(0);
   delay_ms(10);
   valor_default=read_adc();
   
 while(true)
  {
        valor_1=read_adc(); 
        
        if(valor_1>valor_default)
          {
             output_high(pin_b0);
           valor_default=valor_1;
          }
        
        if(valor_1<valor_default)
          {
              output_low(pin_b0);
           valor_default=valor_1;
          }
  }
}
Gracias 0002 por responder. Y sí, eso fue lo que yo estoy haciendo pero no sé si me falta algo para que eso lo haga mi programa, ya que no lo hace.
 
Última edición por un moderador:
#17
:unsure: el codigo parece bien, y si lo hace bien en proteus y en la realidad no, es muy comun que no esten bien configurados los fuses...

podrias poner como esta el adc.h y poner el diagrama completo, asi hay un panorama mas completo del problema.
 
Última edición:
#19
el adc.h no es una libreria solo es el nombre del programa con el que lo guarde y como configuro los fusibles??
amigo aqui dice:

#include <adc.h>

esa es una libreria abrela y vela ahi estan los fuses. no olvides postear el diagrama.
 
Última edición:
#20
cierto lo siento ya la abri y esto fue lo que me apareció:

#include <18F4550.h>

#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES PLL12 //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV4 //System Clock by 4
#FUSES USBDIV //USB clock source comes from PLL divide by 2
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOPUT //No Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES VREGEN //USB voltage regulator enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES ICPRT //ICPRT enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPB //No Boot Block code protection
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads

#use delay(crystal=20000000, clock=5000000)

el diagrama no lo puedo poner porque no me permite, dice que excede el tamaño para subir la foto
 

Temas similares

Arriba