Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2015:bio-polygraph

Detektor stresového stavu (lži)

Jakub Rusz, ID: 155601
Jakub Milek, ID: 154641

Úvod

Polygraf je zařízení schopné vyhodnotit zda-li měřený subjekt lže. Využívá psychofyziologické reakce člověka na stresovou situaci. Ve stresové situaci se člověku zvedne srdeční rytmus a zrychlí se mu dech. Správným vyhodnocením změny těchto frekvencí lze vidět, zda jsou měřenému kladené otázky nepříjemné a má-li strach z odhalení případné lži a tím určit věrohodnost jeho odpovědí.. V tomto projektu jsou vstupní signály záznam EKG a záznam dechové křivky z termistoru. Jako předzesilovače slouží měřící jednotky MP35 od firmy Biopac. Zesílené nefiltrované signály jsou přivedeny na analogové vstupy procesoru. V procesoru se EKG signál vzorkuje frekvencí 1 kHz a dechová křivka frekvencí 10 Hz. Filtrace je pomocí IIR filtrů. Výsledné vyhodnocení je posíláno přes sériovou linku do PC.

Použitý hardware

Měřící jednotka Biopack MP35 pro měření EKG.

Měřící jednotka Biopack MP35 pro měření dechové křivky.

K těmto měřícím jednotkám je dodáván software Student Lab, kde ve verzi Pro lze libovolně nastavit zesílení i filtraci vstupních dat. Byli jsme nuceni využít dvě jednotky, protože každá má pouze jeden analogový výstup. Na výstup jednotka posílá pouze zesílený vstup, filtrace je pouze pro zobrazení na PC.

Vývojový kit s FRDM-K64F

Specifikace procesoru je možné najít například zde: https://developer.mbed.org/platforms/FRDM-K64F/

Detail termistoru pro měření dechové křivky

Detail připojení procesoru

Celkový pohled na workspace

Vstupní signály

EKG je elektrická aktivita srdce. Nejjednodušší způsob jak ji zaznamenat je pomocí tří elektrod na končetinách a tak je tomu i v našem případě. Zemnící elektroda je na pravé noze, kladná je na levém zápěstí a záporná na pravém zápěstí. Tyto elektrody vedou na jeden ze čtyř vstupních kanálů na měřící jednotce MP35. Software v počítači zobrazuje filtrovanou a zesílenou EKG křivku a na výstup posílá pouze zesílený signál z vybraného vstupu. Signál je vyveden dvěmi dráty a přiveden na osciloskop pro vizualizaci a na analogový vstup A0 na procesoru. Tepová frekvence se určuje z doby mezi jednotlivými R vlnami, což signalizuje stah levé komory a vypuzení krve ze srdce do krevního oběhu. Tepová frekvence v tepech za minutu se určí jako 60/RR_interval.

Ukázka EKG křivky

Dechová křivka je zaznamenána pomocí termistoru, který je možné připojit k měřící jednotce MP35. Termistor reaguje na změny teplot způsobené prouděním vzduchu při dýchání změnou svého odporu. Výsledkem jsou tedy změny úbytků napětí a to je opět vizualizováno softwarem na počítači a posíláno výstupem na osciloskop a analogový vstup A5 na procesoru. Dechová frekvece se určí podle periody dechové křivky, která připomíná sinusovku. Počet dechů za minutu je tedy 60/perioda. V našem případě je termistor umístěn v náustku aby byl pod větším vlivem proudění vzduchu při dýchání, nebyl ovliněn prouděním vzduchu z okolí a získali jsme tak lepší signál.

Zesílení je v obou případech 5000. V průběhu práce bylo zkoušeno několik různých návrhů filtrů a přesné charakteristiky funkčních filtrů ve finální verzi byly ztraceny. Poslali jsme tedy na filtry Diracův impuls a z výsledků filtrace jsme získali jejich přenosové charakteristiky. Filtrace EKG je pomocí pásmové propusti s mezními frekvencemi 10 Hz a 25 Hz. Filtrace dechové křivky je pomocí pásmové propusti s mezními frekvencemi 0.1 Hz a 1.2 Hz. Oba filtry jsou IIR typu Inverse Chebyshev (Chebyshev II).

Přenosová charakteristika filtru pro EKG

Přenosová charakteristika filtru pro dechovou křivku

Zpracování vstupních signálů

V první části programu je for smyčka, která má za úkol naučit se práh pro detekci R vlny v EKG signálu. Čtení i filtrování je po jednom vzorku v každé iteraci smyčky ve které je nastaven wait na 1 ms čímž je určena vzorkovací frekvece. Neni to tedy přesně 1 kHz, ale vzhledem k jednoduchosti příkazů ve smyčce dostatečně blízko této hodnotě. Z načtených dat se počítá obálka, která má okno o velikosti 7 vzorků, takže se začne počítat až po načtení sedmi vzorků. Při výpočtu obálky se z okna vybere maximum, umocní na druhou a to se uloží jako aktuální vzorek obálky. Tato inicializačni smyčka proběhne 10000x. Výsledný práh se pak vypočítá jako 40% ze 150ti maxim v této učící fázi.

//Smyčka pro učení práhu detekce R vln
for (int i=0;i<10000;i++)
{      
    samples[0] = ain.read_u16();    //přečtení vzorku
    nProcessedSamples = filter1_filterBlock( filter, samples, outputBuffer, inputBufferSize );  //filtrování vzorku
 
    P[c1]=outputBuffer[0];
    c1++;
    if (c1==okno1 || f==1)  //začátek výpočtu obálky
    {
        f=1;
        c1=okno1-1;
        mmx=P[0];
        for (int i=1;i<=okno1-1;i++)
        {
            if (mmx<P[i])
            {
                mmx=P[i];
            }
        }
    obal = mmx*mmx;
    maxima[c2]=obal;
    c2++;
    if (c2==150)    //seřazení pole s maximy od největšího po nejmenší
    {
        c2=149;     //nová hodnota se bude zapisovat na konec pole
        qsort(maxima,150,sizeof(float),compare);    //řadící funkce
    }
 
   for (int i=0;i<=okno1-2;i++)     //smyčka pro posun hodnot v poli o 1 doleva, nová hodnota z ADC se pak zapíše na konec
    {
        P[i]=P[i+1];
    }
    }
     wait(0.001f);
}
 
 
for (int i=0;i<150;i++)     //pole už obsahuje jenom 150 maxim z celého měření v předchozí smyčce
{
    prah=prah+maxima[i];
}
    prah=(prah/150)*0.4;    //výsledný práh jako 40% z maxim

V druhé části programu se určuje normální tepová i dechová frekvence. Před začátkem se spustí timer t pro potřebné výpočty. Vzhledem k proměnlivým šířkám obálek R vln je zaznamenán čas v době překročení prahu a následně čas kdy procesor načte vzorek který je menší než práh a pozice detekované R vlny se vypočte jako průměr těchto časů. Výsledná tepová frekvence se počítá z RR intervalů, neboli dobou trvání od detekce jedné R vlny po detekci následující R vlny. Hodnota BPM (beats per minute) se vypočte jako 60/RR. Pro určení normální tepové frekvence je průměrováno 100 vypočtených hodnot RR intervalů. Pro frekvenci dýchání je zde podmínka, která nabere vzorek každých 100 ms což opět dostatečně odpovídá vzorkovací frekvenci 10 Hz. Zde se po filtraci detekují průchody nulou a čas se zapisuje ze sputěného timeru. Výsledná dechová frekvence je 60/T, kde T je doba mezi 1. a 3. detekcí průchodu nulou. Smyčka se ukončí po detekci 100 tepů, vypočítá se průměr z nasbíraných dat a po serialu se vypíšou výsledné normální hodnoty.

//Smyčka pro určení normálních hodnot tepu a dechové frekvence
while (1)
{ 
    samples[0] = ain.read_u16();
    nProcessedSamples = filter1_filterBlock( filter, samples, outputBuffer, inputBufferSize );
    P[c1]=outputBuffer[0];
    c1++;
    if (c1==okno1 || f==1)
    {
        f=1;
        c1=okno1-1;
        mmx=P[0];
        for (int i=1;i<=okno1-1;i++)
        {
            if (mmx<P[i])
            {
                mmx=P[i];
            }
        }
    obal = mmx*mmx;
    if (obal>prah && f1==0 && c5==0)    //první překročení prahu
    {
        f1=1;
        cas1=t.read();
        led=0;
        nprh=obal;
    }
    if(f1==1 && nprh<obal)      //do nprh se uloží maximální hodnota z obálky nad prahovou hodnotou
    {
        nprh=obal;    
    }
    if (obal<prah && f1==1)     //obálku už není nad prahem
    {
      f1=0;
      cas2=t.read();
      led=1;
      cas[c2]=(cas1+cas2)/2;    //střední hodnota mezi časy překročení prahových hodnot
      c2++;
      prah=nprh*0.4;    //práh je adaptivní, upravuje se podle poslední zaznamenané maximální hodnoty
      c5=50;    //nastavení aby 50 ms nemohla být detekována další R vlna
    }
    if (c2==2)
    {
        c2=1;
        RRu=cas[1]-cas[0];
        cas[0]=cas[1];
        RRu=60/RRu;     //aktuální tepová frekvence
        NormalBPM=NormalBPM+(RRu/100);   //výpočet pro výslednou tepovou frekvenci
        c3++;
    }
    }
    if (c5>0)   //delay pro detekci další R vlny
    {
     c5--;
    }
 
//začátek výpočtů pro dechovou křivku
    if (k%100==0)    //provede se jednou za 100 cyklů, tedy jednou za 100 ms
{
   samples1[0] = ain1.read_u16();
   nProcessedSamples = filter2_filterBlock( filter2, samples1, outputBuffer1, inputBufferSize );
   filtvzor = outputBuffer1[0];
//časy průchodu nulou se zaznamenají vždy jak přechází z kladné do záporné půlvlny
   if (filtvzor>0 && ff1==0)    
   {    
    if(ff2==1)
    {
        ccas2=t.read();
        ff2=0;
        ccas=60/(ccas2-ccas1);  //aktuální dechová frekvence
        Normaldech=Normaldech+ccas;
        c4++;   //počet zaznamenaných hodnot
    }  
       ff1=1;
       led3=1;
       ccas1=t.read();
       ff2=1;
   }
    if (filtvzor<0 && ff1==1)
    {   
        ff1=0;
        led3=0;
    }
}
 
//načtení 100 tepů, zprůměrování dechové frekvence a ukončení smyčky     
     if (c3==100)    
     {
         Normaldech=Normaldech/c4;
         break;
     }
    wait(0.001f);
    k++;
}

V poslední části je nekonečná smyčka, která funguje jako ta předešlá, ale místo zaznamenávání normálu se detekuje překročení normálu o 8 tepů za minutu nebo 5 dechů za minutu. V tom případě se po serialu vypíše, že došlo k překročení a o kolik.

//nekonečná smyčka vyhodnocující aktuální tep, dechovou frekvence a rozdíl od normálu  
while (1)
{  
 
    samples[0] = ain.read_u16();
    nProcessedSamples = filter1_filterBlock( filter, samples, outputBuffer, inputBufferSize );
    P[c1]=outputBuffer[0];
    c1++;
    if (c1==okno1 || f==1)
    {
        f=1;
        c1=okno1-1;
        mmx=P[0];
        for (int i=1;i<=okno1-1;i++)
        {
            if (mmx<P[i])
            {
                mmx=P[i];
            }
        }
    obal = mmx*mmx;    
    if (obal>prah && f1==0 && c5==0)
    {
        f1=1;
        cas1=t.read();
        led=0;
        nprh=obal;
    }
    if(f1==1 && nprh<obal)
    {
        nprh=obal;    
    }
    if (obal<prah && f1==1)
    {
      f1=0;
      cas2=t.read();
      led=1;
      cas[c2]=(cas1+cas2)/2;
      c2++;
      prah=nprh*0.4;
      c5=50;
    }
    if (c2==2)
    {
        c2=1;
        RR[c3]=cas[1]-cas[0];
        cas[0]=cas[1];
        RR[c3]=60/RR[c3];   //průměrování ze tří posledních hodnot tepu
        c3++;
        if (c3==3)
        {
            BPM=(RR[0]+RR[1]+RR[2])/3;
            c3=2;
            RR[0]=RR[1];
            RR[1]=RR[2];
            //pc.printf ("BPM: %f\r\n",BPM);   //možnost nechat si vypsat aktuální tep
            if (BPM>NormalBPM+8)    //pokud aktuální tep překročí normál o 8, tak se vypíše, že došlo k překročení a o kolik
            {
            pc.printf("Tep vyssi o %.2f BPM\r\n",BPM-NormalBPM);
            }
        }
 
 
    }
    }
    if (c5>0)
    {
        c5--;
    }
 
//hodnocení dechové frekvence
     if (k%100==0)
     {
     samples1[0] = ain1.read_u16();
     nProcessedSamples = filter2_filterBlock( filter2, samples1, outputBuffer1, inputBufferSize );
     filtvzor = outputBuffer1[0];
 
    if (filtvzor>0 && ff1==0)
    {    
    if(ff2==1)
    {
        ccas2=t.read();
        ff2=0;
        ccas=60/(ccas2-ccas1);
        //pc.printf("Frekvence dechu: %f",ccas);    //možnost nechat si vypsat aktuální dechovou frekvenci
        if (ccas>Normaldech+5)  //pokud dojde k překročení dechové frekvence o 5, tak se vypíše, že došlo k překročení a o kolik
        {
        pc.printf("Dech vyssi o %.2f za minutu\r\n",ccas-Normaldech);
        }
    }  
       ff1=1;
       led3=1;
       ccas1=t.read();
       ff2=1;
    }
    if (filtvzor<0 && ff1==1)
    {   ff1=0;
 
        led3=0;
        }
     }
    wait(0.001f);
    k++;
}

Kompletní zdrojový kód je dostupný z https://developer.mbed.org/users/customer10123/code/Polygraf_K64F/

Funkce pro filtraci byly vygenerovány na stránce http://www.micromodeler.com/dsp/. Je zde možné vybrat typ filtru, různými způsoby upravit jeho charakteritisku a pak použít vygenerovanou hlavičku a funkce. Hlavičkový soubor se pouze připojí a funkce jsou nakopírovány na konci main.cpp programu. Ve free verzi je u IIR filtrů možné generovat kód pouze pro filtry do 4. řádu.

Demonstrační video s komentářem

Při demonstraci se pro zvýšení dechové frekvence využilo zadržení dechu, což způsobí mírnou hypoxii a srdce tak zvýší svou frekvenci aby se rychlejší cirkulací krve dostalo více kyslíku k buňkám v těle. Ve videu tak bylo náročné uměle překročit tepovou frekvenci z důvodu naměření poměrně vysoké normální tepové frekvence způsobené událostí před videem. Dechovou frekvenci lze jak je vidět snadné uměle zvýšit. Ve fázi učení normální tepové frekvence je průměrováno pouze 30 hodnot aby video nebylo zbytečně dlouhé.

Diskuze

Při detekci tepové frekvence se čeká 50 ms po detekci jedné R vlny. To je z důvodu, že testovaný subjekt může mít vysokou vlnu T, která hned následuje R vlnu a mohla by tak být falešně považována za další R vlnu. Průměr z posledních tří hodnot RR intervalů se dělá aby výsledná hodnota lépe reprezentovala momentální tepovou frekvenci. Jednotlivé po sobě jdoucí RR intervaly se můžou dost lišit, bez průměrování by se hodnota tepu měnila příliš rychle a neodpovídala by reálné hodnotě počtu tepů za minutu.

U měření dechové frekvence je termistor přilepen v náustku pro měření na spirometru. Tento přístup byl zvolen aby nebylo nutné termistor lepit přímo pod nos a také aby získaný signál šlo lépe zpracovat. V reálném použití by však nastal problém, protože s náustkem v puse se špatně mluví a vytvořený proud vzduchu mluvením by příliš kontaminoval naměřená data. Ke zvýšení dechové frekvence dojde při reakci subjektu na otázku, tedy ještě nemluví, proto použití náustku pro detekci dechu v našem projektu by nezpůsobilo znemožnění použití v reálné situaci.

Odkaz na interaktivní vytváření filtrů Micro modeler byl získán ze stránky https://community.arm.com/groups/embedded/blog/2014/02/04/introduction-to-digital-filters-2 odkud taky pochází inspirace pro jejich použití.

Závěr

Cílem projektu bylo vytvořit polygraf s využitím procesoru FRDM-K64F. Výsledný projekt je schopen detekovat zvýšení tepové i dechové frekvence měřeného subjektu oproti jeho normálu, což se shoduje s funkcí polygrafu. V zadání bylo řečeno, že se bude vyhodnocovat i pocení. K tomu nakonec nedošlo z důvodu nespolupráce dalších měřících jednotek od Biopacu. Vhodným vylepšením by bylo vytvořit vlastní zesilovače, bylo by tak možné měření provádět kdekoliv s přístupem napájení.

2015/bio-polygraph.txt · Poslední úprava: 2016/01/17 23:01 autor: Aleš Pohludka