Autor Tema: Conversion ADC de 4 entradas analogas, envio via Serial  (Leído 2211 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Dk99

  • PIC10
  • *
  • Mensajes: 1
Conversion ADC de 4 entradas analogas, envio via Serial
« en: 14 de Febrero de 2007, 03:54:34 »
Tengo un problema, estoy manejando un pic 16F873, habilite el puerto A, como 4 entradas analogas (Variacion de 0 - 5VDC), realizo la conversion ADC y la envio por el puerto C, por los pines q habilitan el puerto Serial, pero cuando hago la conversion este no la hace correctamente siempre, por ejemplo si tengo 5V, el deberia mostrar 3FF, pero solo algunas veces muestra el valor correcto aunque mi señal analoga este fija. Este programa envio tres digitos hexa por cada entrada analoga, es decir que por el puerto C envia una rata de datos de esta forma 3FF2F12FF0FF, para que em puedan ayudar mejor este es el programa y no se donde esta la falla. Gracias!!!!


;Utilizando el PIC16F873
;Micro=PIc16F873;
;WDT=off;OSc=xt;PWRT=on
;DEFINICION DE REGISTROS Y BIST UTILIZADOS
status   equ   03
ptoa   equ   05
ptob   equ   06
ptoc   equ   07
pclath   equ   0ah
intcon   equ   0bh
pir1   equ   0ch
rcsta   equ   18h
txreg   equ   19h
rcreg   equ   1ah
adresh   equ   1eh
adcon0   equ   1fh
trisa   equ   85h
trisb   equ   86h
trisc   equ   87h
txsta   equ   98h
spbrg   equ   99h
adres1   equ   9eh
adcon1   equ   9fh
rp0   equ   5
rp1   equ   6
irp   equ   7
z   equ   2
c   equ   0
txif   equ   4
rcif   equ   5
go   equ   2
loops   equ   20h
loops2   equ   21h
nibble1   equ   22h
nibble2   equ   23h
nibble3   equ   24h
buffer   equ   25h
filter1   equ   26h
filter2   equ   27h
filter3   equ   28h
veces   equ   29h
LRC   equ   2ah

;*********begin the program
   org   00
   goto   inicio
retardo            ;subrutina de retardo en milisegundos
   movwf   loops
top2   movlw   d'110'      ;numero de milisegundos
   movwf   loops2      ;cargado en el registro loops
top   nop
   nop
   nop
   nop
   nop
   nop
   decfsz   loops2      ;pregunta si termino 1mS
   goto   top
   decfsz   loops      ;pregunta si termino cerrado
   goto    top2
   return

            ;Rutina de conversion ADC a 10 bits
            ;devuelve dos datos
conver   bsf   status,rp0
   movlw   b'10000010'   ;selecciono vref internos y 5 canales
   movwf   adcon1      ;8 bits en ADRESL y 2 bit en ADRESH
   bcf   status,rp0
   nop   
   nop
   nop
   nop         ;tiempo de  adquisicion 7 uS
   nop
   nop
   nop
   bsf   adcon0,go   ;inicio de conversion
   nop
   nop
consu   btfsc   adcon0,go   ;espera q termine de convertir
   goto    consu
   nop
   return

;Esta rutina toma 256 muestras y las promedia
filtro   clrf   filter1      ;para que el dato enviado de cada canal
   clrf    filter2      ;sera muy confiable
   clrf   filter3      ;intervalo entre muestras es de 1mS
   clrf   veces
repeat   movlw   d'1'      ;retardo de un miliseg
   call   retardo      ;toma de la muestra
   call   conver
   bsf   status,rp0   ;las muestras se suman y el resultado queda en tres bits
   movf   adres1,w   ;filter1, filter2, filter3
   bcf   status,rp0
   addwf   filter3,1
   btfss   status,c   ;Para completar el pormedio, luego de sumar 256 datos
   goto   filt2      ;
   movlw   d'1'      ;de menor peso de las sumas
   addwf   filter2,1
   goto   filt2      ;
   movlw   d'1'      ;de menor peso de las sumas
   addwf   filter1,1
filt2   movf   adresh,w   ;A la hota de tx datos solo toma en cuenta los dos bytes de mayor peso filter1 y filter2
   addwf   filter2,1   ;peso: filter1 y filter2
   btfsc   status,c
   incf   filter1
   decfsz   veces,1      ;Repite el ciclo de sumar muestras hasta que acabe

   goto   repeat      ;de tomar las 256 veces
   movf   filter1,w   ;debe pasar los dos bytes hexa
   movwf   nibble1      ;a los registros individuales para
   movlw   30h      ;ser TX
   addwf   nibble1      ;le suman 30
   movf   filter2,w   ;para convertirlo en ASCII
   movwf   buffer      ;antes de tx      
   andlw   0fh      
   movwf   nibble3      ;contiene el digito menos significativo
   movlw   0ah
   subwf   nibble3,0   ;Verifica si es una letra o un numero
   movlw   37h

   btfss   status,c
   movlw   30h      ;ser TX
   addwf   nibble3      ;le suman 30
   swapf   buffer,0      ;antes de tx      
   andlw   0fh      
   movwf   nibble2      ;contiene el digito menos significativo
   movlw   0ah
   subwf   nibble2,0   ;Verifica si es una letra o un numero
   movlw   37h

   btfss   status,c
   movlw   30h      ;ser TX
   addwf   nibble2      ;le suman 30
   return

            ;Esta rutina envia serialmente los datos obtenidos en cada conversion
enviar   movf   nibble1,0   ;transmitiendo el digito hexa de mayor peso
;   addwf   LRC      ;suma el dato a transmitir con el LRC
   call    trasmi      ;para llevar el calculo de los datos enviados
   movf   nibble2,0   ;tx el segundo digito hexa
;   addwf   LRC      ;suma el dato a transmitir con el LRC
   call    trasmi      ;para llevar el calculo de los datos enviados
   movf   nibble3,0   ;tx el tercer digito hexa
;   addwf   LRC      ;suma el dato a transmitir con el LRC
   call    trasmi      ;para llevar el calculo de los datos enviados
;   movlw   A','      ;enviar el caracte "," para separa datos

;   addwf   LRC      ;suma el dato a transmitir con el LRC
;   call    trasmi      ;para llevar el calculo de los datos enviados
   return

            ;Transmite cualquier caracter especial
trasmi   btfss   pir1,txif   ;pregunta si el usart esta listo para transmitir
   goto    trasmi      ;si no esta listo espera
   movwf   txreg
   nop         ;confirma si ya habia enviado el caracter especial

trasmi2   btfss   pir1,txif   ;si no espera a que termine de enviarlo
   goto    trasmi2      ;si no esta listo espera
   return

            ;Esta es la rutina que transmite el caracter de chequeo LRC
lrctx   comf   LRC,1      ;complementa el contenido de LRC
   incf   LRC,0      ;Para q sea complemento de los dos le suma 1 LRC
   andlw   0fh
   movwf   nibble3
   movlw   0ah      ;Nibble3 que contiene el digito menos significativo debe probarse para ver si es un
   subwf   nibble3,0   ;numero de 0 a 9o si es una letra
   movlw   37h      ;para hacer la conversion a codigo ascii
   btfss   status,c   
   movlw   30h
   addwf   nibble3
   swapf   buffer,0
   andlw    0fh
   movwf   nibble2      ;El digito de mas peso tiene el mismo proceso que el anterior
   movlw   0ah
   subwf   nibble2,0
   movlw   37h
   btfss   status,c   
   movlw   30h
   addwf   nibble2
   movf   nibble2,0   ;Transmite el digito alto del LRC
   call   trasmi
   movf   nibble3,0   ;Transmite el digito bajo del LRC
   call   trasmi
   return

;---------------   main program  ------------------
inicio   bsf   status,rp0
   movlw   0ffh
   movwf   trisa      ;Puerto A entradas
   movwf   trisb      ;Puerto B entradas
   movlw   b'10111111'
   movwf   trisc      ;Puerto C entradas y pin TX salida
   movlw   b'00100110'   ;programa USART asincrono para TX
   movwf   txsta      ;alta rata de baudios
   movlw   d'25'      ;configura temporizador a 4MHz
   movwf   spbrg      ;9600 bps (8,n,1)
   bcf   status,rp0
   bsf   pir1,txif
   bcf   pir1,rcif
   movlw   b'10010000'   ;habilita el puerto serial
   movwf   rcsta
;   clrf   LRC      ;inicio en ceros el caracter de chaequeo de error

ciclo   btfss   pir1,rcif   ;pregunta si el buffer de recepcion esta lleno
   goto    ciclo      ;si esta vacio vuelve a esperar en ciclo
;   movf   rcreg,0      ;pasa el contenido del Buffer a w
;   xorlw   d'13'      ;para verificar si es el caracter enviado del PC
;   btfss   status,z   ;para comprobar hace una xor con el dato que llego con
;   goto    inicio      ;el valor ASCII del caracter esperando que es el 13

;   movlw   A':'      ;Inicia la trama con caracter
;   call   trasmi
   movlw   b'10000001'   ;selecciona el canal 0, reloj de conv fosc/32

   movwf   adcon0      ;convertidor encendido
   call   filtro      ;llama rutina de conversion AD
   call   enviar      ;envia datos seriales

   movlw   b'10001001'   ;selecciona el canal 1, reloj de conv fosc/32

   movwf   adcon0      ;convertidor encendido
   call   filtro      ;llama rutina de conversion AD
   call   enviar      ;envia datos seriales

   movlw   b'10010001'   ;selecciona el canal 2, reloj de conv fosc/32

   movwf   adcon0      ;convertidor encendido
   call   filtro      ;llama rutina de conversion AD
   call   enviar      ;envia datos seriales

   movlw   b'10011001'   ;selecciona el canal 3, reloj de conv fosc/32

   movwf   adcon0      ;convertidor encendido
   call   filtro      ;llama rutina de conversion AD
   call   enviar      ;envia datos seriales

;   call    lrctx      ;transmite el caracter LRC calculado con los datos

;   movlw   d'13'      ;Envia a caracter Carriage Return
;   call   trasmi

;   movlw   d'10'      ;Envia caracter Line Feed
;   call   trasmi

   goto   inicio      ;Vuelve a empezar el ciclo para esperar que le soliciten otro paquete de dato   
   end

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Conversion ADC de 4 entradas analogas, envio via Serial
« Respuesta #1 en: 14 de Febrero de 2007, 04:54:31 »
Bueno...los conversores AD de los PICs no son precisamente famosos por su precisión.
No pretendas obtener 0x3FF siempre porque no creo que lo logres con el ADC del PIC.
Pero sí puedes mejorarlo si eliges un tiempo de sampleo correcto y haces una pausa considerable entre las mediciones para asegurar la correcta descarga/carga del capacitor interno del ADC del PIC.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Conversion ADC de 4 entradas analogas, envio via Serial
« Respuesta #2 en: 14 de Febrero de 2007, 09:11:13 »
DK99, en mi opinión tienes un problema en tu software o hardware.  Para mí, el A/D de los pics si tiene la presición suficiente, no le puedes errar por tanto.  Una cosa es un pequeño "jitter" o corrimiento que tiene cualquier A/D si la tensión está dentro de los límites de un valor y el siguiente.

Algunas sugerencias

1) Filtra a tu PIC sobre todo su alimentación, ponle un capacitor de .1uF entre Vdd y Gnd.
2) Filtra la señal que vas a digitalizar, un pequeño capacitor es suficiente, pero a tener cuidado con no hacer muy pequeño el tiempo de toma de la señal.  Tu lo tienes en 1mseg así que creo que es más que sufiente
3) Fíjate cómo haces ese famoso promedio, hay algo que no me cierra


     addwf   filter3,1
     btfss   status,c   ;Para completar el pormedio, luego de sumar 256 datos
     goto   filt2      ;
     movlw   d'1'      ;de menor peso de las sumas
     addwf   filter2,1
     goto   filt2      ;
     movlw   d'1'      ;de menor peso de las sumas
     addwf   filter1,1


¿Porqué no verificas el Carry, al sumar la variable filter2 ?

4) Usa [ code=asm ] y [ /code] como marco para postear tus códigos. 

5) Estas líneas no tienen sentido práctico.  Son flags de solo lectura.


   bsf   pir1,txif
   bcf   pir1,rcif



6) Para aumentar la legibilidad de tus códigos, te sugiero lo siguiente

6.a) Que uses el archivo INCLUDE de Microchip.  Haciendo


    INCLUDE   "P16F873.INC"     


Con esto te ahorras de tener que hacer todos esos tediosos EQUS que has usado.  Eso sí, tendrás que usar los registros y bits en mayúsculas ya que así están definidos en el .INC de Microchip.

rcsta pasará a ser RCSTA y así sucesivamente.


6.b) Que no uses ,1 o ,0 como destino de las operaciones.  Define un equ que sea w y otro que sea f, y cambia tu código

Por ejemplo:
decfsz   veces,1
pasaría a ser
decfsz veces,f


6.c) Separa bien lo que sean bloques de subrutinas y lo que sean instrucciones, usa más espacios, usa nombres en mayúscula o bien con un ":" para demarcar.  Además evita omitir el ,f si es que el destino es el file.  Esto te lo digo porque luego de unos días cuando vuelvas a ver el programa tal vez no sepas si eso está bien o simplemente te olvidaste de ponerle ,w
Trata de encolumnar las instrucciones y los argumentos juntos
Ej:


filt2   movf   adresh,w   ;A la hota de tx datos solo toma en cuenta los dos bytes de mayor peso filter1 y filter2
   addwf    filter2,1   ;peso: filter1 y filter2
   btfsc    status,c
   incf     filter1
   decfsz   veces,1      ;Repite el ciclo de sumar muestras hasta que acabe


por


FILT2:
    movf      ADRESH,w   ;A la hota de tx datos solo toma en cuenta los dos bytes de mayor peso filter1 y filter2
    addwf     filter2,f    ;peso: filter1 y filter2
    btfsc     STATUS,C
    incf      filter1,f
    decfsz    veces,f      ;Repite el ciclo de sumar muestras hasta que acabe



Saludos
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)


 

anything