TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: ciroperaloca en 16 de Marzo de 2007, 22:31:22
-
Tengo un proyecto en donde uso un pic 16f873a junto con un lcd en donde uso un convertidor AD cuyo resultado me lo pone en adresl y adresh al pasarlo al dispay me pone cantidades enteras, es decir si tengo en la entrada analoga 1.165 volts en el display me pone 116 yo quiero que en el display me muestre 116.5 como hago para que me lo muestre teniendo encuanta que trabajo con 8 bits.
agradecere mucho pues es para mi examen del proximo martes
Uso ensamblador con el MPLAB IDE
-
Que lenguaje de programacion usas?
-
Tengo un proyecto en donde uso un pic 16f873a junto con un lcd en donde uso un convertidor AD cuyo resultado me lo pone en adresl y adresh al pasarlo al dispay me pone cantidades enteras, es decir si tengo en la entrada analoga 1.165 volts en el display me pone 116 yo quiero que en el display me muestre 116.5 como hago para que me lo muestre teniendo encuanta que trabajo con 8 bits.
agradecere mucho pues es para mi examen del proximo martes
Uso ensamblador con el MPLAB IDE
Primero, si usas el módulo A/D en ensamblador así como viene, no podrás nunca tener eso que mencionas. El módulo A/D en 8 bits te dará un resultado de 0 a 255 que representará el total de la escala.
0 = 0V
255 = 5V (o el Vref que uses)
Si te muestra 116 , y hablamos de un Vref de 5V, entonces estas teniendo
5V * (116/255 ) = 2,27V
Hay varias formas en que podrías resolver tu problema, una es que trabajas en formato decimal en mV usando enteros, de todas formas no te salvas de tener que multiplicar y eventualmente usar una conversión a BCD.
Lo más simple que puedes hacer y dado que eres novato, te sugiero que emplees una tabla por cada dígito
Entonces, si por ej.
a 116 le corresponde 2.27V
Tu harías 3 tablas, una para las Unidades, otra para las decenas de voltio y otra para las centenas de voltio. Cada tabla contendría 255 valores.
Donde dec indica que estoy poniendo la equivalencia de los valores obtenidos en decimal vs su tensión.
0dec = 0.000 V
1dec = 0.002 V
...
10dec = 0.20 V
...
50dec = 0.98 V
100dec = 1.96 V
200dec = 3.92 V
250dec = 4.90 V
255dec = 5.00 V
Estoy indicando con un color diferente lo que debieras tener en cada tabla.
Saludos
-
Mejor explicacion que la dada por maunix, no la encontraria ni en el mejor tutorial de PIC. Gracias maunix por esas explicaciones de gran calibre.! :-)
-
Muchas gracias por tu super respuesta lo hare hoy y mañana o pasado te aviso si funciono.
ciroperaloca
-
Mejor explicacion que la dada por maunix, no la encontraria ni en el mejor tutorial de PIC. Gracias maunix por esas explicaciones de gran calibre.! :-)
Gracias Ernesto por los elogios aunque no se si sean merecidos, no me parece que fuera para tanto.
Es simplemente que he lidiado con este tipo de problemas una y otra vez y por eso me salió la respuesta con una forma fácil e intuitiva que encontré en algún momento cuando me vi limitado con el tiempo y la velocidad de cálculo.
ciroperaloca, estaremos esperando saber cómo te ha ido!
-
Hola amigos son de mucha ayuda y tal vez algun dia me vuelva experto en esto pero ahora necesito mucho su colaboracion les explico:
No he podido hacer la tabla, podria aprovechar los 10 bits del resultado de la conversion para que me entregue los decimales o seria mas facil utilizar un pic de 16 bits, para lograr hacer la cuenta en el circuito tengo lo siguiente:
1.908 v = 190
1.235v = 123
1.028v =102
yo necesito me presentara 190.1 como minimo si fuera 190.15 seria ideal.
te muestro el codigo en que estoy fallando?
CICLO bsf ADGO ;Inicia la conversión A/D
btfsc ADGO ;ADGO=?0 si=sig. instrucion, si no brinca, Espera que termine de ;convertir
goto $ -1 ;espera para terminar de escribir
bsf RP0 ;Pasa a página 1 (para acceder a los ocho bits bajos del resultado)
movf adres, 0 ;Resultado de conversión -> W
bcf RP0 ;Pasa a página 1
movwf buffer ;Guarda el dato obtenido de ADRESL en el buffer temporal
bcf CARRY ;Limpia el CARRY
btfsc adres, 0 ;Mira el bit menos significativo de ADRESH (Bit 8)
bsf CARRY ;Si está en 1 pone en uno el carry
rrf buffer, 1 ;Rota un bit de (buffer) a la der. a traves del carry,--->(buffer) ;hace desaparecer el bit 0 de ADRESL, mete el bit 0 de ADRESH por ;el 7 de ADRESL
;-----------Termina conversion analogica a digital--------------<
movf buffer, 0
call DECIMAL ;Obtiene UNI,DEC y CEN con el agregado de 30h(1101) para la tabla ASCII
movlw 0x88 ;Coloca el cursor en la posición 9 de la pantalla.(8D=141)
call CONTROL ;Llamada a subrutina del LCD, envia dato
movf cen, 0 ;Coloca en el LCD las centenas
call DATO ;Coloca el dato o control a enviar en el bus del LCD, pone en alto la ;línea de modo del LCD (Dato)
movf dec, 0 ;Coloca las decenas
call DATO ;Coloca el dato o control a enviar en el bus del LCD, pone en alto la ;línea de modo del LCD (Dato)
movf uni, 0 ;Coloca las unidades
call DATO ;Coloca el dato o control a enviar en el bus del LCD, pone en alto la ;línea de modo del LCD (Dato)
goto CICLO ;Vuelve a medir y mostrar
;Termina ciclo de conversion analogica a digital mostrando lectura-<
;------------Subrutina para conversion de datos a decimal------------------------------->
DECIMAL movwf uni ;Convierte el dato presente en W en UNI, DEC y CEN
clrf dec
clrf cen
;clrf deci
movlw d'100' ;Determina la cant. de centenas
CENTENA subwf uni, 1 ;(uni-1)-->(uni)
btfss CARRY ;(CARRY)=?1, si=sig. instruccion, si no brinca
goto CIEN
incf cen, 1 ;(cen+1)--->cen
goto CENTENA
CIEN addwf uni, 1 ;(uni+W)-->uni
movlw d'10' ;Determina la cant. de decenas
DECENA subwf uni, 1 ;(uni-1)-->(uni)
btfss CARRY ;(CARRY)=?1, si=sig. instruccion, si no brinca
goto DIEZ
incf dec, 1 ;(dec+1)--->dec
goto DECENA
DIEZ addwf uni, 1 ;Uni queda con la cant. de unidades (sin decenas ni centenas)
movlw 0x30 ;Le suma 30h a los valores de UNI, DEC y CEN ---> ASCII
addwf uni, 1
addwf dec, 1
addwf cen, 1
return
-
Hola amigos son de mucha ayuda y tal vez algun dia me vuelva experto en esto pero ahora necesito mucho su colaboracion les explico:
No he podido hacer la tabla, podria aprovechar los 10 bits del resultado de la conversion para que me entregue los decimales o seria mas facil utilizar un pic de 16 bits, para lograr hacer la cuenta en el circuito tengo lo siguiente:
1.908 v = 190
1.235v = 123
1.028v =102
yo necesito me presentara 190.1 como minimo si fuera 190.15 seria ideal.
Antes de ir al código, ¿me puedes comentar algunas cosas?
1) ¿Con qué rango de tensión piensas trabajar?
2) ¿Qué precisión piensas tener? 0.1V ?
3) ¿Qué voltaje de referencia estás usando?
-
perdon el rango que uso es de 0 a 2.0 volts pero no se cuantos digitos recibe el pic.
la precision no la se pues solo he podido trabajar con enteros. en el miltimetro me aparece 1.908 volts pero el pic me lo pone como 191 y yo necesito que me lo exprese 190.8 como minima resolucion de .1 lo maximo para esto seria 190.05 pero eso para mi ya es un sueño.
muchas gracias
salvaras mi vida con esa solucion
!!!!!DE VERDAD¡¡¡¡¡¡
-
Hasta donde he visto, nadie ha dado una respuesta clara con respecto al manejo de decimales en los resultados de la conversion AD y creo que muchos tenemos este problema, en mi caso he aprendido en forma autodidacta (tengo casi dos meses) y viendo esta exelente pagina he aprendido mucho, pero tambien me he detenido con un proyecto al no tener claro esto de los decimales, sera posible que teniendo ADRESH cargado en Byte_H y ADRESL cargado en byte_L podamos trabajar con 16 bits con esto q encontre
List p=16F873 ;Tipo de procesador
include "P16F873.INC" ;Definiciones de registros internos
Byte_L equ 0x18 ;Parte baja del byte a convertir, lsb
Byte_H equ 0x19 ;Parte alta del byte a convertir, hsb
BCD_2 equ 0x20 ;Byte 2 de conversión a BCD
BCD_1 equ 0x21 ;Byte 1 de conversión a BCD
BCD_0 equ 0x22 ;Byte 0 de conversión a BCD
Contador equ 0x23 ;Variable de contaje
Temporal equ 0x24 ;Variable temporal
;*******************************************************************************
;Visualizar: Visualiza sobre la pantalla LCD los cinco dígitos situados en las variables
;BCD_0, BC_1 y BCD_2
Visualizar movlw 0x80
call LCD_REG ;Posiciona el cursor
movlw 3 ;en el lugar 3
movwf Contador ;Inicia contador de bytes a convertir
movlw BCD_0
movwf FSR ;Inicia puntero índice
Visual_loop swapf INDF,W
andlw 0x0f ;0f=15
iorlw 0x30 ;Convierte a ASCII el nible de más peso
call LCD_DATO ;Lo visualiza
movf INDF,W ;Direccionamiento indirecto en la ram
andlw 0x0f ;0f=15
iorlw 0x30 ;Convierte a ASCII el nible de menos peso
call LCD_DATO ;Lo visualiza
decf FSR,F ;Siguiente byte
decfsz Contador,F
goto Visual_loop
movlw ' '
call LCD_DATO
return
;****************************************************************************************
;Bits16_BCD: Esta rutina convierte un número binario de 16 bits situado en Cont_H y
;Cont_L y lo convierte en 5 dígitos BCD que se depositan en las variables BCD_0, BCD_1
;y BCD_2, siendo esta última la de menos peso.
;Esta rutina se presenta en la nota de aplicación AN544 de MICROCHIP
Bits16_BCD bcf STATUS,C
clrf Contador ;borra el contador
bsf Contador,4 ;Carga el contador con 16
clrf BCD_0 ;borra registro BCD_0
clrf BCD_1 ;borra registro BCD_1
clrf BCD_2 ;borra registro BCD_2 Puesta a 0 inicial del resultado
Loop_16 rlf Byte_L,F
rlf Byte_H,F
rlf BCD_2,F
rlf BCD_1,F
rlf BCD_0,F ;Desplaza a izda. (multiplica por 2)
decfsz Contador,F
goto Ajuste
return
Ajuste movlw BCD_2
movwf FSR ;Inicia el índice
call Ajuste_BCD ;Ajusta el primer byte
incf FSR,F
call Ajuste_BCD ;Ajusta el segundo byte
incf FSR,F
call Ajuste_BCD
goto Loop_16
Ajuste_BCD movf INDF,W
addlw 0x03
movwf Temporal
btfsc Temporal,3 ;Mayor de 7 el nibble de menos peso ??
movwf INDF ;Si, lo acumula
movf INDF,W
addlw 0x30
movwf Temporal
btfsc Temporal,7 ;Mayor de 7 el nibble de menos peso ??
movwf INDF ;Si, lo acumula
return
mi pregunta es :como cargo byte_H, y byte_L para q pueda comprobar si las insrtucciones anteriores estan correctas? porque en el manual del F873a no indica como hacerlo, creanme que me he desvelado bastante para solucionar tambien los dichosos decimales, pues necesito las centenas, decenas, unidades y decimas (lectura en el display xxx.1, es decir enteros e incrementos de 0.1
gggggggrrrrrrracias por las respuestas que pudieran dar
-
encontre una nota de aplicacion de microchip en donde parece q trabaja el pic con decimales y es la AN939 en donde se describe un medidor de energia utilizando el F873A, les pido a los PICSPERTOS le hechen un ojo
ggggggrrrrrrrrrrraaaaaaccccccciiiiiiiaaaaaasssssss
-
ese método que aplica Mauricio, se usa sobre todo en cálculos laboriosos donde la solución efectiva es crear tablas con resultados y que el programa vaya tomando constantes que sean aproximados al valor en ese instante.
por citar un ejemplo: la arquitectura de Sintesis Digital Directa usa unas tablas de conversión fase- seno (Look up Table) para agilizar los calculos. y era obvio que también se podía usar esto para el módulo Convertidor Analógico Digital, pero me creeran si les digo que nunca me pasó por la cabeza aplicar tablas a este módulo 8)
-
He leido leido segui sus consejos y no funciono pues al hacer la tabla se pierde la precision, en pocas palabras no funciona. Mi profesor reconoce que es dificil hacer esto y me dio de prorroga hasta despues de vacaciones de semana santa. si alguien sabe como hacerlo le supico me ayude.
saludos
Ciroperaloca
-
Hola ciroperaloca
si vas a usar tablas, te recomiendo que +Vref sea lo mas exacto y estable posible, ya que estas asumiendo el +Vref constante para el cálculo de los digitos.
-
pero me creeran si les digo que nunca me pasó por la cabeza aplicar tablas a este módulo 8)
Te creo, aunque también hay que pensar que a veces hacer las rutinas del cálculo (se usan multiplicaciones y divisiones ) en números enteros o en FLOAT no es la tarea más fácil del mundo y a veces conviene usar la tabla y solucionar el problema. Además para una entrada totalmente conocida y acotada (después de todo un A/D de 8 bits no nos dará más que 256 valores posibles) el usar una tabla suele ser también una muy buena solución.
He leido leido segui sus consejos y no funciono pues al hacer la tabla se pierde la precision, en pocas palabras no funciona. Mi profesor reconoce que es dificil hacer esto y me dio de prorroga hasta despues de vacaciones de semana santa. si alguien sabe como hacerlo le supico me ayude.
Fíjate el pic en cuestión. No puedes usar un Vref de 2 V. Te sugiero leas las A/D CONVERTER CHARACTERISTICS en el datasheet del pic que estás usando.
Me dijiste que esperas tener una precisión de 0.001V es decir valores tales como 190.1 serían el equivalente a 1.901 V
Estamos hablando de 1mV de precisión.
Si usas un A/D en modo 8 bits, y un Vref de 2.5V (lo más pequeño que puedes usar), entonces fíjate con simples números porqué es imposible lo que planteas.
2.5V / 255 = 0,0098 V es decir casi igual como 10mV
Estamos hablando de una precisión diez veces menor de la que pretendes.
Además una precisión de 1mV no es fácil de obtener. Realmente deberás hacer muchos esfuerzos para que tu señal a muestrear y tu vref tengan un ripple menor a eso.
A todo esto no se le puede achacar la culpa al pic. 8)