Conversor ADC del PIC

Hola!
Estoy con un proyecto con PIC especificamente el 16F877a.
he leido mucho y ahora programo en lenguaje ensablador, estoy utilizando el conversor ADC del pic pues mi proyecto sensa temperatura y presion.
probe los dos programas por separado.
el de temperatura funciono muy bien, el sensor estaba en la primera entrada del conversor
(AN0) y mostraba por la LCD la temperatura actual. el sensor de humedad a pesar de que su programa estaba terminado lo conecte a la segunda entrada del ADC (AN1) y probe temperatura y humedad a la vez y temperatura daba bien y humedad no.

asi que revise mil veces el programa y ahi no estaba el error. probe humedad por separado en la primera entrada del ADC reemplazando el sensor de temperatura por el de humedad y funciono perfecto.

PROBLEMA:
no puedo jugar con los dos canales del ADC creo que estoy obviando algo o nose pero necesito que alguien me diga como hacer para sensar con dos canales en el mismo programa.
no puedo utilizar ese cambio de canal para pasar a medir de un sensor a otro. solo por seprado.



ademas quiero agragar que para el primer sensor el voltaje de referencia yo lo he determinado. y para el segundo estoy usando el mismo del PIC 5v
 
Última edición:
En el datasheet del PIC16F877A
Registros de configuración:
ADCON0, ADCON1
Registros del puerto:
TRISA
Registros de resultado:
ADRESH, ADRESL

Sigue el problema entonces sube el código o parte de él.
El resto lo encuentras en el foro; usa el Buscador
saludos.
 
Edit:eek:lvide que necesitas el codigo en ensamblador.. lo siento.
-----------------------------------------------------------
Debes decirle al micro que pines usaras como a/d, en css eso se hace asi:

setup_adc(ADC_CLOCK_INTERNAL); //puedes usar distintas bases de tiempo
setup_adc_ports(AN0_TO_AN1_ANALOG ); // ra0 y ra1 como analogo
set_adc_channel(0); // elijo el ra0 analog
delay_us(10);
temp = (5.0*(FLOAT)read_adc()*100)/1024.0;
set_adc_channel(1);//elijo puerto ra1 como analogo
delay_us(10);
humedad=read_adc();

printf(lcd_putc,"\nTEMP :%1.1f",temp); //muestra en el lcd con un decimal

y asi sucesivamente..
saludos
 
Debes configuarar que pines usaras como convertidor A/D En ensambldor lo haces con los registros ADCON0 y ADCON1 como lo dijo el compañero ByAxel. Luego en tu programa debes activar la lectura de un conversor A/D y luego la del otro y repetir. No te explico mejor la programacion ya que el lenguaje ensamblador no lo manejo desde hace ya un buen tiempo y no recuerdo mucho pero lee el datasheet y ahi encontraras lo que te digo. Espero que te ayude.
Saludos.
 
hola soy nuevo en esto del ADC del pic...
como debo tratar en pin ADC del pic....
como si fuera una entrada HI-Z (algo asi como un opamp??)
o por seguridad un resistencia en serie?
 
Preferentemente se le debe poner un operacional en modo seguidor, pero practicamente nunca se hace por cuestiones de espacio y precio...

Dependiendo del circuito que tengas se tiene que buscar la solucion mas adecuada, si solo quieres hacer pruebas y medir un puente de resistencias (Siempre y cuando el voltaje no exceda los limites) puedes colocar la señal directamente al ADC sin ningun problema...
 
hola Chico3001.

Estoy tratando re realizar un programa para controla cuatro entradas analogicas(por el momento), mediante un menu seleccionable con 4 pulsadores up,down, enter y esc, bueno el control del menu mas una entrada AN0 funciona simulado en proteus, pero cunado agrego AN1,AN2,AN3. Al compilar me dice que no se reconoce AN1,AN2,AN3. Porfa si pueden ayudarme, estoy colocando el programa: Los pulsadores (RB0-RB7).Les agradezco de antemano......

Código:
#INCLUDE "C:\Archivos de programa\PICC\Devices\16F877A.H"
#DEVICE ADC=16
#USE DELAY(CLOCK=8M)
#FUSES HS,NOLVP,NOWDT,NOPROTECT,NODEBUG
#INCLUDE "C:\Archivos de programa\PICC\Drivers\LCD.C"
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#INT_RB
void main(void){
    unsigned char menu;
    float d,x;
    port_b_pullups(TRUE);
    setup_adc_ports(ALL_ANALOG);
    setup_adc(ADC_CLOCK_INTERNAL);
    lcd_init();
    enable_interrupts(INT_EXT);
    enable_interrupts(GLOBAL);
    lcd_putc("\f**TEXTO1**\n***TEXTO2***");
    delay_ms(1000);
menu_inicio:
    menu=1;
    lcd_gotoxy(1,1);
    printf(lcd_putc,"\fTENSION_1");
    lcd_gotoxy(1,2);
    printf(lcd_putc,"\TENSION_2");
while(TRUE){
    if(menu==01){
        if(input(PIN_B4)){
            delay_ms(20);
            menu=2;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_2");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"TENSION_3");
    }else if(input(PIN_B5)){
            delay_ms(20);
            menu=4;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_4");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"TENSION_5");
    }else if(input(PIN_B6)){
            delay_ms(20);
            setup_adc_ports(AN0);
            set_adc_channel(0);
            delay_ms(30);
    while(TRUE){
                d=read_adc();
                x=(30*d)/1024.00;
                printf(lcd_putc,"\fTENSION_1= %fV",x);
                delay_ms(100);
                if(input(PIN_B7)){
                    delay_ms(20);
                    goto menu_inicio;
                            }
                }

            }
        
        }
    if(menu==02){
        if(input(PIN_B4)){
            delay_ms(10);
            menu=3;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_3");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"TENSION_4");
    }else if(input(PIN_B5)){
            delay_ms(10);
            menu=1;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_1");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"TENSION_2");
    }else if(input(PIN_B6)){
            delay_ms(20);
            //setup_adc_ports(ALL_ANALOG);
            //setup_adc(ADC_CLOCK_INTERNAL);
            setup_adc_ports(AN1);
            set_adc_channel(1);
            delay_ms(30);
    while(TRUE){
            d=read_adc();
            x=(30*d)/1024.0;
            printf(lcd_putc,"\fTENSION_2= %fV",x);
            delay_ms(100);
            if(input(PIN_B7)){
                delay_ms(20);
                goto menu_inicio;
                            }    
            }    

        }
    }
    if(menu==03){
        if(input(PIN_B4))
            delay_ms(20);
            menu=4;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_4");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"\TENSION_1");
    }else if(input(PIN_B5)){
            delay_ms(20);
            menu=2;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_2");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"\TENSION_3");
    }else if(input(PIN_B6)){
            delay_ms(20);
            setup_adc_ports(AN2);
            set_adc_channel(2);
            delay_ms(30);    
    while(TRUE){
            d=read_adc();
            x=(30*d)/1024.0;
            printf(lcd_putc,"\fTENSION_3= %fV",x);
            delay_ms(100);
            if(input(PIN_B7)){
                delay_ms(20);
                goto menu_inicio;
                            }    
            }    
    }
    if(menu==04){
        if(input(PIN_B4))
            delay_ms(20);
            menu=4;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_1");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"\TENSION_2");
    }else if(input(PIN_B5)){
            delay_ms(20);
            menu=2;
            lcd_gotoxy(1,1);
            printf(lcd_putc,"\fTENSION_3");
            lcd_gotoxy(1,2);
            printf(lcd_putc,"\TENSION_4");
    }else if(input(PIN_B6)){
            delay_ms(20);
            setup_adc_ports(AN3);
            set_adc_channel(3);
            delay_ms(30);    
    while(TRUE){
            d=read_adc();
            x=(30*d)/1024.0;
            printf(lcd_putc,"\fTENSION_3= %fV",x);
            delay_ms(100);
            if(input(PIN_B7)){
                delay_ms(20);
                goto menu_inicio;
                            }    
            }    
    
        }

    }

}
 
Última edición por un moderador:
si alguien me podria dar una idea de como hacer uin temporizador progamable atraves de un potenciometro analogo que vaya desde cero hasta 60 segundo y que a suvez me active un relay gracias
 
si alguien me podria dar una idea de como hacer uin temporizador progamable atraves de un potenciometro analogo que vaya desde cero hasta 60 segundo y que a suvez me active un relay gracias

Hola...Al menos que tengas alguna razón especial lo mas sencillo es un temporizador en base a NE555 y no con un PIC y ADC. Si aun persistes debes conectar el potenciomentro al ADC del PIC y hacer el programa en el lenguaje que sepas para que dependiendo de la lectura del ADC sea el tiempo a transcurrir antes de activar al relay.
Saludos.
Ric.
 
Hola a todos,

Tengo un problema con el ADC de PIC ya que he probado en dos PIC diferentes 16F676 y 12F675, el inconveniente es que en algunos rangos de voltaje el micro al parecer no los tomara esos cambios, es decir si vario entre 3.3V y 3.9V la salida que requiero es la misma, lo que estoy buscando es hacer un disparador controlado para un triac pero en ciertos puntos los saltos que realiza son muy grandes el código que estamos implementando es el siguiente:
Código:
#include<16f676.h>
#device adc=10
#fuses NOWDT, NOPROTECT, NOBROWNOUT, NOMCLR, HS, PUT 
#use delay (clock=20000000)
#use standard_io(C)
#INT_EXT
#define LED  PIN_C1
  
void EXT_isr(void)
{
   float q,Vin;
   int16 Dfase,Dfase2;
   set_adc_channel(0);
   q=read_adc();
   Vin=(5*q)/1023;
   if (Vin <= 2.5)
   {
      Dfase=(Vin*3100);
      delay_us(Dfase);
      delay_us(200);
      Output_high(LED);
      delay_us(250);
      Output_low(LED);
      Dfase2=(7730-Dfase);
      delay_us(Dfase2);
      Output_high(LED);
      delay_us(250);
      Output_low(LED);}
    else 
    {
      delay_us(200);
      Dfase=(Vin*3150);
      delay_us(Dfase);
      Output_high(LED);
      delay_us(250);
      Output_low(LED);}
}
 
void main()
{
 
   setup_comparator(NC_NC_NC_NC);
   enable_interrupts(INT_EXT);
   ext_int_edge(L_TO_H);
   enable_interrupts(GLOBAL);
   Output_low(PIN_C0);
   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);

   while(true)
   {

   }
}

El voltaje que tomamos para leer con el micro viene de una tarjeta de National Instruments y tiene una resolución de 0.01mV, de antemano les agradezco su colaboración en como puedo solucionar este problema ya que en la simulación no realiza estos saltos. ...
 
Hola juanma2468, Gracias por tu pronta respuesta, la tensión que estoy midiendo con el PIC es una señal DC de 0V a 5V, la señal con la que estoy sincronizando el micro es la señal de la red, 60Hz de la cual me sincronizo con un detector de cruce por cero, adjunto una imagen de como estoy realizando las conexiones



Con tantos retardos dentro del servicio de interrupción, es muy normal que el programa no funcione correctamente.

Hola, D@rkbytes gracias por tu participación, pero no entiendo es porque es solo en algunos rangos de voltaje que presenta esos inconvenientes, los presenta alrededor de los 2V, los de 3.3V a 3.9V y alrededor de los 4.5
 

Adjuntos

  • Circuito.JPG
    Circuito.JPG
    100.4 KB · Visitas: 24
Última edición:
¿Por qué quieres medir una tensión de 5 V por medio del cruce por cero?
Saca la lectura del conversor de la rutina de interrupción y todo lo que tenga que ver con retardos.
 
¿Por qué quieres medir una tensión de 5 V por medio del cruce por cero?
Saca la lectura del conversor de la rutina de interrupción y todo lo que tenga que ver con retardos.

lo que quiero hacer es un disparador controlado para un Triac, el voltaje que tengo en la entrada analógica de 0V-5V va a representar cuanto voy a desfasar el disparo para que el Triac comience a conducir, el cruce por cero lo utilizo para sincronizar ese disparo a la frecuencia de la red, es decir que si el voltaje que tengo a la entrada es cero la onda no va a presentar ningún recorte, pero si por el contrario el voltaje que lee el micro es de 2.5V voy a tener la onda recortada a la mitad, es algo similar a un dimmer
 
Pues si, así es como funciona un dimmer con potenciómetro controlado por microcontrolador.

Pero la forma en la que lo estás implementando no es la correcta.

 
Yo acomodaria el codigo de la siguiente forma para comenzar.
Código:
#include <16f676.h> 
#device adc=10 
#fuses NOWDT, NOPROTECT, NOBROWNOUT, NOMCLR, HS, PUT  
#use delay (clock=20000000) 
#use [COLOR=Red]fast_io(C)[/COLOR] 
#INT_EXT 
#define LED  PIN_C1   
[COLOR=Red]// Definiciones de variables
float q,Vin; 
long Dfase,Dfase2;[/COLOR]

void EXT_isr(void) 
{    
   if (Vin <= 2.5)    
   {       
       Dfase=(Vin*3100);       
       delay_us(Dfase);       
       delay_us(200);       
       Output_high(LED);       
       delay_us(250);       
       Output_low(LED);       
       Dfase2=(7730-Dfase);       
       delay_us(Dfase2);       
       Output_high(LED);       
       delay_us(250);       
       Output_low(LED);
   }     
   else      
   {       
       delay_us(200);       
       Dfase=(Vin*3150);       
       delay_us(Dfase);       
       Output_high(LED);       
       delay_us(250);       
       Output_low(LED);
    } 
}   

void main() 
{    
   Output_low(PIN_C0);    
   setup_adc_ports(sAN0|VSS_VDD);    
   setup_adc(ADC_CLOCK_DIV_2);    
   set_adc_channel(0);
   ext_int_edge(L_TO_H);    
   enable_interrupts(INT_EXT);   
   enable_interrupts(GLOBAL);   
   while(true)    
   {       
       [COLOR=Red]q=read_adc();       
       Vin=(5*q)/1023;[/COLOR]    
   } 
}
Modifique algunas instrucciones y el orden de las instrucciones para optimizarlo. Fijate si asi mejora.
 
Última edición:
Ok, ya podré realizarlo el día de mañana a primera hora les comunicaré como me fue con este nuevo código.

Hola!!, pues hasta el momento he quedado peor de lo que estaba antes, en el momento intento realizar la simulación y ahora no anda no muestra ningún pulso como lo hacia antes, realicé algunos cambios en el código nuevamente como regresar a la configuración standad_io(C), agregar un delay_us(20) luego de la lectura del ADC pero nada lo único que me sirvió es declarar las variables dentro de la interrupción, no se si se deban declarar entonces de otro modo
 
Última edición:
Atrás
Arriba