Autor Tema: Proyecto de altímetro  (Leído 4652 veces)

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

agaran

  • Visitante
Proyecto de altímetro
« en: 15 de Diciembre de 2005, 03:31:00 »
Muy buenas.

En el mensaje del foro "pantalla lcd" comenté que quiero construirme un altímetro utilizando un pic.

Parece que la idea va tomando forma aunque aún quedan muchos puntos que no se resolver.

Voy a exponeros como va el tema a ver si me podeis ayudar.

La altitud está relacionada con la presión atmosférica de la siguiente manera:

h=(P0-P)/gamma  donde:

h: altura respecto a una cota de origen
P0: presión atmosférica en la cota de origen
P: presión atmosférica a la altura que queremos saber
gamma: densidad específica del aire

A la hora de implementarlo en el controlador el cálculo se reduce a:

h=K*(P0-P)

Donde K es una constante que se calcula de forma práctica en el tarado del altímetro de la siguiente manera:

1) Nos situamos en un punto de altitud conocida (ej. El nivel del mar)
2) Subimos a una cota de altura conocida (vienen en cualquier plano topográfico)
3) Calculamos la diferencia de presiones medidas
4) Dividimos la diferencia de cotas entre la diferencia de presiones y así obtenemos la constante K

5) Implementamos el programa en el pic con esa constante
6) Se trata de un altímetro relativo, es decir, cada vez que lo utilicemos tomará una medida de la presión inicial y lo que nos devolverá será la diferencia de cota respecto al punto en el que lo hemos iniciado.


El sensor de presión será el MPX2200AP de motorola que da una señal de 0 a 4 mV en función de la presión atmosférica.

Esta señal pasará a un amplificador analógico que la pasará al rango entre 0 y 5 V para introducirla en el PIC. (aun no se como diseñar el amplificador pero espero que no sea dificil)

La señal amplificada irá a una entrada analógica del PIC16F81 (creo que es el mas sencillo que tiene conversor AD).

El programa calcula la altitud la convierte en BCD y la pasa a un display de 7 segmentos de 4 dígitos mediante un bus de 8 líneas y 4 de activación de cada dígito.

Ahora viene cuando la operan...

La altitud que quiero medir debe abarcar un rango de al menos 1500 metros y el PIC tiene un ancho de palabra en los registros de memoria de 8 bits por lo tanto creo que no puedo representar un numero mayor de 255 metros.

No tengo mucha idea de electronica digital y no se si habrá una solución para esto.

¿Se os ocurre algo?

Gracias

Desconectado Azicuetano

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1020
    • Aplicaciones Electrónicas en Alicante.
RE: Proyecto de altímetro
« Respuesta #1 en: 15 de Diciembre de 2005, 04:28:00 »
Hola agaran.

El sensor de presión que comentas creo que tiene una salida de 40 mv (no de 4). Míralo bien para no diseñar mal el amplificador.

Como muy bien dices los registros del PIC son de 8 bits (255 en decimal) pero es muy fácil utilizar rutinas aritméticas en 16 bits (65535 en decimal).

Las puedes buscar en:

http://www.piclist.com/techref/microchip/math/basic.htm

O si quieres te puedo pasar las que yo utilizo.

Un saludo desde Alicante.


agaran

  • Visitante
RE: Proyecto de altímetro
« Respuesta #2 en: 15 de Diciembre de 2005, 05:51:00 »


He echado un vistazo al link que has puesto y la verdad... no me entero de mucho. Te agradecería que me pasaras las rutinas que utilizas tu para trabajar con numeros de 16 bits.

Por ejemplo, que pasa si yo sumo 1111d con 1111d en un pic? ¿como puedo hacer para que se almacene en dos registros el resulatdo de la operación (0001 en uno y 1110 en otro? o bien trabajar operar con numeros de 16 bits almacenados en dos registros, poder sumarlos y restarlos sin problema.  A lo mejor lo que pido no es posible

Muchas gracias,

por cierto yo tambien soy de Alicante

Desconectado Azicuetano

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1020
    • Aplicaciones Electrónicas en Alicante.
RE: Proyecto de altímetro
« Respuesta #3 en: 16 de Diciembre de 2005, 03:53:00 »
Hola agaran!

Estas son las rutinas que yo personalmente utilizo. En su día las busqué, me funcionaron bien y... nunca me ha dado por optimizarlas (no he tenido tiempo).

Codigo:
suma_16_bits

      movf   Dato_A_L,W      ;Carga menos peso del dato A
      addwf   Dato_B_L,W      ;Suma menos peso del dato B
      movwf   Resultado_L      ;Almacena el resultado
      movf   Dato_A_H,W      ;Carga más peso del dato A
      btfsc   STATUS,C                      ;Hubo acarreo anterior ??
      addlw   1         ;Si, suma 1 al acumulador
      addwf   Dato_B_H,W      ;Suma más peso del dato B
      movwf   Resultado_H      ;Guarda el resultado

      return



Codigo:
resta_16_bits

      movf   Dato_B_L,W      ;Carga menos peso del dato B (sustraendo)
      subwf   Dato_A_L,W      ;Resta menos peso del dato A (minuendo)
      movwf   Resultado_L      ;Almacena el resultado
      movf   Dato_B_H,W      ;Carga más peso del dato B (sustraendo)
      btfss   STATUS,C                      ;Hubo acarreo (CARRY = 0) anterior ??
      addlw   1                      ;Si, añade 1 al acumulador (sustraendo)
      subwf   Dato_A_H,W      ;Resta más peso del dato A (minuendo)
      movwf   Resultado_H      ;Guarda el resultado

      return



Codigo:
; MULTIPLY multiplier, multiplicand
; Multiply two 16-bit numbers into a 16-bit product, permitting overflow.


Multiply
             CLRF prodH                 ; Clear product to make
             CLRF prodL                 ; way for new calculation.
             MOVLW d"16"                ; Number of bits to calc.
             MOVWF index
Multiply_loop
             BCF STATUS,C              
             RLF prodL                  ; Shift product left.
             RLF prodH                  
             BCF STATUS,C              
             RLF mulcL                  ; Shift multiplicand left.
             RLF mulcH                  
             BTFSS STATUS,C             ; If carry, add multiplier
             GOTO Multiply_skip
             MOVF mulpL,w               ; to the product. Else skip.
             ADDWF prodL
             BTFSC STATUS,C             ; 16-bit addition: prod+mulp
             INCF prodH                
             MOVF mulpH,w              
             ADDWF prodH
Multiply_skip
             DECFSZ index              
             GOTO Multiply_loop
             RETLW 0h





Codigo:
; ; DIVIDE
; Divide one 16-bit number into another, returning the 16-bit result and
; the remainder. Upon entry, the top of the division fraction (the dividend)
; must be in topH and topL, and the bottom (divisor) in btmH and btmL.
; If division by zero is attempted, the routine will return immediately with
; the error code of 0FFh in w. Otherwise, it will perform the division, leaving
; the remainder in topH and topL and the result (quotient) in qH and qL.
; Upon return from a successful division, w contains 0.


Divide       MOVF btmH,w                ; Check for division by 0.
             IORWF btmL,w              
             BTFSC STATUS,Z            
             RETLW d"255"               ; Error code= 255: return.
             MOVLW d"1"                 ; Otherwise, initialize variables
             MOVWF count
             CLRF index                 ; for the division.
             CLRF qH                    
             CLRF qL                    

Divide_sh_loop  BTFSC btmH,d"7"         ; Shift divisor left
             GOTO Divide_d1
             BCF STATUS,C               ; until msb is in
             RLF btmL                   ; btmH.7.
             RLF btmH                   ; count = no. of shifts+1.
             INCF count                
             GOTO Divide_sh_loop        
Divide_d1    BCF STATUS,C              
             RLF qL                     ; Shift quotient left.
             RLF qH                    
             MOVF btmL,w                ; top = top - btm.
             SUBWF topL
             BTFSC STATUS,C             ; If top - btm < 0 then
             GOTO Divide_d2
             MOVLW d"1"                 ; top = top + btm
             SUBWF topH
             BTFSC STATUS,C             ; The idea is to do the
             GOTO Divide_d2
             INCF topH                  ; the subtraction and comparison
             MOVF btmL,w                ; (top > btm?) in one step.
             ADDWF topL
             goto Divide_reentr         ; Then, if btm > top, undo <Microchip instruction>
Divide_d2    MOVF btmH,w                ; the subtraction by adding
             SUBWF topH
             BTFSS STATUS,C             ; top and btm back together
             goto Divide_less           ; <Microchip instruction>
             BSF qL,d"0"                
Divide_reentr
             BCF STATUS,C              
             RRF btmH                  
             RRF btmL                  
             DECFSZ count              
             GOTO Divide_d1
             RETLW 0h                   ; Return w/ remainder in top
                                        ; and result in q.&nsp;
Divide_less  MOVF btmL,w                ; btm > top, so
             ADDWF topL
             BTFSC STATUS,C             ; undo the subtraction by
             INCF topH                  ; adding them back together.
             MOVF btmH,w                
             ADDWF topH
             goto    Divide_reentr      ; <Microchip instruction>




Vamos a  sumar 1111+3333 (el resultado será 4444).

1111 (decimal) = 00000100 01010111

3333 (decimal) = 00001101 00000101

movlw     b"00000100"
movwf    Dato_A_H
movlw     b"01010111"
movwf    Dato_A_L

movlw     b"00001101"
movwf    Dato_B_H
movlw     b"00000101"
movwf    Dato_B_L

call         suma_16_bits

El resultado lo tienes en las variables Resultado_H y Resultado_L

Resultado_H = 00010001
Resultado_L = 01011100


La resta no tienes más que pegarle un vistazo (es prácticamente igual).


Para explicar la multiplicación haremos la siguiente operación.

133 * 99 = 13167

133 = 00000000 10000101
99   = 00000000 01100011

movlw    b"00000000"
movwf    mulcH
movlw    b"10000101"
movwf    mulcL

movlw    b"00000000"
movwf    mulpH
movlw    b"01100011"
movwf    mulpL

call         Multiply

El resultado lo tienes en las variables prodH y prodL

prodH = 00110011
prodL = 01101111

Para la división puedes leer el comentario de la función (explican como utilizarla).

Ya me comentas como te va la cosa.

Un saludo desde Alicante.