HC08 - Medidor de pulsaciones


Este desarrollo basa su principio de funcionamiento en la fotopletismografia (PPG), este método no es invasivo y realiza la medición de variación de la densidad de la sangre en el tejido utilizando una fuente de luz y un detector. Como la luz no tiene que penetrar en el cuerpo, el PPG se puede aplicar a cualquier parte del cuerpo humano. La luz detectada por el sensor a través del tejido del cuerpo fluctuará de acuerdo con el flujo sanguíneo pulsátil causado por el latido del corazón, esta fluctuación será captada y amplificada para ser procesada.
En la práctica utilizamos un optoacoplador infrarrojo comercial pero luego de un testeo del mismo se decidió cambiar este optoacoplador por uno de construcción propia en base a un LDR y un LED rojo de alta luminosidad, logrando así una mejora considerable sobre todo a la inmunidad a la luz ambiente.
El método empleado será ingresando el dedo dentro del dispositivo interponiéndose entre el emisor y el receptor, de esta forma el diodo emisor emitirá luz roja para el led que hemos utilizado y el LDR la recibirá. 

Esta variación de luz será amplificada y luego será comparada con una tensión de referencia (Trigger), de esta forma logramos ajustar el comparador para que en la salida se produzca un nivel alto cuando se produzca un latido.
Es necesario realizar la calibración del trigger ya que solo debe tomarse el valor máximo R del ritmo cardiaco (Trigger A).
Si en lugar de mover el trigger hacia arriba para que tome solo el valor R y se dejara a nivel de P y T (Trigger B), en lugar de tomar un solo pulso tomaría 3 pulsos y nos daría una lectura errada.



El circuito que acondiciona la señal para ser ingresada en el microconrolador se realizara en base a un amplificador operacional LM358. Se realizara un desacoplamiento de continua para que no ingresen las componentes de continua en el amplificador. Se amplificara la componente de alterna en 101 veces y al mismo tiempo se realiza un filtro pasa bajos para que no amplifique ruido eléctrico producido por luminarias a 50Hz.

Luego de esta primera etapa, le sigue una etapa comparadora donde se procede a comparar la señal de salida del amplificador anterior con una tensión de referencia que se ajusta mediante el potenciómetro de 10k, de esta forma la salida del comparador nos entregara en su salida un nivel alto o bajo dependiendo de la comparación de ambos niveles de tensión, esto lo denominamos nivel de trigger y variando el nivel de este tomaremos solo los picos de señal R que se muestran en la figura anterior, luego de esta comparación se monitorea el pulso del corazón en un LED y al mismo tiempo se ingresa la señal a un multibibrador monoestable en base al timer 555 el cual cumple la función de temporizar aproximadamente 160ms tras detectar un nivel alto en su disparo, este se utiliza para eliminar el posible burst que existe como ruido eléctrico.
Como podemos ver en el grafico del osciloscopio podemos apreciar la señal que sale del bloque amplificador y comparador, en este caso ha sido una prueba de laboratorio donde la señal se encuentra limpia y sin burst pero en otros ambientes el test ha sido distinto y el timer monoestable de
160ms de delay ha desechado ese ruido eléctrico quedando así una salida que permanecerá a nivel alto durante 160ms que luego será ingresada al microcontrolador.
Timer monoestable:




El programa utilizara el modulo TIM para realizar dos tareas principales:
1) TSC para realizar un ciclo de iteración cada 12 segundos configurando el mismo como timer con interrupción por desbordamiento cuando la variable interna del contador sea igual a un valor constante grabado en el registro TMOD.
2) TSC0 para realizar la captura por flanco ascendente, esta misma creara un salto cuando detecte un flanco ascendente en su entrada de captura que luego incrementara en una unidad una variable que suma la cantidad de pulsos.
Usando el modulo TSC0 dentro del ciclo de TSC, se contara cuantos flancos ha contado durante los 4 segundos del timer antes de que desborde el mismo. Una vez calculado los pulsos se procederá a multiplicarlo por 5, ya que 12s*5=60s (ppm) y luego se mostrara en los displays.



  1. ;-------------------------------------------------------------------------
  2. ;- MONITOR CARDIACO PARA VISUALIZAR EL RITMO EN PPM                      -
  3. ;-------------------------------------------------------------------------
  4. $Include 'jl3regs.inc'       ;Libreria para el MC68HC908JL3
  5. ;-------------------------------------------------------------------------
  6. ;- DEFINICION DE CONSTANTES Y VARIABLES                                  -
  7. ;-------------------------------------------------------------------------
  8. RamSt   equ    $0080         ;Direccion de origen de memoria RAM
  9. RomSt   equ    $EC00         ;Direccion de origen de memoria ROM
  10. ResetV  equ    $FFFE         ;Vector de Reset
  11. ;
  12.         org    RamSt         ;Se apunta al origen de memoria RAM
  13. ;
  14. varUni  rmb    1             ;Variable para separacion de Unidades
  15. varDec  rmb    1             ;Variable para separacion de Decenas
  16. varCen  rmb    1             ;Variable para separacion de Centenas
  17. varDel  rmb    1             ;Variable para Loop del Delay
  18. varCont rmb    1             ;Variable para el contador de pulsos
  19. varMue  rmb    1             ;Variable para el muestreo
  20. ;
  21.         org    RomSt         ;Se apunta al origen de memoria ROM
  22. ;-------------------------------------------------------------------------
  23. ;- CONFIGURACION                                                         -
  24. ;-------------------------------------------------------------------------
  25. MAIN    mov    #$11,CONFIG1  ;Deshabilita el COP y LVI
  26.         mov    #$FF,DDRA     ;Configura puerto A como salidas
  27.         clr    PORTA         ;Inicializa el puerto A
  28.         mov    #$FF,DDRB     ;Configura puerto B como salidas
  29.         clr    PORTB         ;Inicializa el puerto B
  30. ;-------------------------------------------------------------------------
  31. ;- CONFIGURACION DEL TIMER Y CAPTURA 1MHz/64=15625Hz -> 65535/15625=4.19s-
  32. ;-------------------------------------------------------------------------
  33. CONFIG  bset   5,TSC         ;Timer (STOP)
  34.         mov    #$04,TSC0     ;Captura por flanco de subida ELS0A
  35.         clra                 ;inicializo A
  36.         mov    #$00,varCont  ;Inicializa varCont
  37.         mov    #$03,varMue   ;Inicializa varMue
  38.         jsr    DEC2BCD       ;Rutina de conversion de Decimal a BCD
  39. ;-------------------------------------------------------------------------
  40. ;- INICIO                                                                -
  41. ;-------------------------------------------------------------------------
  42. INICIO  bset   4,TSC         ;reset de contador TCNT y prescaler
  43.         mov    #$26,TSC      ;Inicializa timer (STOP), prescaler:64
  44.         bclr   5,TSC         ;Timer (START)
  45.         clra                 ;Inicializa A
  46. PULSO   brclr  7,TSC0,SIGUE  ;Espera flanco de subida TOF
  47.         bclr   7,TSC0        ;Baja flag
  48.         inc    varCont       ;Sumo varCont=varCont+1
  49. SIGUE   jsr    MUXDISP       ;Rutina de Multiplexado de displays
  50.         brclr  7,TSC,PULSO   ;Espera a overflow
  51.         bclr   7,TSC         ;Baja flag
  52.         dec    varMue        ;Decrementa varMue
  53.         beq    UPDATE        ;Si varMue=0 salta a UPDATE
  54.         bra    INICIO        ;Si no es igual a 0 salta a INICIO
  55. UPDATE  mov    #$03,varMue   ;Asigna valor 3 a varMue
  56.         ldx    #$05          ;Cargo 5 en X
  57.         lda    varCont       ;Cargo varCont en A
  58.         mul                  ;A*X=A
  59.         jsr    DEC2BCD       ;Rutina de conversion de Decimal a BCD
  60.         mov    #$00,varCont  ;Inicializa varCont
  61.         jmp    INICIO        ;Salta a INICIO
  62. ;-------------------------------------------------------------------------
  63. ;- CONVERSION DE DECIMAL A BCD SEPARADO POR DIGITOS                      -
  64. ;-------------------------------------------------------------------------
  65. DECTBCD ldhx   #$0A          ;Carga X con 10
  66.         div                  ;Divide A/X=A, Resto en H
  67.         sthx   varUni        ;Mueve H a varUni
  68.         clrh                 ;Borra H
  69.         ldhx   #$0A          ;Carga X con 10
  70.         div                  ;Divide A/X=A
  71.         sthx   varDec        ;Mueve H a varDec
  72.         sta    varCen        ;Mueve A a varCen
  73.         rts                  ;Retorno de subrutina
  74. ;-------------------------------------------------------------------------
  75. ;- MULTIPLEXADO DE DISPLAYS                                              -
  76. ;-------------------------------------------------------------------------
  77. MUXDISP clrh                 ;Inicializa H  
  78.         ldx    varCen        ;Carga el valor de Centenas en X
  79.         lda    TABLA,X       ;Busca en la tabla el equivalente
  80.         mov    #$01,PORTA    ;xxxxx001, Disp1=1,Disp2=0,Disp3=0
  81.         sta    PORTB         ;Carga el PORTB con el valor de la tabla
  82.         jsr    DELA100       ;Llama a rutina de Delay 100us
  83.         ldx    varDec        ;Carga el valor de Decenas en X
  84.         lda    TABLA,X       ;Busca en la tabla el equivalente
  85.         mov    #$02,PORTA    ;xxxxx010, Disp1=0,Disp2=1,Disp3=0
  86.         sta    PORTB         ;Carga el PORTB con el valor de la tabla
  87.         jsr    DELA100       ;Llama a rutina de Delay 100us
  88.         ldx    varUni        ;Carga el valor de Unidades en X
  89.         lda    TABLA,X       ;Busca en la tabla el equivalente
  90.         mov    #$04,PORTA    ;xxxxx100, Disp1=0,Disp2=0,Disp3=1
  91.         sta    PORTB         ;Carga el PORTB con el valor de la tabla
  92.         jsr    DELA100       ;Llama a rutina de Delay 100us
  93.         rts                  ;Retorno de subrutina
  94. ;-------------------------------------------------------------------------
  95. ;- RUTINA DE DELAY DE 100us                                              -
  96. ;- (9+(10*9))+5=104us                                                    -
  97. ;-------------------------------------------------------------------------
  98. DELA100 mov    #$09,varDel  ;[5]Se carga el valor 9 a varDel
  99. LOOP    dec    varDel       ;[4]Se decrementa varDel
  100.         beq    FIN05        ;[3]Si varDel=0 salta a FIN05
  101.         bra    LOOP         ;[3]Salta a LOOP
  102. FIN05   rts                 ;[4]Retorno de subrutina
  103. ;-------------------------------------------------------------------------
  104. ;- TABLA DE VALORES PARA EL DISPLAY DE 7 SEGMENTOS                       -
  105. ;- Bits del display XGFEDCBA                                             -
  106. ;-------------------------------------------------------------------------
  107. TABLA   db     00111111     ;Numero 0
  108.         db     00000110     ;Numero 1
  109.         db    %01011011     ;Numero 2
  110.         db    %01001111     ;Numero 3
  111.         db    %01100110     ;Numero 4
  112.         db    %01101101     ;Numero 5
  113.         db    %01111100     ;Numero 6
  114.         db     00000111     ;Numero 7
  115.         db    %01111111     ;Numero 8
  116.         db    %01100111     ;Numero 9
  117. ;-------------------------------------------------------------------------
  118. ;- FINAL                                                                 -
  119. ;-------------------------------------------------------------------------
  120.         org   ResetV        ;Se apunta al Vector de Reset
  121.         dw    MAIN          ;Salta a MAIN
  122.         end                 ;Fin del programa

31 comentarios:

  1. NOTA: Dentro de la definición de la tabla para los valores del display de 7 segmentos, por alguna razón que desconozco, el editor del blog ha borrado los caracteres "" del numero 0, 1 y 7. Deberían agregarlo en el código para que compile bien.
    Saludos.

    ResponderEliminar
    Respuestas
    1. Bueno aquí tampoco sale, pero son los caracteres "porcentaje cero cero", seguido del resto de los valores como ocurre en los otros números.

      Eliminar
  2. Hola Sebastian. Interesante, como siempre. Si descarto el microcontrolador ¿a la salida del 555 tendría los pulsos del corazon, como pulsos eléctricos de 160ms?

    Gracias y saludos.

    ResponderEliminar
    Respuestas
    1. Buenas!, es correcto, si lo tomas a la salida del 555 podes ingresar ese pulso en otro lado eliminando el microcontrolador, de igual forma que si tomas la señal dela salida del primer amplificador operacional y la ingresas (mediante un capacitor de desacople) a la entrada de linea de la PC y usas algún programa grabador de sonido (tipo audacity) podes ver los latidos en forma grafica como un ECG.
      http://electgpl.blogspot.com.ar/2009/03/monitor-cardiaco-expandible.html
      Saludos!

      Eliminar
  3. Gracias Sebastian. Perfecto.

    Saludos.

    ResponderEliminar
  4. Hola de nuevo, Sebastian.
    El condensador que está en el primer amplificador, entre la salida de éste y la entrada inversora, de 1uF no tiene polaridad. Los que tengo son electrolíticos. ¿Cómo debería colocarlo?. Si le pongo uno de 470nF cambia la frecuencia a 3.38 Hz. También podría ponerle dos de 470nF en paralelo para obtener 940nF. ¿Cómo se coloca uno electrolítico?

    Gracias y saludos.

    ResponderEliminar
    Respuestas
    1. Hola, cambia muy poco si usas uno de 470nf, no deberia haber problemas. Elelectrolitico (polarizado) pone el positivo a la salida del amp y el negativo a la entrada del amp.
      Saludos!

      Eliminar
    2. Gracias Sebastian por la pronta respuesta. Probaré a ver.

      Eliminar
  5. Hola otra vez. Lo he armado en protoboard con un LM324, LDR y LED rojo común de 5mm. A la salida del comparador, coloqué el LED indicador, para ver los pulsos. El funcionamiento es errático, debido a que no sé como construir realmente el sensor digital. Provisionalmente, monté la LDR y el LED juntos, y coloqué el dedo tapando ambos. Regulando luego el potenciómetro de 10K conseguía a veces ver los pulsos claramente, y otras, el LED indicador fluctuaba, no registrando un pulso claro. Me temo que debo construir un sensor para colocar el dedo, pero no sé realmente como armarlo.

    Gracias de nuevo.
    Saludos.

    ResponderEliminar
    Respuestas
    1. Si, el sensor es un tema, porwue depende de como apolles el dedo y demas, para mi la mejor forma es un broche que apriete rl dedo. El ldr de un lado y el led del otro, asi no hay interferencias, pero es lo que mas cuesta, la construccion mecanica del sensor.
      Saludos

      Eliminar
    2. Si, el sensor es un tema, porwue depende de como apolles el dedo y demas, para mi la mejor forma es un broche que apriete rl dedo. El ldr de un lado y el led del otro, asi no hay interferencias, pero es lo que mas cuesta, la construccion mecanica del sensor.
      Saludos

      Eliminar
    3. Gracias de nuevo. Buscaré algo donde introducir el dedo, y pondré la LDR en en la yema del dedo y el LED por la parte superior, porque me dí cuenta que al tapar con la otra mano, se mejoraba.

      De nuevo, gracias y saludos.

      Eliminar
    4. Si, yo tuve problemas con el sensor, hasta que encontré la combinación que no metía ruido y luz ambiente.
      Saludos!

      Eliminar
  6. se puede hacer lo mismo pero con un 16f877A y un lcd 2X16 ? necesito hacer uno asi y veo que la programacion no esta en lenguaje c :(
    seria de gran ayuda

    ResponderEliminar
    Respuestas
    1. Buen dia, es posible realizar este proyecto en C con el micrcontrolador que mencionas y el LCD.
      Tenes conocimientos de C y microcontroladores como para abordar el proyecto? para saber que nivel de ayuda necesitas!
      Saludos!

      Eliminar
    2. si las cosas basicas nomas se no llego a armar todo el proyecto desde 0 :(

      Eliminar
    3. En que parte te quedaste? o cuales son las que comprendes y cuales no?

      Eliminar
    4. osea el programa lo e echo en micro code studio y anda pero lo simule en el proteus y al mandar pulsos no me muestra los pulsos correctos sera que el simulador es y tengo que armarlo? :_ de aqui saqe todo pero la parte del buzzer yo no puse ( http://www.isaachernandez.com.ve/monitor-cardiaco-con-pic16f628a/ )

      Eliminar
    5. Hola, Tene en cuenta que el proteus no simula Freescale o al menos este JL3, el diagrama esta realizado en proteus, pero solo eso. Se ha probado directamente en protoboard como se puede ver en el video.

      Eliminar
    6. entonces si yo lo implemento en protobard tiene que andar el proyecto? muchas gracias sebastian perdon por mi ignorancia

      Eliminar
    7. Hola, si, deberia andar, tene encuenta el cableado y demas porque es un circuito "grande", en el video del post lo tengo andando en un protoboard.
      Saludos.

      Eliminar
    8. https://www.youtube.com/watch?v=s2jWT7DgTwY

      Eliminar
  7. Una pregunta hermano, ¿El micro controlador en qué programa se ensambla? Ya que con Mplab de microchip no encuentro el path o la ubicación para este microcontrolador.
    ¿Y además, es posible usar el pickit2 para ensamblarlo? Gracias :V

    ResponderEliminar
    Respuestas
    1. Buen dia, El microcontrolador que se esta utilizando es un Freescale MC68HC908JL3, se encuentra programado en lenguaje ensamblador y se programa con el WinIDE, y el programador utilizado es el MON08.
      En realidad podes usar cualquier compilador y programador que sean para Freescale HC08.
      Tanto el MPLAB como el PicKit son para la marca Microchip PIC, no son para Freescale.
      Saludos.

      Eliminar
  8. Se podrá hacer para arduino?

    ResponderEliminar
    Respuestas
    1. Hola como estas? se que esta lleno de proyectos de medidor de pulsaciones (Arduino Pulse Meter) pero ni bien me haga un tiempo lo subo aca!, tene en cuenta que el circuito electronico sera el mismo lo unico que cambia es el microcontrolador Freescale por el microcontrolador Atmega del arduino, pero el resto es lo mismo.
      Saludos!

      Eliminar
  9. Hola sebas podrias ayudarme con la parte del codigo (en c) para poderlo implementar en un pic18f4550, para poderlo visualizar en una LCD 16x2

    ResponderEliminar
    Respuestas
    1. Hola, tendrías que usar el código este: http://electgpl.blogspot.com.ar/2014/03/frecuencimetro-hasta-30khz.html
      Que mide frecuencia, podes saber la cantidad de pulsos en un minuto. En el programa que te paso estas midiendo cuantos pulsos por segundo, pero podrías hacerlo un poco mas lento y en lugar de contar esos pulsos en 1s contarlos por 10s y después multiplicar el valor por 6.
      ahí en la linea: delay_ms(250); proba cambiarla por delay_ms(2500); eso te va a dar el valor en 10s, a ese resultado multiplicalo x6, habría que probarlo bien para ajustarlo pero es algo así sencillo, ya que es básicamente un frecuencimetro lento.
      Saludos.

      Eliminar
  10. como esta genial el proyecto pero como puedo adaptar el proyecto a un microcontrolador mas comercial y poder quemarlo con un PicKit agradecería su pronta respuesta.

    ResponderEliminar
    Respuestas
    1. Hola como estas, no lo tengo echo para microchip, habría que hacerlo.
      Saludos.

      Eliminar