Wireless ECG

Upozornenie: toto je este predbezna verzia, narychlo zbuchana, 19.maja 2008, kedze sa mi nechce ucit na zajtrajsiu skusku. Vsetky obrazky su tu zobrazene zmensene, ak ich otvorite v osobitnom okne, uvidite ich v plnom rozliseni.

Uvod

Po dlhej dobe sa vraciam ku mojmu webu, za ucelom pridania noveho projektu. Tento je znacne rozsiahly a neviem ci sa mi podari predstavit vsetky potrebne casti. Pre istotu iba v rodnom jazyku, mozno neskor ked bude zaujem to prelozim do anglictiny.

Tomuto projektu som sa venoval vramci svojho volneho casu po weekendoch a prazdninach... Stihol som to priblizne za pol roka - necudujte sa, bolo to popri skole a robote. Jednak bolo treba nastudovat vlasntosti operacnych zosilnovacov, ich bezne zapojenia, problematiku Rail2Rail OPAMPov... Z velkej casti pomohla skola (mame nejake tie odborne predmety, na ktorych sa da co-to pochopit, samozrejme nie ze si niekto pomysli ze som nejaky sakra poctivy student co chodi na prednasky - TAK TO TEDA NIE, vacsinou som otravoval mojimi otazkami profesorov na cviceniach...) Doteraz som sa venoval v elektrotechnike iba digitalnej technike, toto bola prilezitost naucit sa a vniknut do sveta analogovej techniky - teda tej skutocnej elektroniky. Vyuzil som teda skusenosti z mikropocitacov, taktiez som konecne nasiel uzitocne a prakticke uplatnenie bluetooth modulu od firmy ConnectBlue OEM-SPA310, ktory stal dost vela - tusim 1600 Sk, sprostredkovala mi ho firma www.rlx.sk, ktoru som o toto poziadal - kedze ho v oficialnom ponukovom katalogu nemaju.

Jedna sa o mobilne zariadenie velkosti zapalkovej krabicky, ku tejto su pripojene 3 elektrody urcene na upevnenie na telo sledovanej osoby. Dve z elektrod su aktivne (mala DPS na ktorej je priamo integrovany operacny zosilnovac v baleni SOIC. Vyhoda tohoto riesenia je ta, ze nie je nutna ziadna priprava pokozky ani vodive gely na zlepsenie prechodoveho odporu. Koniec koncov som zistil, ze tieto elektrody maju ten problem, ze nedrzia dobre na tele... Myslienka aktivnych elektrod pochadza z projektu OpenEEG, kde boli uspesne pouzite na sledovanie mozgovej aktivity. Kedze srdcova aktivita je rovnakej povahy, uspesne sa daju pouzit aj na takyto ucel. Ja som navrhol peknu malicku obojstrannu DPS velkosti 10Sk, na ktorej su umiestnene vsetky potrebne suciastky (IC, odpory, kondenzatory), druha strana (vodiva medena plocha) sluzi ako samotna kontaktna plocha.

Dve taketo elektrody a spominana referencna (iba vodivy spoj, ziadne komponenty) su vedene do hlavneho modulu konektorom PS2. Modul si mozeme predstavit ako bezdrotovy osciloskop, ktory odosiela namerane vzorky z diferencneho zosilnovaca cez bluetooth kanal (profil SPP). Spracovanie je v sparovanom pocitaci, alebo mobilnom telefone.

Prezentacie

Vramci snah zucastnit sa sutaze SVOC (organizovana na vacsine vysokych skol), sa cely vyvoj v poslednych mesiach radikalne zrychlyl ... ako to uz byva zvykom :) Mam teda vypracovany prispevok svoc_final5.doc (WordDoc97) / svoc_final5.pdf (Acrobat PDF) a taktiez prezentaciu ktora moc nehovori... ale mozno sa vam bude pacit prezentacia_ekg_run.ppsx (PowerPoint2003) / prezentacia_ekg.ppt (PowerPoint97). Prezentacia bola smerovana na mobilne zariadenie, ktore v spojeni s mobilnym telefonom vysle varovnu SMS spravu na definovane cislo v pripade ze sledovana osoba javi znamky poruchy srdcovej aktivity. V skratke - ked posle SMSku ked subjekt umre. Prakticke, uzasne :)

Mojou snahou nadalej je najst sikovneho priemyselneho dizajnera, ktory by mi navrhol na toto zariadenie peknu krabicku z vhodnych materialov. Celok by som rad prezentoval dalej nejakej firme, no najradsej by som ho registroval ako priemysleny patent. Ako to uz so mnou byva, nikdy nedovediem veci do finalneho stadia, a skusenosti hovoria, ze je skoda zaujimavy projekt polozit do policky a navzdy nanho zabudnut... A tak ho prezentujem verejnosti prostrednictvom internetu, verim ze zaujme sportovcov, medikov, radioamaterov a hlavne prosim vsetkych aby zariadenie vyrabali pre svoje potesenie a nie pre svoju penazenku. Cize uplatnujem prava dusevneho vlastnictva, ktore este nemam... ale snad budem mat. Povolujem kazdemu jedincovi zostavenie max. dvoch takychto zariadeni, vsetky vacsie vyroby prosim konzultovat so mnou.

Aktivne elektrody

Co-to o nich som uz spomenul v uvode, viac napovia obrazky a schemy v EAGLI. Tieto fotky su urobene este pred finalizaciou elektrod, ktora spocivala v aplikacii tavneho lepidla na povrch elektrody - pri prezentacii som chcel, aby pritomni videli vsetky elektronicke komponenty na elektrode. Na druhej strane to znemoznovalo prakticke pouzitie elektrod.... Tak som teda stranu suciastok zafixoval proti dotyku a korozii tavnym lepidlom. Toto som najprv nacapal len tak na vrch, a potom s plynopajkou v dostatocnej vzdialenosti som ohrieval krivolaky povrch, kym sa lepidlo neroztavilo (asi 200°C) a zacalo sa formovat do pravidelnejsej struktury. Vysledok je velmi slusny, po pretaveni je lepidlo celkom slusne priehladne a je vidiet komponenty...)

Aktivne elektrody
 

Schemy
 

Hlavny modul

Toto je srdce celeho zariadenia, je v nom diferencialny zosilnovac s dvomi obvodmi TLC272D (zdvojene rail2rail op.ampy). Potom je tu malicky 8pinovy mikropocitac PIC, ktory vyuziva interny AD prevodnik. Navzorkovane hodnoty su dalej vyslane na vstupny pin seriovej linky do bluetooth modulu. Tento je prepojeny 4mi pinmi - RX, TX, VCC, VDD. Spatny smer komunikacie (z BT modulu do mikropocitaca) je za ucelom zmeny vzorkovacej rychlosti). Emulovany seriovy port je nastaveny na rychlost 19200 (ci kolko..) baudov. Myslim, ze viacej uz mikropocitac pri 4MHz (interny oscilator) ani nestihal. Kedze firmware je naprogramovany v jazyku C a mikropocitac je nizsej vykonovej rady, nastalo tu zopar problemov... Teda iba jeden :) vstupny pin seriovej linky je zaroven pinom pre prerusenie. Cize ked je prijaty nejaky byte bluetooth modulom a zmeni sa logicka uroven na tomto pine (hi->low), je vygenerovane prerusenie a toto zacne prijimat data... Pouzity kompilator Hi-Tech PicC vsak naserie do obsluznej funkcie prerusenia kopu instrukcii - za ucelom zapamatania si hodnot roznych registrov, alebo uz ani neviem coho... Kvoli tomuto je prvy bajt spolovice strateny. Program teda v obsluhe prerusenia prijme tento poskodeny bajt a potom prijima dalsi jeden byte ktory spracuje...

Firmware mikrokontrolera
#include <htc.h>
#include "config.h"
#include "serial.h"
#include "delay.h"

__CONFIG( BORDIS & UNPROTECT & MCLRDIS & WDTDIS & INTIO );

#define UART_Init()

unsigned int nValue = 0;
unsigned int nClock = 0;
#define CMD_ADDR_BAT 11
const char hex[] = "0123456789ABCDEF";

char message[32];
const char ROM_message[] = "ECG3.0,bat=xx";

char chCmd = 'z';

typedef unsigned int WORD;                                             
typedef unsigned char BIT;

int nFrameIndex;
BIT bNewFrame = 0;


void ADC_StartConversion( unsigned char nAddr )
{
  ADCON0 = nAddr << 2;  // CHS1:CHS0
  ADFM = 1;  // ADRESL = adc&255  ADRESH = analog>>8 (iba dva bity)
  VCFG = 0;
  ADON = 1;
  GODONE=1;  // initiate conversion on the selected channel
}

WORD ADC_GetValue(void)
{
  while (GODONE)
    continue;
  return (ADRESH << 8) | ADRESL;
}

void HW_Init(void)
{
  // main init
  CMCON0 = 0;
  OPTION = 0b10000000;
  PIE1 = 0;
  ANSEL = 0b00000000;    
  INTCON = 0;
  CCP1CON = 0;
  di();                                                 

  // ANSEL
  ANSEL = 0b01010000; // ADCS2:ADCS0 = 101 (fosc/16), 4us per conversion
  ANS3 = 0;  // digital
  ANS2 = 1;  // analog
  ANS1 = 1;  // analog
  ANS0 = 0;  // digital

  // TRISIO
  DIR_UART_RX = DIR_INPUT;
  DIR_UART_TX = DIR_OUTPUT;

  DIR_SIGNAL_ECG = DIR_INPUT;
  DIR_SIGNAL_BAT = DIR_INPUT;

  // GPIO
  PIN_UART_TX = 1;

  // UART INPUT INTERRUPT
  IOC = 0;
  IOC5 = 1;  // GPIO5
  INTEDG = 0;
  GPIE = 1;
  //intcon, pir1
  ei();

}

WORD GetSync(void)
{
  BIT bFrameType = 0;
  BIT bFrameValue = 0;
  // 10 = frame start, 0? = frame bit, 11 = frame end
  unsigned char  nChar = 0;
  if ( nFrameIndex == -1 )
  {
    bFrameType = 1;
    bFrameValue = 0;
    nFrameIndex++;
  } else
  if ( message[nFrameIndex >> 3] == 0 )
  {

    bFrameType = 1;
    bFrameValue = 1;
    nFrameIndex = -1;
    bNewFrame = 1;
  } else
  {
    if ( message[nFrameIndex >> 3] & ( 1 << (nFrameIndex&7) ) )
    {                                           
      bFrameValue = 1;
    }
  nFrameIndex++;
  }
  //return 0;
  return ( bFrameType << 15 ) | ( bFrameValue << 14 );
}
 
void SendValue( WORD wData )
{
  unsigned int delay;
  putch( wData >> 8 );
  putch( wData & 0xff );

  if ( chCmd == 's' )
    return;

  DelayUs(250);
  DelayUs(250);
  DelayUs(250);
  DelayUs(250);
  DelayUs(250);  
  DelayUs(250);
}
                     
void main(void)
{
  unsigned char i;
  for (i=0; ROM_message[i]; i++)
    message[i] = ROM_message[i];
  message[i] = 0;

  HW_Init();
  UART_Init();

  while(1)
  {       
    ADC_StartConversion( ADC_SIGNAL_ECG );
    nValue = ADC_GetValue();
    ADC_StartConversion( ADC_SIGNAL_ECG );
    nValue+= ADC_GetValue();
    ADC_StartConversion( ADC_SIGNAL_ECG );
    nValue+= ADC_GetValue();
    ADC_StartConversion( ADC_SIGNAL_ECG );
    nValue+= ADC_GetValue();

    SendValue( nValue | GetSync() ); 

    if ( bNewFrame )
    {
      ADC_StartConversion( ADC_SIGNAL_BAT );
      nValue = ADC_GetValue();
      nValue >>= 2;  // get 8 MSBs
      message[ CMD_ADDR_BAT     ] = hex[nValue >> 4];
      message[ CMD_ADDR_BAT + 1 ] = hex[nValue & 15];
      bNewFrame = 0;
    }
  }        
}

static void interrupt isr(void)
{
  unsigned char i, j;
  unsigned long l = 0;
  if ( GPIF )
  {
    if ( RxData == 0 )
    {
      getch();  // wrong read
      chCmd = getch();
    }
    GPIF = 0;
  }
}
 Stiahnut zdrojove kody

Hlavny modul zostava z dvoch DPS, jedna je obdlznikoveho tvaru a spomenul som ju v predoslom odseku. Cez dva trojpinove konektory je prepojena s dalsou doskou, ktora sprostredkuje napajanie (su tu dve cesty napajania - dva konektory); a taktiez referencnu uroven ktora signalizuje stav nabitia baterie. Viac informacii je v dokumente pre SVOC. Prvy trojpinovy konektor okrem napajania obsahuje este testovaci pin, ktory je vystupom analogovej casti; cize pin, ktoreho napatie je vzorkovane a posielane na bluetooth modul. Tato napajacia doska je vhodne vytvarovana aby sa na nu dala umiestnit 3.6V bateria velkosti 1/2 AA (oznacenie: SAFT LS14250), typ baterie je "Primary Lithium Thionyl Chloride". Neprijemna situacia je ta, ze sa mi zatial nepodarila najst vhodna nahrada tejto baterie za nabijatelny ekvivalent. Stoji okolo 140 Sk (www.avelmak.sk), v Bratislave v bateriovom svete vam ju predaju za 400 Sk :). Kriterium pre bateriu je napatie 3~5 Voltov. Najprv som rozmyslal nad DC/DC menicom ktoreho schemu mozete najst v praci SVOC, no hodnotte so mnou : PIC pracuje do 2 voltov, BT modul ma vlastny napajaci regulator na 3V, operacne zosilnovace neviem aku maju limit. Je ale dost skoda ze nabijatelne baterie su prave napatia 3.0V, mozno by to aj vydrzalo, ale je to na hranici pouzitelnosti. Pravdepodobne pri poklese napatia by prestal ako prvy fungovat BT modul.

ConnectBlue OEMSPA310
 

Este si neodpustim par slov ku BT modulu. Napriek vysokej cene je to velmi zaujimavy kusok hardweru. Spolocnost connectblue uvolnila viacero firmwarov, ktore sa daju do modulu napalit, z plnohodnotneho BT SPP modulu si mozete vyrobit viackanalovy (dokopy tusim 8 bitov) obojsmerny ovladac (je tu 8 pinov, kazdemu mozeme definovat smer komunikacie...). Ja som samozrejme ostal verny normalnemu rezimu - profil SPP. Zaujemcom vsak velmi silno odporucam objednavat moduly cez firmu SpezialElectronic, ktora vam moduly priamo nakonfiguruje. Problem je tento: BT modul je defaultne nastaveny tak, ze je to seriovy port o rychlosti 9600 baudov 8-n-1, cize bezna konfiguracia... Problem je vsak so synchronizaciou ktora je hardwarova. Prve co potrebujeme, je pripojit modul ku pocitacu cez toto seriove rozhranie. Cize nestaci nam iba prepojit RX, TX signal cez MAX232 obvod ku pocitacu, ale musime taktiez zapojit aj dva piny ktorych mena si nepamatam, tusim to je CTS a DTR. Je to troska skoda, zabil som den, kym som to pochopil :) Takze ak si budete modul kupovat, poziadajte dodavatela, nech vam modul nakonfiguruje tak, aby bol konfigurovatelny on-air. Cize vy len pripojite napajanie (3-5V) a cela konfiguracia prebehne bezdrotovo. Velmi sympaticke :)

Firma ConnectBlue poskytuje po registracii na ich webe uzitocnu utilitku, s ktorou sa da modul nadherne konfigurovovat - nastavenie serioveho portu, heslo, podmienky parovania, moznosti optimalizacie komunikacie (link policy) - s touto mozete optimalizovat modul na nizky odber, na maximalnu interaktivitu (male oneskorenie), velky dosah.... Samozrejme ze v mojej aplikacii bol doraz kladeny na interaktivitu - chcel som aby namerana hodnota bola ihned odoslana do pocitaca a zobrazena aplikaciou... Snazil som sa nastavit modul vseliak - ale zatial bez uspechu. Jedina moznost ako dosiahnut maximalnu interaktivitu bolo odosielanie vzoriek s odstupom asi 1.5ms (^firmware), vysledny tok dat je 300 +- 1 vzoriek za sekundu. Je to uboho malo, ale vysledny signal je napriek tomu velmi pekny. Obsluzna PC aplikacia umoznuje vynechat tuto pauzu medzi odosielanim dat, tym sa zvysi vzorkovacia frekvencia, na druhu stranu, zacne sa uplatnovat interny buffer BT modulu, ktory sa sprava takto: Najprv udaje buffruje, potom ked je buffer plny, odosleho do pocitaca. Vysledok je taky, ze dajme tomu 200 ms neprichadzaju ziadne data, a potom zrazu vsetko pride naraz. Niesom si presne isty, kde nastava problem (moze to byt buffrovanie na strane PC) ale zrejme sa jedna o interny buffer BT modulu - a tym som problem uzavrel :)
Hlavny modul
 

Schemy
 

Na predlohe na plosne spoje je na spodku samotny hlavny modul, potom su smerom hore napajacie moduly - navrhol som ich viacero : DC/DC menic pracujuci do 1.1V (nejak sa mi nepodarilo odfiltrovat rusenie - menic funguje rusi analogove obvody), stabilizator na 5V (pozor, to nie je 7805!, pouzil som nejake specialne cudo s malym stratovym napatim), tento som pouzival vacsinu casu - napajane z 9V baterie, potom tu mame vytvarovanu dosku pre pripojenie 3.6V baterie.

Ukazky signalu

Vysledny signal je sakra cisty - az ma to prekvapilo :) Potlacenie sietovych 50Hz je velmi vyrazne a v okne aplikacie ani nie je pozorovatelne. Po konverzii streamu zo seriovej linky (PC aplikacia umoznuje nahravat prijaty tok do suboru) do RAW formatu, ktory sa da otvorit napriklad programom CoolEdit, je uz citit v signale aky-taky sum, ale myslim ze na zariadenie zostavene z beznych komponentov je to unikatny vykon :) Pri importovani RAW dat nastavime vzorkovaciu frekvenciu 300Hz a format podla nasledovnych obrazkov. Posledne tri obrazky predstavuju konverziu suroveho signalu (inverzia, normalizacia). Na poslednom je vidno kazdu vzorku... neni to nejake extra rozlisenie, ale na sledovany ucel staci.

Nastavenie konverzie
 

Ukazky signalu
 

Spracovanie PC

Pre spracovanie potrebujeme bezny PC (na OS linux zabudnite :), a BT modul. Najprv sprarujeme zariadenia (podla konfiguracie BT modulu zvolime heslo, alebo ziadne nezadame...) Zistime si, na ktorom porte BT modul najdeme *doplnit*, spustime aplikaciu, nastavime port a mozeme otvorit port. Zacneme vidiet graf prichadzajucich hodnot. Elektrody umiestnime na vhodne miesta a vidime elektricku aktivitu nasho srdca. Ak je signal prilis slaby, alebo naopak prilis silny, zmenime zosilnenie pootocenim potenciometra na zakladnej doske. Po chvili, kym sa statisticky modul naladi na vase srdce, zacne pipat v rytme vaseho srdca. Toto moze byt po chvili dost otravne a samozrejme je to mozne vypnut odkliknutim checkboxu Beep v "hartbeat tempo" tabe (ako na poslednom obrazku). Stredny obrazok je zobrazenie FFT transformacie, zvysle ciary znacia 1Hz, 10Hz, a 50Hz, vsimneme si aky je signal krasne cisty na frekvencii 50Hz :).

Ukazky signalu
 

Workspace MS Visual Studio 2005
 Stiahnut zdrojove kody

Taka specialitka ktoru rad spomeniem je, ze som sa pokusil navrhnut jednoduchy PLL system, ktory sa snazit oscilovat subezne s aktivitou srdca. Takyto signal dalej sluzi na vygenerovanie MIDI clocku (tusim command F8, pozri nasledovny kusok kodu). Samozrejme je to vsetko online, takze svoju srdcovu aktivitu mozete pocut vo forme synchronizovanej hudby z vaseho syntetizatora :). Pre syntak Yamaha DJX je potrebne zapnut funkciu External Clock a nastavit nejaky sympaticky rytmus (Style). Sekvencer spusta aplikacia uplne sama. Samozrejme treba prepojit pocitac MIDI kablom... Kto by si to chcel vyskusat, bude musiet zmenit nastavenie vystupneho Midi portu, ked bude cas, mozno k tomu spravim graficke rozhranie, ale cele toto bolo v podstate len pre moju zabavu. Pre komunikaciu s midi zariadeniami som pouzil kniznicu jdkmidi, jej pouzitie je naozaj velmi jednoduche ako vidiet na nasledujucom kode.

ukazka generatora midi clocku
UINT CTabPulse::ThreadFunc(LPVOID lParam)
{
  CTabPulse *lpPulse = (CTabPulse *)lParam;
  jdkmidi::MIDITimedBigMessage msgFirst;
  jdkmidi::MIDITimedBigMessage msgClock;
  msgFirst.SetStatus(jdkmidi::START);
  msgClock.SetStatus(jdkmidi::TIMING_CLOCK);
  BOOL bFirst = TRUE;

  int nLast = -1;
  int nTotalPulses = 0;

  while (1)
  {
    LONG lTime = GetTickCount();
    if ( lpPulse->m_lNotifyTime == 0 )
    {
      Sleep(5);
      continue;
    }
    if (bFirst)
    {
      bFirst = FALSE;
      lpPulse->m_Midi.OutputMessage( msgFirst );
      nTotalPulses = 0;
    }
    LONG lFunDiff = 0;
    LONG lHoldNotify = lpPulse->m_lNotifyTime-lFunDiff;  
    LONG lNotifyLen = lpPulse->m_lNotifyLength;

    lpPulse->m_lNotifyTime = 0;
    int nTicks = 24*1;
    for (int i=1; i<=nTicks; i++)
    {
      LONG lDelta = lHoldNotify - GetTickCount() + i*lNotifyLen/nTicks;
      if (lDelta > 0)
        Sleep(lDelta);
      lpPulse->m_Midi.OutputMessage( msgClock );
    }
    if (++nTotalPulses>=7)
      bFirst = TRUE;
      
  }
}
 

Vsimol som si totiz, ze pri pocuvani elektronickej hudby srdce dost vyrazne synchronne bije s rytmom pesnicky. Napadlo ma teda generovat hudbu podla rytmu srdca, pricom budem rytmus umyselne korigovat na vhodnu hodnotu - napr. Schvalne budem spomalovat hrany rytmus tak, aby srdce zacalo spomalovat, resp. ked bude rytmus prilis pomaly, budem rytmus zrychlovat. Pokusy neboli prilis uspesne - clovek musi byt v uplnom pokoji aby bolo jeho srdce ochotne sa synchronizovat. Celkovo to mozno ani nieje velmi zdrave :)

Cely zjednoduseny popis aplikacie je mozne pozriet v dokumente SVOC, nechcem sa zbytocne opakovat. Pre zaujimavost aspon pridam screenshot zo stromu suborov. Cela aplikacia je celkom prehladne rozdelena, akurat statisticky modul je dost nasilu oddeleny od zvysku. Podstatne odladenejsie je to vidiet v aplikacii pre SmartPhone. Kedze bola tato vyvinuta neskor ako desktop aplikacia, je vyrazne odladenejsia a prehladnejsia. Samozrejme na ukor jednoduchosti - neposkytuje take moznosti - jednoducho zobrazuje graf, BPM rytmus a nejake statisticke udaje.

Spracovanie na SmartPhone

Je to v podstate zjednoduseny klon desktop aplikacie. Caka, kym prijimany signal nepovazuje za platny. V tomto okamihu caka, kedy sa charakter signalu porusi a zacne odpocitavat 15 seknud. Odpocet je mozne zrusit stlacenim lubovolnej klavesy telefonu. Ak odpocet dobehne do konca, odosle SMS spravu na cislo definovane v konfiguracnom okne (zobrazi sa pri starte aplikacie). Tato aplikacia je urobena dost narychlo, necakajte nic uzasne :) Jednalo sa hlavne o prezentovanie a predvedenie pred porotou SVOC. Chystam sa dalej prepisat kod do Javy (ktoru zduse nenavidim a nepovazujem za jazyk), kedze telefony s podporou javy & JSR-082 su podstatne viac rozsirene ako SmartPhony... Aspon zatial... no kedze ja takyto telefon nevlastnim, a zatial sa mi ziadny lacny nepodarilo zohnat, tak vyvoj stagnuje.

Workspace MS Visual Studio 2005
 Stiahnut zdrojove kody

Spracovanie na java telefone

Pcha... zatial neni, ked mi niekto pozica na mesiac telefon, tak bude :) Ja javu zduse nenavidim... Jadro uz napisane mam (otvorenie btspp:// adresy a kreslenie grafu), ale nemam to ako prakticky testovat.

ECG cele zariadenie