En aquest projecte volem fer un sistema per monitoritzar el ritme cardíac. Per fer-ho disposarem d'un sensor que ens dona un senyal analògic amb una forma aproximada del pols cardíac. Aquest sensor el tindrem connectat a l'entrada analògica AN2.

El sensor incorpora un LED i un sensor de llum, a part d'altres elements electrònics. Es coloca sobre el dit (amb una cinta que l'aguanta) o al lòbul de l'orella (amb una pinça). El sensor de llum rep més o menys llum provinent del LED segons el moment del cicle cardíac. El senyal de sortida del sensor és similar al que es mostra a la figura següent. Els valors concrets poden ser diferents segons el ritme cardíac, la tensió d'alimentació i la forma com està col·locat el sensor.

Veiem que, fonamentalment, el senyal té una zona vall i un pols. Ens interessen els polsos. Seguint les recomanacions del fabricant, considerarem que es passa de pols a vall en el centre del senyal. Per trobar el centre agafarem el valor màxim i el mínim i cercarem el punt mig. Considerarem que el cicle cardíac comença cada cop que travessem el valor central del senyal en sentit ascendent. A la següent gràfica s'indiquen els valors que acabem de comentar i, en vermell, el nom de la variable que farem servir per guardar-los. Els noms en verd no es corresponen estrictament amb les variables del mateix nom.

Atès que no ens cal molta precisió, llegirem el senyal analògic amb només vuit bits. A continuació presentarem una funció d'interrupció que detecta els inicis de pols i en mesura el període; així com un petit programa que encén un LED quan hi ha el pols i l'apaga a la zona vall. La funció d'interrupció estarà lligada al Timer0 i s'executarà cada 2 ms. Anem a veure quina pot ser la configuració del Timer 0. La taula següent té les possibles opcions:
| Bits | Escala | Període | Iteracions | Preselecció |
| 100 | 1/32 | 32 μs | 62,5 | --- |
| 011 | 1/16 | 16 μs | 125 | 131 |
| 010 | 1/8 | 8 μs | 250 | 6 |
| 001 | 1/4 | 64 μs | 500 | --- |
Triem l'opció d'1/8 de la freqüència. La nostra funció d'interrupció haurà de tenir unes primeres línies en les que es guarda l'acumulador i l'STATUS abans de tornar a carregar la preselecció. En el nostre cas són 8 μs i, per tant, posarem una preselecció de 7 per fer 249 iteracions (una menys de les que diu la taula).
Les variables que emprarem seran les següents:
| Nom | Mida | Finalitat | Observacions |
| Lectura | 1 byte | Valor llegit a l'entrada analògica | |
| Temps | 2 bytes | S'incrementa cada cop que es fa la interrupció (cada 2 ms) | |
| Max | 1 byte | Valor màxim del senyal en un període | |
| Min | 1 byte | Valor mínim del senyal en un període | |
| Centre | 1 byte | Valor mig del senyal en un període | Centre = (Max + Min) / 2 |
| Periode | 2 bytes | Quart de període | Guarda la meitat del nombre d'interrupcions entre dos inicis de pols |
| Comp | 1 byte | Comptador per filtrar soroll | |
| Bits | 1 byte | Variable on guardarem els bits d'estat que fem servir | |
| Pols | 1 bit | S'activa quan el senyal està per sobre del valor mig | Bits,0 |
| Tenim1 | 1 bit | S'activa quan ja hem detectat l'inici del primer pols | Bits,3 |
| Estable | 1 bit | S'activa quan ja hem detectat l'inici del segon pols i, per tant, ja tenim dades útils | Bits,2 |
La lectura i el tractament del sensor el farem amb una funció d'interrupció que es representa al diagrama següent. En el diagrama hem indicat, amb text de color verd, les etiquetes a les que salta el programa en cada punt. Podem observar que la funció té tres parts: una primera en la que es guarden els valors màxims i mínims del senyal mesurat, una segona en la que es fa el tractament del senyal per detectar els inicis i finals de pols i una tercera en la que es detecta que el ritme cardíac és inferior a 30 pulsacions per minut.
La primera cosa que fem a cada interrupció és llegir l'entrada AN2, on tenim el sensor, i incrementar la variable Temps. Si el valor llegit és superior a Centre, mirarem si és més gran que el màxim que tenim guardat. En cas afirmatiu guardarem el nou valor com a màxim. Per al mínim fem una cosa similar però amb un afegit. És freqüent que, després del pic, hi hagi un segon pic en sentit contrari i, també, que hi hagi soroll en la zona vall. Per això no començarem a cercar el mínim fins que hagi passat mig període. Atès que no sabem el que dura un cicle fins que no ha acabat, fem servir les dades del cicle anterior.
A la segona part de la funció mirem si estàvem (a la interrupció anterior) en la part superior (Pols = 1) o en la inferior (Pols = 0). En la superior comprovem si estem per sota de la meitat, en quin cas voldria dir que ja deixem d'estar a la part superior. Una comprovació similar fem en la part inferior però comprovant que hem passat de mig període com a mesura per filtrar soroll. En tots dos casos no fem res fins que hem detectat que estem per sobre o per sota del mig sis vegades (que comptem amb la variable Comp) per tal de filtrar soroll. Quan ja està clar que estem per sota del valor mig desactivem Pols i calculem uns nous valors de Max, Min i Centre a partir del pols que acabem de veure. D'altra banda, quan ja està clar que estem per sobre del valor mig actualitzem el valor de la variable Periode i reinicialitzem la variable Temps. En tots dos casos reiniciem Comp.
Els valors de les variables només són fiables quan ja hem vist dos inicis de pols. Tenim dos bits de control que ens indiquen si les dades són estables o no. Inicialment els bits Tenim1 i Estable valen zero. Quan s'ha detectat el primer inici de pols s'activarà Tenim1 i quan es detecti el segon s'activarà Estable.
A la tercera part es mira si el temps transcorregut és superior a 2,048 s (la variable Temps és més gran que 1024) i si és així es reinicialitzen totes les variables per tornar a buscar el primer pols.

Disposarem també d'una pantalla paral·lel on podrem mostrar, per exemple, les pulsacions per minut. També podem mostrar altres valors o escriure text.
Si, per exemple, ens interessés mostrar les pulsacions a la pantalla, podríem comptar quants polsos es fan en un temps determinat. Per comptar el temps, podem incrementar una variable apropiada sabent que la funció d'interrupció s'executa cada 2 ms.
El programa de prova que conté la funció d'interrupció que hem comentat és el següent. Podem observar que en el bucle principal no hi ha res perquè l'única cosa que fem amb la lectura del sensor és encendre uns LED i això ho hem posat directament al final de la funció. Si fem servir la pantalla, segur que tindrem codi per posar al bucle.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF) #define ValComp .6 ; Nombre de repeticions per eliminar soroll
cblock 0x20 ; Zona de memòria de dades habitual Lectura ; Valor llegit a l'entrada analògica Temps:2 ; S'incrementa cada cop que es fa la interrupció (cada 2 ms) Max ; Valor màxim del senyal en un període Min ; Valor mínim del senyal en un període Centre ; Valor mig del senyal en un període Periode:2 ; Quart de període ; Guarda la meitat del nombre d'interrupcions entre dos inicis de pols Comp ; Comptador per filtrar soroll Bits ; Variable on guardarem els bits d'estat que fem servir ; Pols Bits,0 S'activa quan el senyal està per sobre del valor mig ; Tenim1 Bits,3 S'activa quan ja hem detectat l'inici del primer pols ; Estable Bits,2 S'activa quan ja hem detectat l'inici del segon pols ; i, per tant, ja tenim dades útils W_Copia ; Guardarà el contingut de W durant la interrupció ST_Copia ; Guardarà STATUS durant la interrupció endc
org 0 goto Inici ; Saltem al lloc on hi ha el programa principal nop ; Zona de memòria de programa que no utilitzem nop nop
Interrup movwf W_Copia ; Copiem l'acumulador a W_Copia swapf STATUS,w ; Copiem STATUS a l'acumulador permutant els nibbles clrf STATUS ; Posa a 0 i així segur que el banc és el 0 movwf ST_Copia ; Guarda STATUS permutat a ST_Copia btfss INTCON,T0IF ; Mira si Timer0 ha arribat a zero ; Si hi ha arribat, no fa la instrucció següent goto FiInt ; Si la interrupció no és del Timer0 no fem res Timer0 ; Programa corresponent a Timer0 movlw .7 ; Nova preselecció movwf TMR0 ; Ho posem a TMR0 bcf INTCON,T0IF ; Si ha arribat, desactivem el bit ; Llegim el sensor bsf ADCON0,GO ; Inicia la conversió btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat goto $-1 ; repetim la línia fins que deixi de ser 1 movf ADRESH,w ; Llegeix el valor (8 bits) movwf Lectura ; I el guarda incf Temps,f ; Incrementem Temps btfsc STATUS,Z ; Si s'activa Z vol dir que hem incrementat un 255 incf Temps+1,f ; Si s'activa, incrementem el byte superior movf Centre,w subwf Lectura,w ; W = Lectura - Centre btfss STATUS,C ; C = 1 si Lectura >= Centre goto baix ; Lectura < Centre ; Lectura >= Centre movf Max,w subwf Lectura,w ; W = Lectura - Max btfss STATUS,C ; C = 1 si Lectura >= Max goto mirapols ; Lectura < Max ; Lectura >= Max movf Lectura,w movwf Max ; Guarda el nou màxim goto mirapols ; Passem a la segona part baix ; Lectura < Centre ; Anem a mirar si Temps:2 > Periode:2 ; Si Temps+1 > Periode+1 segur que sí ; Si Temps+1 < Periode+1 segur que no ; Si Temps+1 = Periode+1 cal comprovar si Temps > Periode movf Periode+1,w subwf Temps+1,w ; W = Temps+1 - Periode+1 btfss STATUS,C ; C = 1 si Temps+1 >= Periode+1 goto mirapols ; Temps+1 < Periode+1 ; Temps+1 >= Periode+1 movf Periode+1,w xorwf Temps+1,w ; Ho comparem amb Temps+1 btfss STATUS,Z goto miramin ; Si són diferents és que Temps+1 > Periode+1 movf Periode,w subwf Temps,w ; W = Temps - Periode btfss STATUS,C ; C = 1 si Temps >= Periode goto mirapols ; Temps < Periode miramin ; Temps >= Periode movf Min,w subwf Lectura,w ; W = Lectura - Min btfsc STATUS,C ; C = 1 si Lectura >= Min goto mirapols ; Lectura >= Min ; Lectura < Min movf Lectura,w movwf Min ; Guarda el nou mínim mirapols btfsc Bits,0 ; Mira si Pols està activat goto activat ; Sí ho està movf Centre,w subwf Lectura,w ; W = Lectura - Centre btfss STATUS,C ; C = 1 si Lectura >= Centre goto miratemps ; Lectura < Centre ; Lectura >= Centre ; Anem a mirar si Temps:2 > Periode:2 ; Si Temps+1 > Periode+1 segur que sí ; Si Temps+1 < Periode+1 segur que no ; Si Temps+1 = Periode+1 cal comprovar si Temps > Periode movf Periode+1,w subwf Temps+1,w ; W = Temps+1 - Periode+1 btfss STATUS,C ; C = 1 si Temps+1 >= Periode+1 goto miratemps ; Temps+1 < Periode+1 ; Temps+1 >= Periode+1 movf Periode+1,w xorwf Temps+1,w ; Ho comparem amb Temps+1 btfss STATUS,Z goto sipols ; Si són diferents és que Temps+1 > Periode+1 movf Periode,w subwf Temps,w ; W = Temps - Periode btfss STATUS,C ; C = 1 si Temps >= Periode goto miratemps ; Temps < Periode sipols decfsz Comp,f ; Decrementa Comp goto miratemps ; Si no ha arribat a zero, ja estem bsf Bits,0 ; Activa Pols movf Temps+1,w movwf Periode+1 ; Periode+1 = Temps+1 movf Temps,w movwf Periode ; Periode = Temps bcf STATUS,C ; Volem entrar un zero rrf Periode+1,f ; Dividim Periode per 2 rrf Periode,f clrf Temps ; Posem Temps a zero clrf Temps+1 ; Posem Temps+1 a zero movlw ValComp ; Nombre de repeticions per eliminar soroll movwf Comp ; Ho posa a Comp btfss Bits,3 ; Mira si Tenim1 està activat goto tenimpols ; Si no ho està, l'activa i surt btfss Bits,2 ; Mira si Estable està activat bsf Bits,2 ; Si no ho estava, l'activa goto miratemps activat movf Centre,w subwf Lectura,w ; W = Lectura - Centre btfsc STATUS,C ; C = 1 si Lectura >= Centre goto miratemps ; Lectura > Centre ; Lectura <= Centre decfsz Comp,f ; Decrementa Comp goto miratemps ; Si no ha arribat a zero, ja estem bcf Bits,0 ; Desactiva Pols movf Min,w movwf Centre ; Guarda Min, provisionalment, a Centre movf Max,w addwf Centre,f ; Centre = Max + Min ; Si ens en portem, quedarà a C rrf Centre,f ; Dividim la resta per dos (les que portem entren per l'esquerra) movf Centre,w ; El resultat queda a Centre movwf Max ; I el copiem a Max movwf Min ; i a Min movlw ValComp ; Nombre de repeticions per eliminar soroll movwf Comp ; Ho posa a Comp miratemps movlw .4 ; Equival a menys de 30 pulsacions per minut subwf Temps+1,w ; W = Temps+1 - 4 btfss STATUS,C ; C = 1 si Temps+1 >= 4 goto FiInt ; Temps+1 < 4 reinici clrf Bits ; Posa tots els bits a zero clrf Periode ; Posem Periode a zero clrf Periode+1 ; Posem Periode+1 a zero clrf Temps ; Posem Temps a zero clrf Temps+1 ; Posem Temps+1 a zero movlw .127 ; Valor central del conversor (255/2) movwf Centre ; Ho posa a Centre movwf Max ; Ho posa a Max movwf Min ; Ho posa a Min movlw ValComp ; Nombre de repeticions per eliminar soroll movwf Comp ; Ho posa a Comp goto FiInt tenimpols bsf Bits,3 ; Si no ho estava, l'activa FiInt movf Bits,w ; Agafa el valor de Bits movwf PORTC ; Ho posa al port C; Només actúa el bit 0 (Pols) swapf ST_Copia,w ; Copia permutant ST_Copia a l'acumulador movwf STATUS ; I ho passa a STATUS recuperant el valor d'abans ; de la interrupció swapf W_Copia,f ; Permuta els bits de W_Copia swapf W_Copia,w ; Torna a permutar els bits de W_Copia ; i els guarda a l'acumulador sense variar STATUS retfie ; Torna al programa principal, on s'havia quedat
Inici bsf STATUS,RP0 ; Tria el banc 1 movlw b'10000010' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 010 - Factor d'escala de 8 ; I resistències de pull-up desactivades (valor per defecte) movwf OPTION_REG ; Ho guarda al registre de configuració del Timer0 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada clrf TRISB ; Tot el port B és de sortida clrf TRISC ; Tot el port C és de sortida movlw b'00010000' ; Posa el conversor a 1/8 de la freqüència movwf ADCON1 ; Copia W a la configuració del conversor A/D bcf STATUS,RP0 bsf STATUS,RP1 ; Tria el banc 2 movlw b'00000101' movwf ANSEL ; Configura port AN0 i AN2 com entrades analògiques bcf STATUS,RP1 ; Tria el banc 0 movlw b'00001001' ; activa el conversor A/D connectat a AN2 movwf ADCON0 ; amb el resultat justificat per l'esquerra ; Inicialització de variables clrf Bits ; Posa tots els bits a zero clrf Periode ; Posem Periode a zero clrf Periode+1 ; Posem Periode+1 a zero clrf Temps ; Posem Temps a zero clrf Temps+1 ; Posem Temps+1 a zero movlw .127 ; Valor central del conversor (255/2) movwf Centre ; Ho posa a Centre movwf Max ; Ho posa a Max movwf Min ; Ho posa a Min ; Configurem el Timer i activem interrupcions movlw ValComp ; Nombre de repeticions per eliminar soroll movwf Comp ; Ho posa a Comp movlw .7 ; Presselecció de 7, que són 249 iteracions movwf TMR0 ; Ho posa com a preselecció del temporitzador movlw b'10100000' ; Activem GIE i T0IE movwf INTCON ; Activa les interrupcions globals i la de Timer0 Bucle goto Bucle ; En el bucle no hi ha res end
A continuació posarem els programes realitzats pels grups. Estan tal com els han deixat i tenint present que no els va donar temps de simplificar-los o millorar-los. També pot ser que hi hagi errades ortogràfiques.

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.