Voltímetro con el ADC del PIC

Estado
Cerrado para nuevas respuestas.
Estoy armando el voltímetro de 7 segmentos ánodo común con la rutina de D@rkbytes
¿Cuál rutina?
En el simulador me funciona, pero cuando armo en la placa se ven todos 8888 y muy rápido.
Deberías dar más información, porque no podemos ver tu circuito.
Adjunta algunas fotos y un esquema de las conexiones que estás realizando.
¿Cómo muestro más lenta la lectura?
Ya adjunté un programa sobre como lograr eso en el post #151

Notas:
Proyecto probado y funcionando físicamente con 4 displays de cátodo común.
Si se desea usar displays de ánodo común, en posts anteriores se ha dicho como realizar el cambio.
 
disculpa la ignorancia, estoy en aprendisaje viendo bastantes videos de programacion quiero armar un voltimetro de tres digitos con un pic 18f2550 , que debo de cambiar en el programa para este pic gracias saludos.
 
Debes quitar las variables y rutinas que hacen referencia al cuarto display o dígito.
Y ver que tipo de oscilador usarás para el 18F2550 para configurar los fuses.
 
¿Para quitar el cuarto dígito tendría que borrar. output_c(tabla_7segs[display[0]]); // Mostrar los millares.?

Pido de tu gran ayuda .
PHP:
#include <18f2550.h>
#device  adc = 10
#fuses   nowdt,hs, put
#use     delay(crystal = 20MHz)
#use     fast_io(d)

#define  punto pin_c7

// Arreglo para las variables de los dígitos.
int8 display[3] = {0,0,0};
float valor_adc;

void entero_a_bcd(int16 valor,int8 digitos_menos_1);


// Tabla para displays de 7 segmentos cátodo común.
int8 const tabla_7segs[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

#INT_TIMER1
// Servicio de interrupción por desborde del Timer 1
void sdi_timer1 (void)
{
   // Realizar la lectura del conversor análogo a digital.
   valor_adc = ((40.0 * read_adc()) / 65536);
   set_timer1(0xBDC);               // Recargar el Timer 1
}

void main (void)
{
   int16 voltaje;

   set_tris_d(0b11110000);
   
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   set_timer1(0xBDC); // Cargar el timer1 con 3036 (500Ms. Aprox. 0.001% Error)
   enable_interrupts(GLOBAL);
   setup_adc_ports(sAN0|VREF_VREF); // Seleccionar canal 0 y usar VRef = 2.5V
   setup_adc(ADC_CLOCK_INTERNAL);   // Reloj ADC = interno
   set_adc_channel(0);              // Establecer el canal 0
   delay_us(50);
      
   while (true)
   {  
      // Multiplicar por 100 el valor de "valor_adc"
      voltaje = (valor_adc * 100);
      // Obtener el valor para cada dígito, separando el número
      // y convirtiéndolo con la tabla para displays de 7 segmentos.
      entero_a_bcd(voltaje,3);
      
      // Multiplexar los displays. (Con 4 ms se consiguió menor transición en las unidades)
      output_d(1);   // Activar display 1 y desactivar display 2 y 3
      output_c(tabla_7segs[display[3]]);  // Mostrar unidades.
      delay_ms(2);   // Retardo para mostrar las unidades.
      output_d(2);   // Activar display 2 y desactivar Display 1 y 3
      output_c(tabla_7segs[display[2]]);  // Mostrar decenas.
      delay_ms(2);   // Retardo para mostrar las decenas.
      output_d(4);   // Activar display 3 y desactivar Display 1 y 2
      output_c(tabla_7segs[display[1]]);  // Mostrar las centenas.
      output_high(punto);  // Apagar el punto.
      delay_ms(2);   // Retardo para mostrar las centenas.
      output_d(8);
      output_c(tabla_7segs[display[0]]);  // Mostrar los millares.
      output_low(punto);   // Encender el punto.
      delay_us(700);
   }
}

// Subrutina para separar el número.
void entero_a_bcd(int16 valor, int8 digitos_menos_1)
{
int8 i;
   // Limpiar variables del arreglo "display[]".
   for(i=0;i<=digitos_menos_1;i++)
   {
      display[i] = 0;
   }

   i = digitos_menos_1;
   // Separar los números.
   while (valor > 0)
   {
      display[i--] = (valor % 10);
      valor /= 10;
   }
}
Intenté con este PIC pero hay algo malo, no funciona bien.
¿Me pueden colaborar?

Gracias. Saludos.
 

Adjuntos

Última edición por un moderador:
¿Para quitar el cuarto dígito tendría que borrar. output_c(tabla_7segs[display[0]]); // Mostrar los millares.?
Son más cosas las que se tienen que modificar, pero sin conocimientos de programación, te resultará complicado.

Adjunto el programa en C (PIC C Compiler) y simulación (Proteus v7.10) con los cambios necesarios.

Suerte.
 

Adjuntos

Hombre, de ante mano muchas gracias por su gran colaboración.
Estoy luchando para eso, para tener conocimiento, y estoy empezando.
Me dedico a la eléctricidad automotriz.

Una pregunta. ¿Para su experiencia, q debo de seguir variando para un buen funcionamiento en físico?
Y
o lo seguiré acondicionando. Saludos.

En la simulación trabaja muy bien, sólo faltan milésimas en algunas tensiones, pero lo veo muy bien.

 
Última edición por un moderador:
Un buen plano de tierra en el circuito impreso.
Fuente de alimentación estable a 5V y bien filtrada.
Componentes de calidad, sobre todo en el divisor de tensión y voltaje de referencia.

Como son tres dígitos, no se puede obtener más resolución.
 
Buenas. No sé si ya han hablado de esto.
Aunque estuve viendo la conversación, no leí las nueve páginas porque al parecer hablan de programar el PIC en C, y yo tengo muchos problemas.

Es con ensamblador y no sé si me pueden ayudar.
Es que no soy muy ducha con ese lenguaje, por el momento no sé cómo conectar un LCD al propio conversor con la utilización de ASCII, puesto que no tengo ni idea de como llevar los resultados del mismo a este código.

Esto es lo que tengo por el momento:
PHP:
List        p=16f887    ; list directive to define processor
    #include    <p16f887.inc>    ; processor specific variable definitions

    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
 ;    __CONFIG _CONFIG1, 2007h; LAS PALABRAS DE CONFIGURACION DE ARRIBA EN HEXA
    ;__CONFIG _CONFIG2,  2008h


    CBLOCK 20H
       RESULTHI, RESULTLO, DATO, DATO1        ;variables del conversor
    ENDC
    
    CONT1    EQU 0x20        ;variables del lcd
    CONT2    EQU 0x21
    
       
    
    ORG 0X00    ;INICIO

       BANKSEL OSCCON
    MOVLW    b'11101000'        ; Oscilador interno estable a 8MHz.
        MOVWF    OSCCON
    
    
    
   ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    ;%%%%%%%%%%%%%%%%CONVERSOR ANALOGICO A DIGITAL%%%%%%%%%%%%%%%%%%
  ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

     ;///////////ASIGNACION DE VOLTAJES DE REFERENCIA////////////////
    BANKSEL ADCON1        ; SELECCIONAR BANCO DONDE SE ENCUENTRA ADCON1
    MOVLW B'10000000'   ;
    MOVWF ADCON1    ; ESTABLECER BITS JUSTIFICADO A LA DERECHA


    ;//////////CONFIGURAR MODULO ADC//////////////
    BANKSEL ADCON0        ; SELECCIONAR BANCO
    MOVLW B'10000000'
    MOVWF ADCON0    ; ESTABLECER BITS DE CONFIGURACION DE RELOJ 4uS FOSC/32



    BANKSEL ANSEL
    BSF ANSEL,0    ; ESTABLECER PUERTO RA0 COMO ANALOGICO
    BANKSEL TRISA
    BSF TRISA,0    ; ESTABLECER PUERTO RA0 COMO ENTRADA
    
    
    BANKSEL ADCON0
    BSF ADCON0,0    ;HABILITAR EL CONVERTIDOR

    CALL RETARDO

    BSF ADCON0,1 ;COMIENZA CONVERSION (HABILITA GO/DONE)
CHEKEAR    BTFSC ADCON0,1 ;CHEKEA SI EL BIT GO SE APAGO SI APAGA SALTA
    GOTO CHEKEAR

    CALL RETARDO

    BANKSEL ADRESH
    MOVFW ADRESH       ; MOVER EL VALOR PICO POSITIVO DE LA CONVERSION A W
    MOVWF RESULTHI        ; GUARDAR EL VALOR EN LA VARIABLE
    BANKSEL ADRESL
    MOVFW ADRESL    ;MOVER AL W EL VALOR PICO MINIMO
    MOVWF RESULTLO    ; MOVER A LA VARIABLE ESE VALOR


    
    
    
    
    
    
    ;MOVF RESULTHI,PORTB
    ;MOVF RESULTHI,PORTA
    ;MOVF RESULTLO,PORTC



    
    
    
;%%%%%%%%%%%%%%%%RETARDO%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    ;/////////20mS
RETARDO
    MOVLW D'39' ;INICIALIZAR DATOS
    MOVWF DATO1
SEGUNDO
        MOVLW D'255'
        MOVWF DATO
PRIMERO
        NOP;PERDER TIEMPO
        DECFSZ DATO; DECREMENTO Y SALTA SI IGUAL 0
        GOTO PRIMERO
    DECFSZ DATO1; DECREMENTO Y SALTA SI IGUAL 0
       GOTO SEGUNDO

    RETURN
    
    
    
    
    
END
Les agradecería enormemente su ayuda
 
Última edición por un moderador:
¿Y físicamente de dónde tomas el voltaje de referencia?
En tu esquema únicamente colocaste un voltaje de 2.0V
Si no lo indicas, ¿cómo podemos saber por qué sube a 4.8 V?

Detalles aparte:
Elimina las instrucciones #use fast_io(x) porque no son necesarias.
Aparte, la instrucción set_tris_a(0x01); no está bien configurada así.
Recuerda que usas el pin Vref- (RA2) y ese pin debe ser entrada.
Al estar configurado el pin RA2 como salida, tendrás una contención lógica porque ese pin lo estás conectando hacia negativo.
 
:unsure:

set_tris_a(0x01) como debe de ser configurado?
y estoy usando esos voltajes de una fuente digital con voltajes independientes.
entonces en código que le tengo que cambiar?
 
El registro TRISX se usa más que nada para determinar que pines serán salidas, ya que por defecto todos los puertos al iniciar, en el POR (Power On Reset) se configuran como entradas.
Entonces, si no vas a usar ningún pin como salida en el puerto A, elimina esa instrucción.

Y tampoco tiene problema su uso.
Un 1 en cada bit seleccionado, configura al pin correspondiente como entrada, y un 0 como salida.

Es mejor que uses un circuito integrado para obtener el voltaje de referencia, por ejemplo; un TL431.
Algo así como el diseño del post #151
 
Estado
Cerrado para nuevas respuestas.

Temas similares

Arriba