Por otro lado cuando digo Expandible quiere decir que podremos aumentar su representación, cantidad de dígitos, parámetros de medición, adaptación electrónica de señal, muestro, etc...
En este caso se trata de utilizar las funciones básicas ya que en la sencillez se comprende mejor el código y su principio de funcionamiento.
Hay que tener en cuenta que la tensión máxima para el ADC del microcontrolador es de 5V continuos, si queremos realizar una medición que supere este valor tendremos que utilizar un divisor de tensión.
En nuestro caso mediremos hasta los 4,999V, nuestro voltímetro tendrá una resolución de 4.7mV y para garantizar la estabilidad realizara una toma de 500 muestras cada unos 5ms que luego procesara su promedio y lo mostrara en el display de 4 dígitos.
El ADC del microcontrolador estará funcionando a 10Bit, es decir a 1024 cuentas que funcionando con un máximo de tensión de 4,999V tendremos una representación de 4.7mV lo cual hace poco útil tener 3 dígitos decimales, ya que con 2 dígitos decimales seria útil. (esto quedara para la segunda versión donde pondremos un limite de unos 5V).
Por otro lado nos quedara el tratado de los displays que sera la técnica común de multiplexado, es decir, dato del display 1 y se activa el display 1, mientras el resto sigue desactivado, luego dato del display 2 y se activa el display 2 mientras el resto sigue desactivado, y asi para cada display de esa forma cada dígito muestra el valor que debe, al ser una acción repetitiva y rápida se genera una persistencia que al ojo humano parecen estar los cuatro dígitos encendidos a la vez pero en realidad se activan de uno en uno.
- //Función que se ejecutara en paralelo al programa principal sobre el Timer0
- void timer0_mux(int8 dig4, int8 dig3, int8 dig2, int8 dig1){
- output_c(0b00000001); //Selección del display 1
- output_b(num[dig1]); //Valor tratado del dígito 1 en la salida B
- output_high(PIN_B7); //Prendemos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00000010); //Selección del display 2
- output_b(num[dig2]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00000100); //Selección del display 3
- output_b(num[dig3]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00001000); //Selección del display 4
- output_b(num[dig4]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- set_timer0(0); //Seteo del Timer0
- }
Por ultimo la función encargada de tomar un numero entero y dividirlo en 4 se realiza en base a división y restos, con el símbolo "/" dividimos y con "%" tomamos el resto.
- void convert(int16 valor){ //Función para convertir entero en dígitos
- int uno, diez, cien, mil; //Declaración de variables de los dígitos
- mil=valor/1000; //Operación para adquirir miles
- cien=(valor/100)%10; //Operación para adquirir cientos
- diez=(valor/10)%10; //Operación para adquirir decenas
- uno=valor%10; //Operación para adquirir unidades
- timer0_mux(uno,diez,cien,mil); //Llamado a la función de multiplexado
- }
La medicion se realiza en base a un canal ADC el cual se acondiciona multiplicando por los 5V del fondo de escala del ADC y se lo divide por la cantidad de muestras del ADC que seran 1024.
Luego para mejorar la estabilidad de la medición utilizaremos el calculo del promedio de la medición, es decir, mediremos 500 veces el valor, realizaremos la sumatoria de cada uno de ellos y al finalizar el lazo de iteracion dividiremos el valor final por 500 para que nos de el valor estable. De esta forma el bit menos significativo sera mas estable, pero como lo comentaba al principio del proyecto no es necesario tener 3 decimales con 10 bit de representación.
- while(true){ //Lazo repetitivo principal
- set_adc_channel(0); //Selección del canal 0 del ADC
- delay_ms(5); //Delay para la conversión de 5ms
- tension=read_adc()*5.0/1023.0; //Lee el ADC y convierte en valor de tensión
- for(i=0;i<500;i++){ //Lazo de 500 iteraciones para sacar promedio
- tensionAnt=tension+tensionAnt; //Suma del acumulado para sacar promedio
- }
- convert((tensionAnt/500)*1000); //Llama a la función que convierte a dígitos
- tensionAnt=0; //Inicializa variable de promedio
- }
Ahora dejare el código completo para poder observar las funciones del mismo de forma mas sencilla y la interacción entre ellas.
- #include <16F883.h> //Microcontrolador a Elegir
- #device adc=10 //Resolución del ADC a 10Bit
- #use delay(clock=4000000) //Oscilador Externo a 4MHz
- //Vector que aloja los 10 valores numéricos para el display de 7 segmentos
- int8 num[10]={0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,
- 0b01101101,0b01111101,0b00000111,0b01111111,0b01101111};
- #int_timer0 //Función del Timer0
- //Función que se ejecutara en paralelo al programa principal sobre el Timer0
- void timer0_mux(int8 dig4, int8 dig3, int8 dig2, int8 dig1){
- output_c(0b00000001); //Selección del display 1
- output_b(num[dig1]); //Valor tratado del dígito 1 en la salida B
- output_high(PIN_B7); //Prendemos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00000010); //Selección del display 2
- output_b(num[dig2]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00000100); //Selección del display 3
- output_b(num[dig3]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- output_c(0b00001000); //Selección del display 4
- output_b(num[dig4]); //Valor tratado del dígito 1 en la salida B
- output_low(PIN_B7); //Apagamos el punto decimal
- delay_ms(2); //Delay de multiplexado de 2ms
- set_timer0(0); //Seteo del Timer0
- }
- void convert(int16 valor){ //Función para convertir entero en dígitos
- int uno, diez, cien, mil; //Declaración de variables de los dígitos
- mil=valor/1000; //Operación para adquirir miles
- cien=(valor/100)%10; //Operación para adquirir cientos
- diez=(valor/10)%10; //Operación para adquirir decenas
- uno=valor%10; //Operación para adquirir unidades
- timer0_mux(uno,diez,cien,mil); //Llamado a la función de multiplexado
- }
- void main(){ //Función principal del programa
- setup_adc_ports(sAN0|VSS_VDD); //Configuración del canal del ADC
- setup_adc(ADC_CLOCK_DIV_2); //Configuración de velocidad del ADC
- setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8); //Configuración del divisor del Timer0
- set_timer0(0); //Seteo del Timer0
- enable_interrupts(INT_TIMER0); //Habilitación de interrupción Timer0
- enable_interrupts(GLOBAL); //Habilitación de interrupciones
- float tension, tensionAnt=0; //Definición de variables flotantes
- int16 i; //Definición de entero de 16 bit
- while(true){ //Lazo repetitivo principal
- set_adc_channel(0); //Selección del canal 0 del ADC
- delay_ms(5); //Delay para la conversión de 5ms
- tension=read_adc()*5.0/1023.0; //Lee el ADC y convierte en valor de tensión
- for(i=0;i<500;i++){ //Lazo de 500 iteraciones para sacar promedio
- tensionAnt=tension+tensionAnt; //Suma del acumulado para sacar promedio
- }
- convert((tensionAnt/500)*1000); //Llama a la función que convierte a dígitos
- tensionAnt=0; //Inicializa variable de promedio
- }
- }
De la misma manera hay que utilizar resistencias de 330R a 680R para los 7 segmentos que no esta en el diagrama de simulación pero si las he utilizado en la practica con un pack DIL de resistencias.
Buen proyecto, muy util para iniciarse en el mundo de la multiplexación de displays de 7 segmentos.
ResponderBorrarGracias, Me alegra que te sirva. Saludos!
BorrarHola esta fantastico por el limite de medicion, ahora bien mi proyecto es un medidor de presion con un sensor de presion de 3 pines masa señal y +5v, segun la presion el sensor entrega con 330bar alrededor de 4.6v y con 25 bar 0,5v (valores aproximados dentro de ese rango de voltajes), como haria para que a 4,6v no muestre voltaje sino 330,0 BAR, si es posible me pongo de cabeza a aprender a programar el chip PIC y por otra parte seria posible que exitando alguna entrada al pic pueda cambiar de BAR a Psi digamos con un pulsador.
ResponderBorrarQue posibilidades habria de colectar datos y enviarlos a la placa de audio de pc, le explico me dedico a mecanica de equipos viales las bombas hidraulicas de pistones suelen gastarse los pistones como tienen 6 o mas uno que este gastado provoca fluctuacion de caudal si se pudiera hacer un registro grafico a distintos regimenes de rpm se haria un analisis de estado sin desarmar el equipo para ver como esta su bomba, con una simple captacion de datos se puede dar un veredicto de si conviene o no desarmar.
Me gusta tu proyecto felicitaciones y muchas gracias.
Me gustaría hacerlo y mostrar tres resultados con un pulsador, como?
ResponderBorrarsabes que no me funciona en el proteus, todos 88888 me pone
ResponderBorrarbuena noche amigo, me intereza aserlo, pero con punto desimal movible, q si el voltaje sea 5.033, ese valor se muestre, pero ya al pasar a decemas cambie el punto desimal por ejemplo, 14.56. crees que usando este codigo de muestra se pueda aser esta funsion?
ResponderBorrarbuen dia amigo, el codigo se puede ocupar para el pic16f88??, porque quiero usarlo para crear un amperimetro, podrias ayudarme? porvafor
ResponderBorrar