Mostrar voltaje sin usar ADC

El viejo gameport de las PC incluia la lectura de la resistencia de un potenciómetro y lo hacía sin usar ADC. El principio de funcionamiento era simplemente medir el tiempo de carga de un condensador.

No es un ADC como se puede llegar a pensar, la lectura no es lineal , depende fuertemente de las variaciones de la tensión de umbral y de las variaciones por temperatura de la capacidad del condensador. Pero como es algo muy sencillo, para aplicaciones de baja resolución como es un estabilizador donde solamente hay que ver en qué rango se está para conmutar los relays --> sirve.

Con microcontroladores lo que se puede hacer es programar un puerto como salida para descargar un condensador y luego reprogramarlo como entrada para medir el tiempo que demora en cargarse hasta leer un '1'
No está en el ejemplo, pero luego se debe comparar la lectura con valores de una tabla para saber en rango se está y actuar en consecuencia.

Ver el archivo adjunto 260101

En el ejemplo el programa del micro es:
Código:
#include <12f508.h>
#FUSES NOWDT          //No Watch Dog Timer
#FUSES NOMCLR         //Master Clear pin used for I/O
#use delay(internal=4MHz)
#use FAST_IO(all)

#bit pinB0 = getenv("SFR:PORTB").0

int16 N  ;
//-----------------------------------
int16 Tcarga(){
int16 k ;

    set_tris_b(1) ;
    for(k=0 ; pinB0 == 0 ; k++);

    set_tris_b(0) ;
    pinB0=0 ;

    return k ;
}
//-----------------------------------

void main(void){

    set_tris_b(0) ;
    pinB0 = 0 ;

    while(1){

        N = Tcarga() ;    // Leo el tiempo de carga
                          // del condensador
/*
    Otras operaciones dentro del bucle ppal
.........
.........
*/
        delay_ms(200) ;  // Un retardo cualquiera para este ejemplo
    }
}


Hay que tener cuidado con la simulación porque al menos Proteus usa un modelo de entrada que llama "Digital" y vaya uno a saber por qué pero no mantiene constante el umbral donde la entrada pasa de detectar '0' a '1' y en consecuencia la lectura durante la simulación es inestable

Con compuertas, Proteus tiene la opción de usar un modelo 'Analógico" o 'Digital' para las entradas (obviamente el que funcionaría en este ejemplo es el 'Analógico') pero para micros NO.
Buena tarde.
Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura?

En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo.

Gracias.
 
Buena tarde.
Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura?

En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo.

Gracias.
Por diversas razones, en lenguaje de alto nivel, se suele llegar a tardar mas, pero ésta aseveración, no es absoluta de ninguna manera, es una tendencia lógica no mas.
No confundir tiempo de instrucción con ejecución de comando. Para mi, son cosas distintas. La primera es de HARDWARE la segunda es de SOFTWARE
 
Dónde puedo encontrar el voltaje umbral de los pines configurados como entradas para ser leídos como 1? En cada pic es diferente ? Depende de la temperatura?
En ningún lado, en una entrada digital lo que se te dan son dos niveles de tensión donde se garantiza que por encima o por debajo se leerá un 1 o un 0, entre medio no se asegura nada. A su vez estos niveles dependen del pin y como esté configurado.

Obviamente que en cada pin existe un umbral, pero pero lo tenés que sacar experimentalmente con una rutina de calibración. A fines de dimensionar podés usar un valor de 2V (Vdd=5V)

En lenguaje de bajo nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel? Es para calcular el valor de K en el ejemplo.
Supongo que la pregunta era "En lenguaje de alto nivel una orden se ejecuta a la misma velocidad que uno de bajo nivel?"
Ni cerca, salvo casualidades de compilación.

Siendo que usas Proteus, la manera mas fácil es poner breakpoints y que el mismo Proteus te dé el tiempo transcurrido.
 
Igual, dependiendo del microcontrolador, se puede realizar un ADC mediante un comparador si es que lo trae internamente.

Como el mismo puede conectar una de sus entradas a una tensión externa precisa o a una referencia interna estable no hace falta hacer cálculos raros para saber si varia de un microcontrolador al otro. Y en el caso de necesitar precisión se usa una referencia externa.

Si no hace falta mucha precisión, que el umbral esté 100mV mas arriba o mas abajo no va a variar mucho la situación.
 
Buenas noches.

El pic que estoy usando es el 12f508 que es el más económico, el voltimetro que uso es básico simplemente son 4 led que me indiquen si sube o baja conmutados por los pines libres del pic.

La primera imagen es la el tiempo de carga cuando el voltaje está bajo y la segunda imagen es cuando el voltaje está alto, de lo anterior he notado que el tiempo no varía linealmente con el voltaje esto es problemático al intentar mostrar en los led que voltaje aprox que hay.

Pienso que para hacer lineal el tiempo de carga de acuerdo al voltaje puedo usar una fuente de corriente constante con un par de bjt?

Pdt: la imagen final es el circuito para que tenga una idea de que hice.
 

Adjuntos

  • IMG-20220521-WA0031.jpg
    IMG-20220521-WA0031.jpg
    90.4 KB · Visitas: 14
  • IMG-20220521-WA0032.jpg
    IMG-20220521-WA0032.jpg
    91.3 KB · Visitas: 14
  • IMG_20220521_224632720.jpg
    IMG_20220521_224632720.jpg
    162.4 KB · Visitas: 12


...
El pic que estoy usando es el 12f508 que es el más económico,
No sé en Colombia, pero acá en Argentina podés conseguir a menor precio el 12F1571 , también de 8 pines y con sus limitaciones de memoria, pero al lado del 12F508 es un cohete a la Luna. Soporta interrupciones, tiene timers de 8 y 16bit, PWM , comparador, ADC y DAC.

el voltimetro que uso es básico simplemente son 4 led que me indiquen si sube o baja conmutados por los pines libres del pic.

La primera imagen es la el tiempo de carga cuando el voltaje está bajo y la segunda imagen es cuando el voltaje está alto, de lo anterior he notado que el tiempo no varía linealmente con el voltaje esto es problemático al intentar mostrar en los led que voltaje aprox que hay.

Pienso que para hacer lineal el tiempo de carga de acuerdo al voltaje puedo usar una fuente de corriente constante con un par de bjt?

Con 4 niveles de tensión la alinealidad la corregís con una tabla (si es que realmente hace falta)
También, si la tensión a medida es bastante superior a 5V, usás una resistencia+zener de protección en lugar de un divisor de tensión --> te queda mucho mas lineal.

Pdt: la imagen final es el circuito para que tenga una idea de que hice.
Sinceramente me dá poca idea. Un circuito vale mas que mil fotos.
 
Si te quieres complicar un poco puedes usar la formula de carga del capacitor y calcular los puntos de tu interés, en tu caso serían 4. Una vez tenido los cuatro tiempos es solo cuestión de cronometrar y comparar.

La fórmula es: T = R * C * ln (VCC / (VCC - VD))

Donde R es la resistencia de carga, C el capacitor, VCC la tensión de alimentación (5V) y VD la tensión del punto que estas calculando.

De todas formas hay que saber bien el valor de C, ademas que en general no se usa del tipo electrolítico sino de poliéster ya que son mas estables.
 



No sé en Colombia, pero acá en Argentina podés conseguir a menor precio el 12F1571 , también de 8 pines y con sus limitaciones de memoria, pero al lado del 12F508 es un cohete a la Luna. Soporta interrupciones, tiene timers de 8 y 16bit, PWM , comparador, ADC y DAC.



Con 4 niveles de tensión la alinealidad la corregís con una tabla (si es que realmente hace falta)
También, si la tensión a medida es bastante superior a 5V, usás una resistencia+zener de protección en lugar de un divisor de tensión --> te queda mucho mas lineal.


Sinceramente me dá poca idea. Un circuito vale mas que mil fotos.
Buena tarde el circuito que uso está en la foto adjunta. Muchas gracias por la ayuda de verdad es que he podido dilucidar como hacer la lectura de forma más económica pues acá es el pic más económico el siguiente más económico es el 12f675 pero vale más del triple del 508

Si te quieres complicar un poco puedes usar la formula de carga del capacitor y calcular los puntos de tu interés, en tu caso serían 4. Una vez tenido los cuatro tiempos es solo cuestión de cronometrar y comparar.

La fórmula es: T = R * C * ln (VCC / (VCC - VD))

Donde R es la resistencia de carga, C el capacitor, VCC la tensión de alimentación (5V) y VD la tensión del punto que estas calculando.

De todas formas hay que saber bien el valor de C, ademas que en general no se usa del tipo electrolítico sino de poliéster ya que son mas estables.
Hola que tal, hermano gracias muchas gracias por tu ayuda. Esa fórmula era exactamente lo que buscaba pues no tengo mucho conocimiento sobre el cálculo.

La verdad es que gracias a todos me han ayudado enormemente les envío un gran abrazo..
 

Adjuntos

  • screenshot-2022-05-22-14-00-13.jpg
    screenshot-2022-05-22-14-00-13.jpg
    133.4 KB · Visitas: 15
Última edición:
Ojo que la formula que puse es para cargar el capacitor siempre desde 5V y usar esa rampa para comparar con la tensión a medir.

Para tu circuito, VCC, en la formula, vendría a ser la tensión de entrada (la que se quiere medir) y VD la tensión a la que cambia de estado el pin.
 
Buena tarde el circuito que uso está en la foto adjunta. Muchas gracias por la ayuda de verdad es que he podido dilucidar como hacer la lectura de forma más económica pues acá es el pic más económico el siguiente más económico es el 12f675 pero vale más del triple del 508


Hola que tal, hermano gracias muchas gracias por tu ayuda. Esa fórmula era exactamente lo que buscaba pues no tengo mucho conocimiento sobre el cálculo.

La verdad es que gracias a todos me han ayudado enormemente les envío un gran abrazo..
Yo creo que le está errando al blanco...
Su programa tendría que tener 2 partes bien independientes a mi entender :

-Una que se dedica a capturar los datos y ponerlos en un registro apropiado hasta el momento correcto y
- Otra dedicada al muestreo equidistante en el tiempo y en las salidas, de manera que, no importe la cadencia de captura de los datos de entrada, siempre pueda hacer las muestras de los valores a la misma cadencia que a usted le importe mostrar, independientemente de si pierde alguna lectura o no.
Eso no es crítico a la velocidad que todo ocurre. Esto se hace con interrupciones, que deberías aprender a usar correctamente.
 
Última edición:
Yo creo que le está errando al blanco...
Su programa tendría que tener 2 partes bien independientes a mi entender :

-Una que se dedica a capturar los datos y ponerlos en un registro apropiado hasta el momento correcto y
- Otra dedicada al muestreo equidistante en el tiempo y en las salidas, de manera que, no importe la cadencia de captura de los datos de entrada, siempre pueda hacer las muestras de los valores a la misma cadencia que a usted le importe mostrar, independientemente de si pierde alguna lectura o no.
Eso no es crítico a la velocidad que todo ocurre. Esto se hace con interrupciones, que deberías aprender a usar correctamente.
Hola, no te sigo, no te entiendo muy bien. podrías explicar de forma más sencilla ?

En el pic 12f508 no se puede hacer interrupciones
 
En ese circuito de prueba la alinealidad se da porque la tensión es baja, con tensiones del orden de los 100V (y cambiando la R10k por una del orden de 150k + zener de protección por las dudas) , en el rango de interés te va a quedar prácticamente lineal.
De todas maneras, cuando se trata de discriminar pocos niveles se usa una tabla o una cadena de IFs
Código:
#include <12f508.h>
#FUSES NOWDT        
#FUSES NOMCLR      
#use delay(internal=4MHz)
#use FAST_IO(all)
                                 
                                 
// Umbral para diferentes voltajes
#define N1 90
#define N2 120
#define N3 150
#define N4 180  

//-----------------------------------

void main(void){
int8 N  ;

    #asm
        movlw 0xC0
        option
    #endasm  
       
    set_tris_b(0) ;
    output_b(0) ;

    while(1){

//-----------------------------------
//--    Lee el tiempo de carga     --
        set_tris_b(1) ;
        for(N=0 ; !input(pin_B0) ; N++)
            delay_us(20) ;   // delay para que N resulte menor de 256
        set_tris_b(0) ;
        output_b(0) ;
//-----------------------------------
       
        if(N>N4)        output_high(PIN_B5) ;
        else if(N>N3)   output_high(PIN_B4) ;
        else if(N>N2)   output_high(PIN_B2) ;
        else if(N>N1)   output_high(PIN_B1) ;

        delay_ms(200) ;
    }
}

Este es un ejemplo de como hacer la comparación, porque debe realizarse una calibración para determinar los umbrales N1..4 y el programa incluir una histéresis.
 
Atrás
Arriba