MISKOLCI EGYETEM GÉPÉSZMÉRNÖKI ÉS INFORMATIKAI KAR
TUDOMÁNYOS DIÁKKÖRI DOLGOZAT
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba mérnök informatikus hallgató
Konzulens: Dr. Gáti Attila egyetemi docens Elektrotechnikai- Elektronikai Tanszék
Miskolc, 2011
Firmware programozás egészségügyi állapotfelmérő rendszerhez
1
Ferenc István Csaba
Honnan…
Informatikusként elengedhetetlen a nyitottság más szakmák felé. A különböző szakterületek általában sokkal nagyobb értéket képviselnek, ha képesek együttműködni egymással. Az informatikus szakma szépségét is azok a munkák jelentik számomra, amik más szakterületek keze alá dolgoznak, vagy pedig a hétköznapi emberek életét könnyítik meg. Számos példát lehetne felhozni, de egyetemi éveim alatt az informatika, az elektronikai tudományok és az orvostudomány határterületeibe nyertem betekintést. A történet röviden a következő. Dr. Kellényi Lóránd MSc. Ph.D, az MTA Idegélettani Tanszéki Kutatócsoportjának nyugalmazott főmunkatársa keresett saját találmányának nullszériás gyártására, valamint dokumentálására fiatal egyetemistákat. A Bay Zoltán Alkalmazott Kutatási Közalapítvány Nanotechnológiai Kutatóintézetén keresztül az ElektrotechnikaiElektronikai Tanszék közreműködésével készítettük el hallgatótársaimmal a prototípusokat. A projekt lebonyolítására a tanszék munkatársa, Dr. Gáti Attila egyetemi docens szakmai segítségével, és Dr. Pungor András, a kutatóintézet akkori igazgatójának vezetésével került sor. A munka során a feltaláló kapcsolási rajzokat, egy félig kész számítógépes feldolgozó szoftvert és egy kezdetleges prototípust bocsátott a rendelkezésünkre. Ezek alapján készült el öt mérőműszer, és került ki a szoftverrel együtt a kísérletben résztvevő orvosokhoz. A kiváló kísérleti eredmények ismeretében indokolttá vált a mérőrendszer továbbfejlesztése, korszerű technológiákkal történő megvalósítása. Ennek tervezésére és kivitelezésére ismét a replikákat elkészítő csapatot kérte fel a feltaláló. A tervezést részekre osztva komplex feladatként valósítottuk meg, majd a nyári szakmai gyakorlat ideje alatt egy próbapanelen kezdtük felépíteni az új mérőműszert. Az alap funkciók megvalósítása, és a számítógépes valamint mobil platformra készített feldolgozó szoftver fejlesztése is megkezdődött. Praktikusan a részfeladatokat úgy hangoltuk össze, hogy élőben tesztelhessük a rendszert. Az egyetemi kutatómunkákban való részvétel számos előnyös ismerettel vértezi fel a résztvevő hallgatókat. Nem véletlen, hogy a munkaerőpiacra kikerülve ezeket a referenciákat előnyben részesítik a munkaadók. Az iskolapadban szerzett tudás mellé a helytálláshoz elengedhetetlen az ipar világába való betekintés valamint a komplex problémák csoportos megoldására való felkészülés. A problémák mérete legtöbbször meghaladja egyetlen ember kapacitását, így szükségszerű a részfeladatok elkülönítése, és a kooperáció. Ha az egyetemről kikerülve először szembesül az ember ezekkel, minden bizonnyal megpróbáltatást jelent a készségek elsajátítása, ám a tanszéken végzett projektek során sok segítséget kaphatunk a munkavégzéshez mind szakmai, mind a csoportmunka terén adott tanácsok formájában. A megállapodások, kompromisszumok, egymás keze alá dolgozás korántsem olyan egyszerű, mint azt első hallásra gondoltuk. A projekthez szükséges eszköz erőforrásokat közös erővel hoztuk össze. A szerszámokat – azokat, amiket a tanszék nem tudott biztosítani – otthonról hoztuk el, illetve az alkatrészeket részben közös költségvetésből vásároltuk, részben az egyes tagok tulajdonát képezik.
2
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
1.1 Mérőrendszer rövid bemutatása A mérőrendszert egy egységként kezelve elmondható, hogy faladata egyszerű, olcsó és gyors vizsgálati módszerek segítségével átfogó képet adni az orvos számára a vizsgált személy szellemi frissességének állapotáról, időskor esetén annak hanyatlásáról, valamint a keringési fizikai funkciók korhoz köthető változásáról.
1.1.1 A mérőrendszerrel végzett vizsgálatok A mérőrendszerrel végzett vizsgálat sorozat első eleme feltételes és feltétel nélküli reakcióidő mérés. Véletlenszerű időközönként elhangzó 1000Hz-es (magas) sípszóra történő gombnyomás idejét rögzíti a feltétel nélküli reakcióidő mérés (sRT simple Reaciton Time). A feltételes reakcióidő mérés (cRT choice Reaction Time) pedig zavaró jelzésként szintén véletlenszerűen elhangzó 500Hz-es (mély) sípszókkal egészíti ki a feltétel nélküli reakcióidő mérést, ám ez esetben is csak a magas sípszók tekintendők célingernek. A mély sípszóra történő gombnyomás hibás reakciónak számít. A reakcióidő mérése során a vizsgált személynek valamilyen egyszerű számolási feladatot is kell végeznie, képességeinek megfelelően olyat, ami leköti a figyelmét. Neurológiai okokból eltérő eredményeket kapunk ezáltal. A másik eleme a vizsgálatnak a pletizmográfia, avagy a szívgörbe vizsgálat. Ez a vizsgálat a bőrfelszín közeli hajszálerek keringésének megfigyelésén alapszik. A szenzor egy infravörös fényt kibocsátó diódából, és egy megfelelő (a dióda által kibocsátott hullámhosszú fényre érzékeny) fotodiódából áll. A bőrfelszínről visszaverődő fényből a véredények belsejében lévő nyomásingadozásra lehet következtetni. A visszavert jel tehát a szívgörbe, amin a vérnyomás ingadozását értjük. A kapott kép megjelenítése, rögzítése a feladat. A jelen végzett csúcsdetektálással könnyedén megállapítható a pulzusszám, de ennél sokkal szignifikánsabb jellemzők is leolvashatóak, mint például az úgynevezett recovery time – azaz a szívfrekvencia visszaállási ideje. Ebből következtetéseket lehet levonni a szív terhelhetőségére vonatkozólag.
1. ábra - szívgörbe - pletizmográfia
A vizsgálat harmadik és utolsó eleme a fiziológiás tremor vizsgálata. Ez a kéz fiziológiás remegésének kétdimenziós vizsgálata. A fiziológiás tremor analízissel 3
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
gyakorlatilag az agyi szabályzás gyorsasága mérhető fel, milyen gyorsan képes reagálni a test a kinyújtott karra ható gravitációs erőre, és milyen pontosan képes azt kompenzálni. A kéz remegését piezoelektromos gyorsulásmérő segítségével rögzíti a műszer. A kézremegés frekvenciakomponenseinek megállapítása a feladat, amely adatokat a feldolgozó egység a rögzített jelsorozat FFT analízisével állít elő. Az orvos számára a szignifikáns frekvenciakomponenseket kell megjeleníteni.
1.1.2 A mérőrendszer fizikai felépítése A mérőrendszer két fő részből áll. Az egyik a mérőegység, amely feladata a mérendő mennyiségek digitalizálása, és továbbítása. Vezeték nélkül is használható hordozható eszközt terveztünk meg. A másik a feldolgozó egység, az adatok tárolására és elemzésére szolgáló komponens. Erre a célra egy egyedi szoftvert készítünk, amely képes kommunikálni a mérőegységgel. A feldolgozás alapvetően számítógépen történik, ám a hordozhatóságot szem előtt tartva a mérőrendszerhez egy egyszerűsített feldolgozó szoftver is készül Android platformra, amely lehetővé teszi az adatok okostelefonnal történő rögzítését. Mind a PC-s szoftver, mind a mobil alkalmazás közös protokollt használ a mérőegységgel való kommunikáció során, és az archivált adatok formátumát tekintve is.
2. ábra - a mérőrendszer sematikus ábrája
A mérőrendszer kis mérete, hordozhatósága valamint egyszerűsége lehetővé teszi, hogy a háziorvosok mindennapos eszközévé váljon, és a vizsgálati rutin része lehessen a feltaláló módszere. Olyan korszerű technológiákat kell alkalmazni, mely sorozatgyártásra való igény felmerülése esetén miniatürizálható.
2
Hogyan…
Az új műszer tervezése és a prototípus összeállítása során az egyéni érdeklődésnek megfelelően egyeztünk meg a részfeladatok elosztásában. A Miskolci Egyetem informatikus hallgatójaként Bartók Roland foglalkozik az Android alapú mobil alkalmazás fejlesztésével és Simon Csaba írja a számítógépes szoftvert. A mérőegység hardveres részének összeállítását Fodor Gábor Dénes végzi, aki villamosmérnök és mérnök informatikus szakot végez párhuzamosan. A mérőegység programozása (a firmware elkészítése) valamint digitális áramkörök kiválasztása pedig az én feladatom. A munka során egy alkalmas mikrokontrollert, kompatibilis gyorsulásmérőt, valamint kommunikációs periféria modulokat kellett választanom, majd programoznom ezeket az eszközöket. 4
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
2.1 A digitális áramkörök kiválasztása A feltaláló által tervezett mérőműszer, amelyet 5 példányban legyártottunk, több tucat nagyméretű, nagy fogyasztású TTL1 IC-t tartalmazott. A számítógéppel csak egy irányú, analóg kommunikációra volt képes. Az áramkör működésébe azok reprodukciója és dokumentálása során mély betekintést nyertünk, és világossá vált, hogy a mai mikrokontrollerek által nyújtott lehetőségeket kihasználva jóval kisebb hardveres mérőeszközt készíthetünk. Digitális áramkörök, illetve digitális kommunikációs perifériával rendelkező mérőmodulok használatával olcsó, kevés alkatrészből megépíthető mérőegységet terveztünk, amely funkcionálisan minden vizsgálat elvégzésére alkalmas. Az alkatrészek helyes megválasztása lényeges momentuma volt a munkálatoknak, és igen összetett szempontrendszert kellett alkalmazni a folyamat során. Többek között ez is minden bizonnyal kiemelkedő fontosságú tapasztalatnak számít. Az elektronikai piac rendkívül sokféle, jó hírű gyártók százai, alkatrészek milliói közül lehet válogatni. Ez azonban nem csak azt jelenti, hogy jó eséllyel minden megtalálható, hanem annak a veszélyét is magában hordozza, hogy a sok lehetőség közül nem sikerült a legmegfelelőbbet megtalálni, felismerni. Meg kellett tanulni az adatlapok gyors és részletekre is kitérő olvasását, azok összehasonlítását. Összetettebb alkatrészeknél (és esetünkben minden alkatrész ide tartozik) sok paramétert kell összehasonlítani, és mivel sok gyártó szolgáltat különböző megoldásokat ugyanazon problémára, az angol nyelvet leszámítva minden egyes adatlap más szerkezetű, más felépítésű. Az alapfunkciókhoz illeszkedve a következő fejezetekben bemutatom a kiválasztott alkatrészeket.
2.1.1 Mikrokontroller A mikrokontroller, mikrovezérlő egyetlen szilícium lapkára integrált számítógép. Processzor, műveleti memória, adat- és programmemória, több digitális I/O port valamint számos vezérlési feladatokhoz használt periféria illesztésére alkalmas áramkör, mint például analóg-digitál átalakító, kommunikációs interfészek, 3. ábra - mikrokontroller számlálók, időzítők találhatóak ezekben az eszközökben. A mikrokontroller választása az analóg technológiák, vagy a sorrendi hálózatok alkalmazásával szemben azzal indokolható, hogy jóval kevesebb különálló alkatrészt igényel, mivel egyetlen IC sok feladatot képes ellátni, kisebb áramkör készíthető ezáltal. Kevesebb alkatrész energiatakarékossági szempontból és az eszköz méretét figyelembe véve is praktikusabb. Az sem elhanyagolandó szempont, hogy az áramkör átépítése nélkül, mindössze a programkód módosításával változtatható meg a működése. A modern kommunikációs csatornák alkalmazásához pedig elengedhetetlen valamilyen programozható áramkör alkalmazása. Így tehát sok integrált áramkör helyett mindent egyben, szoftveres támogatással valósít meg egy mikrovezérlő.
1
TTL – Transistor-transistor Logic 5
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
A legismertebb mikrokontroller gyártók kínálatát végignézve a választás az AVR mikrovezérlő családra esett, amelyet az Atmel cég fejlesztett ki. Ezek a mikrokontrollerek minden szükséges kiegészítő áramkörrel rendelkeznek, jól dokumentáltak, megfizethető áron érhetőek el, és a fejlesztő eszközök is könnyen beszerezhetőek. Az ATMega32 mikrovezérlő 8 bites RISC processzort tartalmaz, 32kB programmemória áll a programozó rendelkezésére, 10bit-es felbontású kétoldali közelítéses (SAR - Successive Approximation) típusú AD átalakító, 3 időzítő/számláló áramkör, melyek közül kettő pulzusszélesség-modulációra is alkalmas. I2C, USART, SPI kommunikációs protokollokat támogat, belső órája 1-8 MHz közt hangolható, és külső kvarc oszcillátorral akár 20MHz-es órajellel is vezérelhető. Fejlesztési célokra jó választásnak tűnt – és az idő igazolta is ezt – mert kellően sokoldalú áramkör, és minden fontos funkció megvalósítható a segítségével. Beszerezhető DIP-es (furatszerelt) és SMD-s (felületszerelt) kivitelben egyaránt. A projektben a könnyű kezelhetősége miatt a DIPes tokozású, 40 lábas IC-t használunk. A reakcióidő mérés megvalósításához milliszekundum nagyságrendben pontos órát kell készíteni megfelelően megválasztott órajel frekvencia és számlálók segítségével, amiről később még szó lesz. A kétféle (mély és magas) sípszó hangfrekvenciás jelének generálása a mikrokontrollerbe épített kiegészítő áramkörök segítségével történt. A pletizmográfia vizsgálat hardware igénye egy szűrő-erősítő áramkör – amivel a team villamosmérnök hallgatója foglalkozott – és ennek a jelkondicionáló áramkörnek a kimenetén megjelenő feszültséget egy analóg-digitális átalakító segítségével kell digitalizálni. A legtöbb mikrokontrollerben van ilyen modul, de nem mindegyik képes kellő felbontásra és sebességre. Szempont volt a mikrokontroller választásánál, hogy az igényeknek megfelelő pontosságú és sebességű konverter legyen benne. Az alábbi ábra segít összefoglalni, milyen hasznos modulok vannak a mikrovezérlőben, és mit mire használunk.
4. ábra - Mikrokontroller modulok
6
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
2.1.2 Gyorsulásmérő A tremor analízishez használt gyorsulásmérő esetében olyan eszközt kerestem, ami digitális interfésszel rendelkezik, és nincs szükség kiegészítő, külső áramkörre, hanem az eszköz közvetlenül csatlakoztatható a mikrokontrollerhez. A gyorsulásmérők terén is nagy választékot találtam, ám anyagi szempontból már kevésbé volt előnyös a helyzet. A legtöbb gyorsulásmérő igen magas áron szerezhető be. A másik problémás szempont a szerelhetőség. Mivel teszt projektről van szó, célszerű lett volna furatszerelt (DIP) tokozású alkatrészeket választani. A mai integrált áramkörök általában sokkal kisebb tokozásban kerülnek felhasználásra, a kis méret ugyanis fontos szempont a modern berendezéseknél. Kifejezetten fejlesztőknek, és teszt applikációk részére vannak furatszerelt tokozású, vagy annak megfelelő méretű nyomtatott áramkörre szerelt alkatrészek, ám ezek ára még magasabb. A digitális gyorsulásmérőkről érdemes tudni, hogy a legelterjedtebb technológia a piezoelektromos működési elvű mikroelektro-mechanikus rendszer (MEMS Microelectromechanical System). A tehetetlenségi erő egy apró mechanikus rendszerre hat, ami piezoelektromos érzékelőre nyomást gyakorolva a villamos jellé alakítja azt. Az 5. ábra - gyorsulásmérő érzékelők számától függően léteznek két és háromdimenziós szenzorok is. A méréshez két dimenzió elemzése szükséges, de a szoftver háromdimenziós adatok feldolgozásával meg tudja határozni a függőleges és vízszintes irányvektorokat, és az ennek megfelelő összetevőket. Ezáltal bármilyen pozícióban elvégezhető a vizsgálat. Az analóg gyorsulásmérők ezt a jelet felerősítve, szűrve szolgáltatják további feldolgozás céljára. A feltaláló eredeti műszerében ilyen eszközt alkalmazott. A digitális gyorsulásmérő ugyanilyen alapokon működik, ám a tokba be van építve az analógdigitális átalakító is, valamint interfész modul (esetenként több is). Legtöbb esetben képesek önmagukat hangolni, esetünkben az érzékenység is állítható. Léteznek protokollok áramkörön belüli, chipek közti kommunikációra. Ilyen az I2C vagy az SPI, de ezekről később, az alkalmazásakor bővebben esik szó. A digitális gyorsulásmérők is ilyen szabványos protokollok alkalmazásával kezelhetőek.
Szűkös anyagi erőforrásaink miatt egy olyan gyorsulásmérőt választottam, amit magunk tudunk forrasztani. Tesztelési céljainknak ez is megfelel, egy esetleges következő verzióba azonban várhatóan másik eszköz kerül bele. A LIS3LV02DQ nevet viselő IC volt a befutó, aminek ugyan nem DIP-es tokozása van, de a mellékelt 6. ábrán látható módon egy varia-nyákra 6. ábra forrasztottuk. Így a próbapanellel összeköthettem, és a tesztelési fázisban már használhattuk ezt az eszközt is. A varia-nyák egy olyan előre gyártott LIS3LV02DQ nyomtatott áramköri lap, ami valamilyen séma szerint tartalmazza a lyukakat és vezetősávokat. Biztosítja az alkatrészek távolságát, rögzíthetőségét, és a valós áramkör forrasztással, valamint vezetékezéssel alakítható ki rajta.
7
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
2.1.3 Interfész modulok Nem elegendő a vizsgálathoz szükséges mennyiségek mérése, továbbítani is kell azokat a feldolgozó szoftver részére, ami rendszerint egy másik eszközön fut. A számítógép és a mérőegység közti analóg kapcsolatot – melyet egy hangkártyával történő analóg digitális átalakítás biztosított a feltaláló rendszerében – szabványos digitális kommunikáció váltja fel. Vezetékes és vezetéknélküli megoldások is szóba jöttek. Mindkét mód alkalmazása indokolt más-más szempontból, ezért végül az a megállapodás született, hogy egy vezetékes, és egy vezeték nélküli technológiát is beépítünk a rendszerbe. A vezetéknélküli technológia a könnyen kezelhetőséget és a hordozhatóságot szolgálja, viszont számos problémát vet fel. A vezetékes kommunikáció alapvetően egyszerűbben megvalósítható, tesztelési feladatokra leginkább ezt választják. Más megközelítésből hordozható eszközről lévén szó, az áramellátást akkumulátor biztosítja, amit időről időre tölteni is kell. Szempont volt, hogy minél kevesebb csatlakozó kerüljön az eszközre, és széles körben használható legyen. Vezetékes kommunikációs csatornák közül a legegyszerűbbnek a soros port bizonyult, ezért a fejlesztést ezzel kezdtük el. A soros port manapság elavultnak számít önmagában, ám az egyszerűsége miatt sok helyen alkalmazzák más eszközön emulált adatkapcsolatként. Mind az USB, mind Bluetooth támogatja virtuális soros portok kreálását, és ezek a legelterjedtebb interfészek PAN-ok létrehozására. Az USB alkalmas a tápfeszültség biztosítására is, melyről az akkumulátor töltése is megoldható. Vezetéknélküli hálózati kapcsolatok közül a legelterjedtebb a Bluetooth, ezért ilyen megoldásokat kerestünk. Sokféle Bluetooth modul kapható egyedi áramkörökhöz tervezve, amelyek a legelterjedtebb chip-chip kommunikációs protokollokat támogatják. Esetünkben a 2. osztályba tartozó modulok az ideálisak,lévén azok hatótávolsága 10m. Ez a távolság elegendő az orvos-beteg távolság lefedéséhez egy vizsgálat során. A fent említettek alapján a BTM-112 típusú Bluetooth interfészt alkalmaztam. A teszteléshez valódi soros portot használtunk, mert ennek a legkisebb a hardware igénye, de a Bluetooth modult is elkezdtem programozni. Az áramkört úgy tervezte meg a csapat villamosmérnök tagja, hogy az USB interfész modul is könnyedén csatlakoztatható legyen.
2.1.4 Kvarc oszcillátorok – külső órajel a mikrovezérlőhöz Minden processzornak szüksége van egy órajelre a működéshez. A digitális áramkörök esetében ez beépített rezonátorból, vagy külső kristályból származó órajel lehet. Az ATMega32 is, mint sok más mikrovezérlő, belső órajel generátorral is rendelkezik, ami különböző frekvenciákra hangolható. Ez a belső óra azonban nem elég pontos az idő méréséhez, vagy más precíz feladatokhoz. Sok esetben ezek a mikrovezérlők valamilyen adatfolyammal dolgoznak, ahol meghatározott az adatátviteli sebesség. Ilyenkor elengedhetetlen egy pontos órajel. Külső kristályoszcillátort is lehet csatlakoztatni, ha szükséges. Esetünkben nagyon is indokolt a pontos reakcióidő mérés érdekében. Egy részről a pontosság indokolja, másrészről pedig az, hogy a belső óra legfeljebb 8MHz-es órajelet tud szolgáltatni. A kommunikációs csatornák órajeleit is a rendszer órajelből szokás előosztással előállítani. Azért hogy az osztás után megfelelő értékek jöjjenek ki, nem csak kerek értékű kristályok vannak, speciális számokkal is találkozhatunk. 8
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Vegyünk egy példát. A soros kommunikáció, RS-232 használatakor a táblázatban található jelzési sebességekkel (baud rate) dolgozhatunk. A soros kommunikációhoz van egy USART (Universal Synchronous Asynchronous serial Receiver and Transmitter) modul az AVR mikrovezérlőkben. A kommunikációhoz használt frekvenciát a rendszer órajeléből tudjuk előállítani osztással. Ahhoz hogy ez jól működjön, az osztónak egész számnak kell lennie. Minimális tűrés megengedett, de a sebesség növekedésével erre egyre érzékenyebb a rendszer. Az előosztót az AVR-ekben egy UBRR (USART Baud Rate Register) nevű regiszter értéke adja. Ez egy 16 bites regiszterpár, előjel nélküli 16 bites egész szám befogadására képes. Ebbe a regiszterbe a következő módon számolt értéket kell beírni inicializáláskor: UBBR =
F_CPU BAUD_RATE * 16
-1
Az F_CPU a rendszer órajel. Visszafelé pedig a következő képlettel számolhatunk: BAUD_RATE =
F_CPU 16*(UBRR+1)
F_CPU 8000000 Hz
Baud rate [bps] 9600 19200 38400 57600 115200 230400 460800 921600
UBRR 51 25 12 7 3 -
Számolt baud rate [bps] 9615,384 19230,769 38461,538 62500 125000 -
Hiba [%]
F_CPU 11059200 Hz
Baud rate [bps] 9600 19200 38400 57600 115200 230400 460800 921600
UBRR 71 35 17 11 5 2 -
Számolt baud rate [bps]
Hiba [%]
9600 19200 38400 57600 115200 230400 -
0,16% 0,16% 0,16% 8,51% 8,51% -
0,00% 0,00% 0,00% 0,00% 0,00% 0,00% -
A soros kommunikáció a baud rate 5%-os hibáját képes tolerálni. 8 adatbitet egy start és egy stop bit foglal keretbe. 10 bitenként van szinkronizálva a kommunikáció,10 bitet kell mintavételezni. Ideális időzítés esetén a mintavételezés a bitidő felénél történik. Ez alapján addig helyes a kommunikáció, amíg 10 bitenként legfeljebb fél bitidőnyit csúszik el a mintavételezés. Így jön ki az 5%. Mivel a kommunikáció két résztvevős, 2,5% hiba megengedett eszközönként. Készítenek olyan kristályokat, amik pontosan eloszthatóak, így a prototípushoz is ezek közül válogattam. Az alsó ábrán jól látható, hogy 230400 baud/s-ig hibátlanul működhet a soros kommunikáció, a felsőn viszont 8MHz-es órajellel csak időzítési hibával. Jelenleg az alsó táblázatban lévő 11,0592MHz-es kristály oszcillátorral működik a műszer, 115200bps jelzési sebességgel, 1 start és 1 stop bittel kommunikál.
9
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
2.2 Prototípus építése A fenti alkatrészek összeszereléséhez szükség volt még egy breadboardra (protoboard) amelyen összeállítottam, felélesztettem az áramkört. A breadboard meghatározott séma szerint elektromosan összekötött lyuksorozat. A lyukak távolsága megfelel a DIP (dual in-line package) lábkiosztásnak, 2,54 mm így ilyen alkatrészek szerelhetőek össze rajta. Praktikus mikrokontrollerrel történő fejlesztés elkezdéséhez, mert a néhány szükséges külső áramköri elemet 7. ábra - breadboard forrasztás nélkül lehet csatlakoztatni. Gyorsan szerelhető, gyorsan átalakítható a kapcsolás egy ilyen kártyán. A projektünk vége felé haladva kinövi ezt a környezetet, és már a tesztelés során is jelent néha problémát, hogy a sok érintkező felület miatt gyakoriak az érintkezési hibák. Kiindulásnak mindenképpen kielégítő megoldásnak bizonyult ez a technológia.
3
Tesztelő kártya készítése
A mikrokontroller, és a kommunikációs alapséma kidolgozása után, hogy a mérőműszer fejlesztésével párhuzamosan a számítógépes szoftver készítését tesztelési lehetőséggel támogassam, egy tesztelő kártyát építettem, ami kizárólag a mikrokontrollert, egy soros port illesztő IC-t (MAX232) valamint három gombot és néhány LED-et tartalmaz. Az eszköz feladata, hogy véletlenszerű, illetve előre generált jelsorozatot küldjön soros porton keresztül a számítógépnek. A számítógépes szoftvernek így minden komponense tesztelhető. A kommunikációtól a kirajzoláson át az archiválásig. A módváltó gomb (B2) megnyomásával különböző üzemmódok közt lehet váltani. A második verzióban pedig már a reakcióidő mérés is működik, lévén semmilyen extra perifériát nem igényel. Sípszó helyett LED felvillanására kell gombot nyomni. Az alábbi táblázatban vannak az üzemmódok összefoglalva:
N 0 1 2 3 4 5 6
PLET szinusz szinusz szinusz szinusz ---
Üzemmódok TREM_X TREM_Y TREM_Z random random random szinusz szinusz szinusz eltolt szinusz eltolt szinusz eltolt szinusz random ----------STOP – csak a reakcióidőmérés fut goto(0);
Jel frekvencia 1kHz 1kHz 1kHz 2kHz 4kHz
10
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
A tesztelő kártyán lévő gombok funkciói: R B1 B2
-
Reset. Újra indítja a µC2-t (boot idő alatt nem küld semmit) Reakcióidő mérő gombja Módváltó gomb
A kártyán lévő jelzőfények jelentése: Sárga LED - Reakcióidő mérő magas sípszója helyett Piros LED - Reakcióidő mérő mély, zavaró sípszója helyett / Módváltás Zöld LED - soros kommunikáció folyamatban A tesztelő kártya programja azon az elven működik, hogy inicializáláskor egy választható mintával feltölt egy tömböt, és annak a tartalmát küldi el többször egymás után. Szinusz, eltolt szinusz jelek, fűrészfog jel készítésére írtam függvényeket. Véletlenszám generálásra is van lehetőség, akárcsak a hagyományos C programozásnál. A véletlenszám generátor pszeudo-random egész számot ad vissza 0 és 32767 közti intervallumból. A seed értéket állítva reprodukálható a számsorozat. Teszteléskor hasznos tulajdonság, ám a végleges műszerben is kell véletlen számot generálni, és ha minden bekapcsolás után ugyanaz a számsorozat következne, meg lehetne tanulni a reakcióidő mérés időközeit, és ez torzítaná az eredményeket. Ráadásul a valósnál jobb eredményekkel vezetné félre a felhasználót.
2
µC - mikrokontroller 11
Firmware programozás egészségügyi állapotfelmérő rendszerhez
4
Ferenc István Csaba
A mérőeszköz programozása
A mérőegység fontosabb hardware összetevői bemutatásra kerültek. A belőlük épített kapcsolás részleteivel ez a dolgozat nem foglalkozik, a továbbiakban a fenti komponensek programozása, kezelése a téma. Mint minden szoftverkészítés, az egyedi hardware-en történő programozás is precíz tervezést igényel. Annál is inkább, mert az erőforrások (memória, processzor idő, instrukciókészlet) mikrokontrolleres környezetben jóval szűkösebbek, mint mondjuk PC-re történő fejlesztés esetében. Operációs rendszer híján minden hibakezelés a programozó feladata. Más szemléletmódot igényel az ilyen szoftverkomponensek fejlesztése. Hosszas böngészés, adatlapok tanulmányozása sok esetben napokat vesz igénybe, aminek eredménye a forráskódban mindössze néhány sor. Egy-egy kontrol regiszter helyes beállítása, inicializálása pár instrukcióval megoldható, ám e regiszterek tartalmának helyes megválasztása precíz előkészítést igényel. Nagy segítséget nyújt ebben a munkában egy jól összeállított fejlesztőkörnyezet, amelyet esetünkben az Atmel cég ingyenesen a programozók rendelkezésére bocsátja. Ez a szoftver az AVR Studio. A dolgozat írásával egyidőben jött ki az 5. verzió, ami sok újdonsággal szolgál, ám a projekt ideje alatt eddig a 4.-es kiadást használtam, ezért erről osztok meg pár gondolatot. A fejlesztőkörnyezet Windowsos platformra készült, az avr-gcc fordítót (illetve annak Windowsos verzióját) használja, és virtualizációs lehetőséget is kínál. A programfejlesztéshez assembly, és C nyelvet lehet választani. A legtöbb Atmel által gyártott mikrokontroller pontos regiszterkészletét ismeri, így lehetőséget nyújt azok szimbolikus nevekkel való használatára, valamint külön ablakban meg is lehet jeleníteni a regiszterkészletet, ahol szöveges elnevezéseket olvasva a programozó könnyedén eligazodhat az éppen használt platformon. Az alábbi két ábrán látható, hogyan segít eligazodni a regiszterek közt a fejlesztőkörnyezet. Az I/O View nevű ablakban faszerkezetbe rendezve találjuk meg a regisztereket, és akár bitenként kaphatunk leírást azok jelentéséről, használatáról.
8. ábra - I/O View ablak - AVR Studio 4
12
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
A firmware elkészítéséhez a C programozási nyelvet választottam. Ez az AVR platformra legjobban dokumentált, és általam is legjobban ismert programozási nyelv. A standard C függvénykönyvtárak mellett a mikrokontroller-család számára fejlesztett avr-libc függvénykönyvtárat használtam. A függvénykönyvtár használatát a Módosított BSD licenc szabályozza. A kutatómunka során végzett tevékenységünk teljes mértékben megfelel a licencben foglaltaknak. A programozás során igyekeztem törekedni bizonyos konvenciókra, mint például az angol nyelv használata a változó- és függvénynevekben valamint a kommentekben. Igyekeztem mindent sok kommenttel ellátni a forráskódban, hogy később akár én, akár más programozó eligazodhasson benne. További fontos szempont volt, hogy modulonként tagoltam a forrást, így több kisebb fájlból áll a projekt. Egyszerű directory struktúrában verziókövetéssel dolgoztam, így bármelyik korábbi verzióhoz vissza tudok nyúlni. Illetve egy-egy új periféria hozzáadásánál külön „HelloWorld” programokat is készítettem, hogy az alapvető működést, és beállítást azon tesztelhessem. A firmware által megoldandó feladatokat a 9. ábra összegzi. A legalsó réteg moduljait egyesével implementáltam és teszteltem. Modulról modulra állt össze a működtető rendszer. A vizsgálati és kommunikációs modulok programozását a hardware építésével párhuzamosan végeztem. Kronológiai sorrendben először a soros kommunikációt (RS-232) valósítottam meg. Eleinte csak szövegesen, terminál ablakban jelentek meg az eredmények, amíg a számítógépes szoftver olyan stádiumba nem érkezett, amikor már képes volt megjeleníteni a mért értékeket. Természetesen a szöveges, terminálos módszerhez még gyakran vissza kellett nyúlni a fejlesztés során. A reakcióidő mérés volt az első vizsgálati modul, ami elkészült. Ezzel együtt természetesen a „felhasználói interfész” is felkerült az eszközre, ám ez drasztikusan leegyszerűsödött, mindössze két gombot, és négy LED-et foglal magába. A pletizmográf erősítő áramköre viszonylag hamar elkészült, ezért ez volt a következő modul. Az analóg-digitális átalakító felélesztése következett, és nagy örömmel néztük a monitoron az első kirajzolódó jeleket. Ezt követően gyorsulásmérőhöz tartozó kódrészek születtek meg, amelyek a tremor analízishez szükséges adatokat szolgáltatják. A soros kommunikáció vezetéknélküli közegre való átültetéséhez egy Bluetooth modul kezelését iktattam a programba. A közeghozzáférési protokoll kezelését a modul firmware-je biztosítja, így a modul konfigurálását leszámítva transzparens maga az átviteli közeg. A számítógépes oldalon lévő driver virtuális soros portként látja a rendszert. Az USB hasonló elven fog működni ám ennek kidolgozására még nem került sor.
9. ábra - Vezérlési feladtok
13
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.1 Perifériakezelés, driverek A mikrokontroller perifériái is alapvetően két részre, input és output eszközökre oszthatóak. A driverek, eszközkezelő programrészek, rutinok egyfajta absztrakciót biztosítanak a perifériák használatához. Legyen szó egy bonyolult gyorsulásmérővel folytatott kommunikációról, vagy egy egyszerű LED villogtatásáról egy digitális I/O porton, célszerű a regiszterműveleteket elrejteni, és egy magasabb absztrakciós szinten kezelni az alkalmazás oldaláról. Egyfajta monitor program készítése, és a réteges felépítés nagyon hasznos az alkalmazások írásának megkönnyítéséhez. Továbbá ha változást kell eszközölni akár a hardware összeállításban, akár a software logikában, a másik réteg érintése nélkül megvalósítható. Ebből a megfontolásból saját driver komponenseket készítettem, amik inicializáló függvényt, és néhány a használatot megkönnyítő absztrakciót tartalmaztak.
4.1.1 I/O portok konfigurálása A digitális áramköröknél a legalapvetőbb periféria a digitális Input/Output. A mikrokontrollernél egy olyan láb, ami kimenetként vagy bemenetként funkcionálhat. A digitális logikának megfelelően magas vagy alacsony feszültséget kapcsolhatunk rá, ha bemenetként használjuk, vagy adhatunk ki rajta, ha kimenetként konfiguráljuk. Általában a mikrokontrollerben 8-asával alkotnak egy-egy portot. Portonként egy 8 bites adatregiszter, és egy 8 bites „adat irány” regiszter tartozik hozzájuk. Kimenetként használva az adatregiszterbe írt biteknek megfelelő kimenet jelentkezik az IC lábain. Bemenetként pedig az adatregisztert kiolvasva a lábakon „mért” aktuális jelszintnek megfelelő bináris értéket 10. ábra - ATMega32 lábkiosztás kapunk. Az inicializálásnál mindössze annyi a dolgunk, hogy az adott porthoz tartozó DDR (Data Direction Register) bitjeit megfelelően állítsuk be. Ha egy lábhoz tartozó DDR bit 1-es, a láb kimenetként funkcionál. Alap esetben a DDR bitjei 0-kat tartalmaznak, azaz bemenetként funkcionálnak. Biztonsági oka van, amíg ugyanis nem történik meg az helyes inicializálás, problémát okozna, ha a kimeneten megjelenne valamilyen jel. Nem kívánt működést válthat ki a perifériákból, zárlat is keletkezhet, ha az adott lábra a csatlakozó eszköz is kiad valamit. Az ábrán látható, hogy az IC 1. lába a B port 0-ik bitje (PB0). A 2. láb a PB1, és így tovább. Látható az ábrán – a teljesség igénye nélkül – hogy egy IC lábnak többféle szerepe lehet. Ezért fontos meghatározni, melyik portot mire kívánjuk használni. A B port adatregisztere a PORTB. Az egyes lábakra PINB0-PINB7 vagy PORTB0-PORTB7 ként hivatkozhatunk. Ez DDRA = 0b00000000; //ADC input utóbbiak azonban csak offsetek, tehát a DDRB = 0b00001000; //buzzer Output PORTB regisztercímmel együtt DDRC = 0b00011111; //LED0,1,2,3,4 használhatóak. A B porthoz tartozó DDR a DDRD = 0b11100000; //PD2-INT0;PD3INT1 DDRB. Ennek analógiájára működik az összes többi (A,C,D) port is. 14
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.1.2 Megszakítások Az AVR környezetben dolgozva többféle megszakítással találkozhatunk. Hardware-es külső és belső megszakítások léteznek. Van egy speciális interrupt, ami ugyan külső hardware-es interrupt, mégis speciális szerepe van. Ez a RESET, ami a $000 címre (azaz a programmemória legelső utasítására) mutató pointer. Az időzítő megszakítása belső, harwarees megszakításnak tekinthető. Több periféria használata esetén hasznosak ezek a megszakítások. Külső megszakítást, például nyomógomb megnyomására is lehet konfigurálni. Az ATMega32-ben 21 megszakítás található. Az adatlap 18. táblázatában találhatóak ezek elnevezései. A programmemória fix címeire vannak ezek bejegyezve, ahonnan ugró utasítással a saját lekezelő kódrészünkre futhat a vezérlés menete. A fejlesztőkörnyezet ezen címek használatához is nyújt segítséget szimbolikus nevek (kvázi függvénypointerek vagy vektoro) használatának lehetőségével. Mindehhez persze az
header inkludálása szükséges. ISR(INT0_vect){ // code to handle external interrupt 0
}
Az avr-libc függvénykönyvtár az interrupt.h headerben a globális interruptok engedélyezésére és az inverz műveletre, a globális megszakítás letiltásra is célfüggvényeket definiált sei(); cli(); de magában a CPU instrukciókészletében is megtalálható a SEI, CLI instrukció. Itt érdemes megemlíteni, hogy az avr-libc lehetőséget nyújt a C forráskódba közvetlen assembly betétek beágyazására. Ezen kódok helyességét, és optimalizálását viszont a fordító már nem minden esetben tudja garantálni. Az assembly betétek elhelyezésének módja az, hogy az asm(); függvény paramétereként adjuk meg az instrukciókat. A feladat megoldása során erre a lehetőségre nem volt szükségem.
4.1.3 SPI driver – „on-board” kommunikáció „On-board” kommunikáció alatt áramkörön belüli kommunikációt értünk. A digitális áramkörök elterjedése szükségessé tette ilyen kommunikációs protokollok készítését. Gyakran több különböző digitális áramkör is található egy-egy nyomtatott áramkörben, és manapság már digitális jelek formájában kommunikálnak az áramkörön belül is szemben a régebbi analóg technológiákkal. Az SPI (Serial Peripherial Interface Bus) a Motorola által fejlesztett szabványos soros adatkapcsolati protokoll. Full-duplex, két adatvonallal működik. Master-Slave alá-fölérendeltség van az eszközök között. Alapvetően „on-board” kommunikációra tervezték, azaz chipek áramkörön belüli összekötésére.
15
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Szokás 4 vezetékes adatbusznak is nevezni. Az összeköttetések elnevezése: MISO MOSI SCLK SS
– Master Input Slave Output (a Slave kimenete) – Master Output Slave Input (a Master kimenete). – Serial Clock (A Master kimenete) – Slave select (chip select) (A Master kimenete, null-aktív)
A kommunikáció közös órajellel működik, amit a Master eszköz szolgáltat. A negyedik vezeték a ”chip select” (vagy slave select) egy null-aktív vonal, ami több slave eszköz esetén annak a slave-nek a bemenetén van logikai nullán, amelyikkel a master kommunikálni szeretne. Többféle topológia építése lehetséges, ám ebben a projektben mindössze egy slave eszközzel való kommunikációra van szükség, így ezek bemutatásával nem foglalkozik a dolgozat. A kommunikáció úgy zajlik, hogy a kiválasztott slave SS lábára alacsony logikai értéket adunk, és az SCLK órajelre a két eszköz adatátviteli regisztereinek (a mikrovezérlőben SPDR - SPI Data Register) értéke kicserélődik, „körbejár”. Full-duplex 11. ábra - SPI körforgás adatátvitel történik, ugyanis 8 órajel alatt mindkét 8 bites regiszter tartalma kicserélődik, tehát 16 bit adat cserélhet gazdát. Más kérdés, hogy ez nem minden esetben használható ki teljes egészében. Más alternatívák is vannak az „on-board” kommunikációra, legjelentősebb az I2C. Kevesebb vezetékkel lenne megoldható a kommunikáció, viszont az SPI esetében nem kötött a 8 bites szavak használata, szabadon bővíthető. Nagyobb adatáteresztő képessége van, és hardware-esen is egyszerűbben kivitelezhető. A mikrokontroller rendelkezik SPI interfésszel, ami azt jelenti, hogy a kommunikáció időzítési és regiszterléptető feladatait önállóan ellátja, ezáltal egy magasabb absztrakciós szintet biztosítva a programozónak. A mérőegységben a digitális gyorsulásmérővel folytatott kommunikáció zajlik SPI protokollal. Az inicializálást a következő blokk végzi. Először a digitális I/O portok irányítását kell megadni. Az SCLK, MOSI, SS kimenet, a MISO bemenet lesz. A mikrokontroller a master eszköz, a gyorsulásmérő a slave. Az SPI kommunikációhoz az órajel 128-as előosztással keletkezik. Mivel elég magas rendszer órajellel dolgozik a CPU, a legnagyobb előosztást választottam. A mintavételezés az órajel felfutó élére történik. void initSPI_Master(void){ // Set MOSI and SCK, SS, CS output, all others input
DDR_SPI = (1<
SPCR = (1<<SPE)|(1<<MSTR)|(1<
16
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Az adatátvitel a master eszközzel úgy váltható ki, hogy az SS lábat lehúzza a földre, és elkezdi küldeni a saját adat regiszterének tartalmát. Ennek hatására a slave eszköz is elkezdi bitről-bitre, órajelről-órajelre elküldeni a kimeneti regiszter tartalmát. Az SPI_MasterTransmit() parancs a paraméterben kapott bájtot küldi el a slave eszköznek, majd az átvitelt követően az SPDR regiszterből a slave eszköz által küldött bájt olvasható ki, amely a függvény visszatérési értéke. A mikrovezérlő SPI modulja pár sorban kezelhetővé teszi az SPI interfészt. A regiszterbe beírt biteket a beállított SPI órajelnek megfelelő sebességgel el is küldi. Arról azonban a programozónak kell gondoskodnia, hogy a slave eszköz SS lába földre legyen lehúzva. Ezt a szolgáltatást azért nem vették bele az SPI modul működésébe, mert nem lehet tudni mennyi slave eszköz közül választ az áramkör kommunikációs partnert. Az SPI modul SS lába tehát minden esetben bemenet, de csak akkor használt, amikor a mikrovezérlő slave szerepkörben van. char SPI_MasterTransmit(char cData){ // Start transmission
SPDR = cData; // Wait for complete
while(!(SPSR & (1<<SPIF))){} return SPDR; }
A LIS3LV02DQ gyorsulásmérővel való kommunikáció során az elküldött bájtok a gyorsulásmérőnek szóló parancsok. A parancs lehet a beíró vagy kiolvasó parancs. A parancs első bitje (MSB) dönti el, hogy read vagy write utasításról van-e szó. A maradék 7 bit pedig az érintett regiszter címe. Ha tehát a gyorsulásmérő egy regiszterének értékét módosítani kívánjuk, először elküldjük a parancsot a regiszter címével, majd a regiszterbe beírandó bájtot. A kiolvasás forgatókönyve is hasonló, mégpedig elküldjük a read parancsot a regiszter címével, és a következő alkalommal 0-t vagy újabb parancsot küldhetünk a gyorsulásmérőnek. Az SPI-n keresztül történő regiszterírást, olvasást az alábbi két függvényen végzi: void write_register(char register_name, char data){ register_name &= 127; // clear bit 7 to indicate we're doing a write PORTC &= ~(1<
17
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.1.4 U(S)ART driver – „off-board” kommunikáció Az adatok mérőegységtől való eljuttatását praktikusan egy olyan protokollra építettem, ami univerzálisan használható. A Universal Synchronous and Assynchronous serial Receiver and Transmitter, USART egy nagyon rugalmasan használható kommunikációs modul, ami könnyen kezelhetővé teszi a soros kommunikációt. Az ATMega32-ben lévő USART modul lehetővé tesz 5,6,7,8,9 adatbites, 1 vagy 2 stop bites, szinkron vagy aszinkron kommunikációt. Három megszakítást képes generálni a modul, úgy mint TX Complete – átvitel lezajlott, RX Complete – fogadás megtörtént, és TX adat regiszter üres megszakítást. Az adatátvitelhez egy órajel generátor a rendszer órajelből képes előosztással a kívánt jelzési sebességnek (baud rate) megfelelő órajelet előállítani. Az UBBR 16 bites regiszterpár értékét a következő képlet alkalmazásával kaphatjuk meg: UBBR =
F_CPU BAUD_RATE * 16
-1
Az RS-232 protokollnak a működési elvét teljes mértékben lefedi ez a modul. Van azonban egy szignifikáns eltérés az U(S)ART és az RS-232 közt. Mégpedig a jelszintek. A mikrokontrolleres környezetben TTL jelszintekkel dolgozunk, ami eltér az RS-232 jelszintektől: TTL 0V – 0,8V 2,4V – 5V
alacsony magas
„0” „1”
RS-232 3V – 15V -15V – -3V
Ezt az eltérést egy külső alkatrésszel kezelni kell. A MAXIM integrált áramköröket gyártó vállalat MAX232 nevű IC-je alkalmas erre a feladatra. Ahhoz hogy hagyományos RS232 csatlakozóval egy PC-re csatlakozzunk, elengedhetetlen ez az áramkör. Ahhoz azonban, hogy az USB vagy Bluetooth modult kvázi soros porton kezeljük, nincs szükség erre a jelszint illesztésre, azokhoz ugyanis már nem az RS-232 protokollal csatlakozik a mikrovezérlő, hanem az UART-tal. Erre az IC-re tehát csak addig van szükség, amíg a hagyományos soros portot el nem hagyjuk. Szoftveres változtatást azonban nem igényel a „médiaváltás”. Soros porton történő kommunikációra építkezve több médián keresztül terveztük az információ, és a parancsok célba juttatását. Azért praktikus, mert elegendő a szoftver komponensekben a soros kommunikációra építeni a kommunikációs modult, és az eszközkezelők feladata lesz a soros port kezelése/emulálása. A kommunikációra a tesztelési fázisban egy egyszerűsített keretrendszerben állapodtunk meg a projekten dolgozó kollégákkal. A protokoll továbbfejlesztése sok újítással szolgál majd, ám ez a projekt folytatásaként kerül részletes kidolgozásra, és implementálásra. A hibakeresés megkönnyítése, és az gyors átláthatóság érdekében fix hosszúságú, kódolatlan keretek formájában történik az adatátvitel. Vezetékes – vagy virtuálisan vezetékes – soros protokollról lévén szó, a keretek sorszámozása szükségtelen. Szinkronizálni viszont kell, illetve típusmező került még a keret fejrészébe, hogy a különböző mérésekhez tartozó adatokat, valamint a jelzéseket és utasításokat meg lehessen különböztetni. Összesen 6 bájt egy keret. 18
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Az első bájt a szinkron bájt, ezt praktikusan 0-nak választottam. A legritkábban előforduló adatbájt a 0, és konvencionálisan 0-s típus nem létezik. Így legrosszabb esetben a második keret érkezésekor helyre áll a kommunikáció. A nullás bájt fogadása után következő 5 bájtot tekinti egy keretnek a rendszer, a típus mező alapján pedig a tartalmát feldolgozza. A keretek felépítését az alábbi ábra mutatja be.
12. ábra - Tremométer keretstruktúra
A keretek típus mezője egy bájt, a szinkron bájtot kivéve 255 különböző típusú keretet lehet definiálni. A következő táblázat foglalja össze a különböző kerettípusok jelentését, értékét és tartalmát. Tremométer kerettípus táblázat (kommunikáció iránya szerint csoportosítva) Csoport Jelentés C konstans neve Érték Adat bájtok tartalma
PC3→µC4 utasítások
µC → PC nyugták
µC → PC adatok
3 4
cRT induljon sRT induljon Pletizm. ind. Tremor ind. cRT állj sRT állj Plet. állj Tremor állj PC oldali hiba cRT elindult sRT elindult Plet. elindult Trem. elindult Magas sípszó elh. Mély sípszó elh. Gombnyomás Hibás gombnyomás Időtúllépés Pletizmográfia adat X tremor adat Y tremor adat Z tremor adat µC oldali hiba
START_CRT START_SRT START_PLET START_TREM STOP_CRT STOP_SRT STOP_PLET STOP_TREM PC_ERROR ACK_START_CRT ACK_START_SRT ACK_START_PLET ACK_START_TREM BEEP_H BEEP_L BTN BTN_ERR TIMEOUT PLET TREM_X TREM_Y TREM_Z UC_ERROR
231 232 241 251 211 212 214 215 1 131 132 141 151 31 32 33 34 35 41 51 52 53 2
üres
hibakód
üres
üres reakcióidő [ms] üres érték [0,216] (fs=250Hz) érték [előjeles 16 bites] (fs=250Hz) érték [előjeles 16 bites] (fs=250Hz) érték [előjeles 16 bites] (fs=250Hz) hibakód
PC – vagy mobil adatgyűjtő alkalmazás uC – mikro controller 19
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
A kommunikáció kétirányú, ahogyan a táblázatból is látszik, a számítógép – vagy mobiltelefon – felől is érkezhetnek utasítások. Az UART modul lehetőséget biztosít arra, hogy megszakításként kezeljük le, ha a kommunikációs csatornán adat érkezik. Az UDR (UART Data regiszter) kívülről történő feltöltése esetén a megszakítást lekezelő blokk megvizsgálja a beérkezett bájtot, és egy switch vezérlési szerkezettel leválogatva a megfelelő műveleteket elvégzi. Mivel a kommunikáció erősen aszimmetrikus, azaz elenyésző a bejövő adat a küldötthöz képest, a parancsok keretszervezés nélkül érkeznek a teszt verzióban.
4.1.5 Bluetooth modul driver A vezetéknélküli kommunikáció igénye úgy a legegyszerűbben kielégíthető, ha a meglévő soros kommunikációt egy Bluetooth csatornán át továbbítjuk. Gyakran alkalmazott megoldás ez, éppen ezért a számítógépes Bluetooth driverek túlnyomó többsége elsőkézből támogatja soros port emulálását Bluetooth adatátviteli közegen. A Bluetooth egy rádiófrekvenciás adatátviteli protokoll. 2,4 GHz körüli átviteli frekvenciákat használ, kimondottan vezetéknélküli PAN (Personal Area Network) –ok kialakítására találták ki. A Bluetooth használata a firmware szempontjából nem nevezhető „off-board”, azaz áramkörön kívüli kommunikációnak, hiszen egy előre gyártott Bluetooth modullal kell az áramkörben kommunikálni, inicializálni és küldeni/fogadni az adatokat. A Bluetooth driver, ami az adatkapcsolati protokollt implementálja, a Bluetooth modulban van implementálva. A mikrovezérlő oldaláról mindössze konfigurálni kell az eszközt, valamint soros protokollal elküldeni és fogadni az adatokat. A kiválasztott Bluetooth modul az UART kommunikációs vonalra csatlakozik, így a firmware szempontjából teljesen transzparens, hogy az adatokat Bluetoothon keresztül, vagy valódi soros porton, esetleg USB-n keresztül küldi/kapja. Más megközelítésből viszont tudnia kell róla, hiszen a modult konfigurálni, illetve ki/bekapcsolni is szükséges. A BTM-112 Bluetooth modul működhet parancs módban, és normál üzemmódban. Azt az üzemmódot, amikor nincs hozzá párosítva a vezetéknélküli oldalon másik Bluetooth eszköz, parancs módnak nevezzük. Vannak olyan Bluetooth eszközök is, amelyeket mind az áramköri oldalról, mind a vezetéknélküli oldalról lehet konfigurálni. Ez alapján megkülönböztethetünk lokális és távoli parancs módot. Parancs üzemmódban a Motorola által fejlesztett AT parancsok segítségével lehet konfigurálni, illetve szolgálati információkat lekérdezni. A konfigurálás során a Bluetooth eszközöknél megszokott beállításokat lehet elvégezni, mint a biztonsági kód beállítása, az egyidőben engedélyezett kapcsolatok száma (legfeljebb 7 a Bluetooth szabványnak megfelelően) továbbá megadható az eszköz neve, és átkonfigurálható a fizikai azonosító száma is. A BTM-112 kifejezetten egy szolgáltatást nyújt, soros port adapterként használható. Vezetéknélküli adatkapcsolat lévén lehallgatható, és az adatok titkosításáról gondoskodni kell, ám ez a tesztelési folyamatokat megnehezítené, így még nincsenek az ide tartozó kiegészítések implementálva. Szintén a közvetítő közeg miatt az elvesző adatok okozta hibák kezelésére is szükség lesz. Például bizonyos mennyiségű keret összefogásával ellenőrző összegek továbbításával.
20
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.1.6 ADC driver Az ATMega32-ben 10 bites kétoldali közelítéses analóg digitális átalakító (ADC) van. Referenciának legfeljebb a µC tápfeszültségét lehet beállítani. A föld és a referenciafeszültség különbsége adja a teljes tartományt (full scale) amelyet a konverter 210 részre bont fel. Belső referencia feszültség kiválasztására is van lehetőség, ami 2,56V. A 10 bites felbontás, és a ±2LSB5 abszolút hiba megfelelő konverziós sebességgel párosul, így maximálisan kielégíti az analóg áramkörrel történő kommunikációval szemben támasztott igényeket. Az AD konverter 15kSPS6 mintavételezési sebességre képes. Ez persze függ a rendszer órajelétől is. 50kHz és 200kHz közötti órajelre van szüksége a modulnak a helyes működéshez. Az ADC órajelének generálásánál tehát úgy kell megválasztani az előosztást, hogy ebbe az intervallumba kerüljön. Egyetlen analóg digitális átalakító van az áramkörben, de multiplexálással az A port minden lábára eső feszültséget meg lehet mérni. A konverzió elkészültére megszakítás jegyezhető be. Az AD konvertert inicializáló függvény két fontos lépésből áll. Az egyik a multiplexer beállítása. Tekintve hogy egyetlen analóg bemenetünk van, a multiplexert elegendő az inicializáláskor a megfelelő lábra ráállítani, és a későbbiekben nem kell a processzoridőt a MUX regiszterének újbóli beállítására használni. Az ADMUX első 3 bitje (MUX0 - MUX2) a portot határozza meg, a következő kettő (MUX3, MUX4) különböző beállításai pedig differenciál módú mérés konfigurálására vannak fenntartva. A hatodik ADLAR bit a konverzió eredményének formátumát határozza meg, 8 bites regisztereket használva a 10 bites eredmény két regiszterbe kerül. Ha ez a bit 1-es, az adatok balra rendezettek, alap esetben azonban jobbra rendezettek lesznek. Az ADMUX hatodik és hetedik bitjével a referencia feszültséget lehet beállítani. Esetünkben ez az IC analóg áramköreinek tápfeszültsége (AVCC) lesz. Az eredmény jobbra rendezett (ADLAR = 0) és a bemenet az ADC0 (ami a PA0, azaz a 40. láb). Fontos, hogy amikor az I/O portokat inicializáljuk, ezt a lábat bemenetként inicializáljuk. Ezek ismeretében egy egyszerű értékadási műveletet képzünk a beállítandó bitsorozatból: ADMUX = 0b01000000 (= 0x40). A másik az ADCSRA (azaz az ADC Control and Status Register A) beállítása. Az ADC áramkör is (mint a legtöbb kiegészítő áramkör) ki/bekapcsolható, hogy az olyan alkalmazások esetén, amikor az energiatakarékosság fontos, fölöslegesen ne fogyasszanak a nem használt modulok. Az ADEN (ADC Enable) bit értékével lehet ki/bekapcsolni az áramkört. Az ADSC (ADC Start Conversion) bit 1-re állításával indítható el a konverzió. Egy átlagos konverzió 13 ADC órajel alatt zajlik le. Az ADATE bit az auto triggerelést engedélyezi. Az ADIF a megszakítás flagje, melyet az ADIE (Interrupt Enable) bittel lehet engedélyezni, hogy a konverzió végeztével keletkezzen interrupt. Az ADPS bitek segítségével lehet az előosztást meghatározni, ami segítségével a rendszer órajeléből a konverter órajele keletkezik. Esetünkben ez 64-es előosztást jelent, ami a 11,0592 MHz-es kristály 172,8 kHz, 5 6
LSB – Least Significant Bit – legkisebb helyiértékű bit a bitsorozatban kSPS – Kilo Sample per Second – mintavételezési frekvencia 21
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
azaz az ADC órajel maximális értékéhez legközelebb eső érték. Az előzőekben részletezett inicializáló blokk a következőképpen néz ki: void initADC(){ ADMUX = 0x40;
//select adc input 0 /* 0x40=0b01000000 REFS: 01 <- AREF=AVCC with external capacitor on AREF ADLAR, MUCX=0 */
ADCSRA = 0x86; /*0x86= 1 0 0 0 0 1 1 0 |ADEN | ADSC|ADATE|ADIF|ADIE|ADPS2,1,0|
*/
}
Az ADC eredmények kiolvasása is részletesebb leírást érdemel, több trükk alkalmazása is indokolt. Két kiolvasó függvényt készítettem a driverhez. Az alábbi readADC()függvény 4 mintavétel átlagát adja vissza. Előfordulhat, hogy egy-egy mintavétel eredményét külső zavarok eltorzítják, de hogy az átlagolást alkalmazva a végeredményt ez jóval kevésbé befolyásolja. A while vezérlési szerkezetben található feltétel is magyarázatra szorulhat. A cél az, hogy a konverzió befejeztéig várjunk. Ezt az eseményt az ADIF flag 1-be billenése jelzi. A ciklus addig tesztel, amíg az ADCSRA-ból 0x10 maszkkal kiemelt értéke 1 nem lesz. Ekkor az ADCL és ADCH regiszterekből kiolvasható a mért érték. A kiolvasott bájtok összevonásához a magas helyiértéket reprezentáló ADCH bájtot 256-tal meg kell szorozni, amivel ekvivalens művelet, ám jóval egyszerűbb a balra történő 8 bites eltolás. Az átlagoláshoz egy akkumulátor változóba gyűjtve a 4. iterációt követően az osztást a gyorsabb bit-eltolással helyettesítve elő is áll a visszatérési érték. int readADC(){ char i; int ADC_temp, ADCH_temp; int ADC_var = 0; ADC_ENABLE; for(i=0;i<4;i++){ // do the ADC conversion 4 times for better accuracy ADC_START_CONVERSION; while(!(ADCSRA & 0x10)){} // wait for conversion done, ADIF flag set ADC_temp = ADCL; // read out ADCL register ADCH_temp = ADCH; // read out ADCH register ADC_temp +=(ADCH_temp << 8); ADC_var += ADC_temp; // accumulate result (4 samples) //for later averaging
} ADC_var = ADC_var>>2;
// average the 4 samples
ADC_DISABLE; return ADC_var; }
A következő readADCfast() függvény a nevéből adódóan rövidebb idő alatt fut le, azonban kevésbé pontos, mivel az átlagolást nem tartalmazza. Akkor van rá szükség, ha a kívánt mintavételezési frekvencia magas, és nincs idő az átlagolásos módszer alkalmazására. 22
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Ez azonban a pontosság rovására történhet meg. Az átlagolás nélkül a függvény működése megegyezik az előzőével, de vannak még makró függvények, amik magyarázatra szorulnak. Az angol elnevezések beszédesek, az ADC_ENABLE, ADC_DISABLE ahogy az inicializálásnál is láthattuk, a konverter áramköreinek ki/bekapcsolására szolgálnak, és az ADEN bit értékét manipulálják. Az ADC_START_CONVERSION az ADSC bitet billenti be 1 állapotba. int readADCfast(){ int ADCH_temp,ADCL_temp; int ADC_var = 0; ADC_ENABLE; ADC_START_CONVERSION; while(!(ADCSRA & 0x10)) {}
// wait for conversion done, ADIF flag set
ADCL_temp=ADCL; ADCH_temp=ADCH; ADC_var +=(ADCH_temp << 8); ADC_var += ADCL_temp; // accumulate result (4 samples) ADC_DISABLE; return ADC_var; }
4.1.7 PWM Beep driver A reakcióidő méréshez használt sípszó generálására alkalmas a pulzusszélesség modulátor (Pulse Width Modulation). Számos felhasználási területe van a pulzusszélesség modulációnak. Az egyik, hogy hanghullámot lehet vele előállítani. Ami fontos tulajdonsága még a modulnak, hogy megfelelő inicializálás után egyetlen bit értékének manipulálásával ki és bekapcsolható. A működése alatt pedig nem igényel processzor időt ez a modul sem. Lehetne sípszót generálni négyszögjelből úgy is, hogy egy I/O kimenetet a kívánt frekvenciával ki és bekapcsolgatunk, de ezen megoldás esetén alig maradna szabad processzoridő a többi művelet végrehajtására. Mivel ez is egyfajta számláló, az AVR-ben a Timer/Counter modulok programozhatóak pulzusszélesség moduláció megvalósítására. A Timer/Counter0 8 bites időzítő számláló, aminek az inicializálását az alábbi lépések végzik: // Timer 0 (Oc0) Buzzer :) TCCR0 = (0<<WGM01)|(1<<WGM00); // set up phase corrrect PWM TCCR0 |= (1<
Hasonló elnevezésekkel találkozhatunk, mint a Timer1 inicializálásakor. A Timer Counter0 Control Register (TCCR0)–ban azonban fáziskorrekt PWM operációt kell beállítani. A megválasztható frekvenciák ez esetben némiképp limitáltak, mert a rendszer órajel leosztásával csak néhány diszkrét érték választható ki, de a mély és magas hangok megkülönböztetésére ez éppen elegendő. Az OCR (Output Compare Register) tartalma ezúttal a kitöltési tényezőt fogja kifejezni. A frekvenciát 3 CS0 (Clock Select) bit kombinációjából lehet beállítani. 23
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Fáziskorrekt PWM (PC PWM) kimeneti frekvenciáját a következő képlet alapján lehet kiszámítani. Az F_CPU a rendszer órajel, N az előosztás.
ƒPCPWM =
F_CPU N * 510
A magas hangjelzéshez 8-as előosztást választottam, így a hang frekvenciája 2710 Hz. Az alacsony 64-es osztás után 323 Hz. A jelzés elindítására szolgál a startBeep(int i) függvény. Az alapbeállítással magas sípszót generál a Timer0, ez ugyanis jóval gyakoribb, mint a mély zavaró sípszó. Ha mégis mély sípszót kell generálni, a TCCR0 regiszterben az előosztást át kell állítani. static void startBeep(int i){ beep = 1; //set flag if(i==HIGH){ //high PORTC |= (1<
A hangjelzés mellett egy világító dióda is bekapcsol, valamint készítettem tesztelési célra egy „válaszoló áramkört” amit egy külön lábra kötöttem. A sípszó elhangzásakor a tesztelő áramkör is kap egy jelzést, és a benne programozott válaszidő elteltével a gombnyomás eseményét utánozza. Azért készítettem, hogy tesztelhessem az időmérés pontosságát. A tesztelő- válaszoló áramkör is egy mikrokontroller. Az ATTiny45 egy kis 8 lábú IC szintén az AVR családból. Pontos órát készítettem ebbe az eszközbe is, és a tesztelő panelre szereltem. Az eredmények alapján a rendszer relatív hibája nem haladta meg a 3,25%ot, ami két AVR-es óra hibájának összege, tehát a valós hiba biztosan kisebb. A PWM sípszó leállításakor a kontrol regiszter megfelelő bitjét 0-ra kell állítani, valamint az előosztást a default értékre állítani. Nem érdemes leellenőrizni, hogy át volt-e állítva, mert több időt vesz igénybe, mint az esetleges „hatástalan” operáció. A jelzőfényekről és a statikus változóként tárolt flagről is gondoskodni kell. static void stopBeep(){ beep = 0; // clear flag PORTC = 0b0000000; TCCR0 &= ~(1<
// LED, test sign off // stop PWM // reset prescaler for high
24
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.2 A firmware fő programrésze (a main függvény) A main függvény a C programok legfontosabb függvénye. Amikor egy C-ben írt program elkezd futni, ennek a függvénynek az első sorával indul. A mérőegység main függvényének elején történik az eszköz inicializálása, a perifériák felkonfigurálása és a kezdő paraméterek beállítása. A mikrokontrollerekben futó kódban mindig kell, hogy szerepeljen egy végtelen ciklus is. Ha nincs végtelen ciklus, és a programfutás menete eléri a main függvényt lezáró kapcsos zárójelet, a program futása megáll. Hardware-es resettel lehet újraindítani a mikrovezérlőt, a legelső instrukciótól. A legtöbb (az általunk használt mikrovezérlőben is) vezérlőbe építenek egy ún. Watchdog Timer-t, vagy más néven COP-t – Computer Operate Properly timert ami hardware-es vagy software-es módon váltja ki (triggereli) a rendszer újraindításokat (reseteket). Azaz ha a főprogram lefagy, nem válaszol, vagy egyszerűen elfogytak a végrehajtandó utasítások (a main függvény végére értünk), elindul egy számláló, és a megadott idő eltelte után újraindítja a folyamatokat. Alapvetően két programozási technikát különböztethetünk meg. Egy procedurális megoldást, ami úgy működik, hogy az inicializáló programrészek után egy végtelen ciklusban hajtódnak végre a program utasításai. A végtelen ciklus mindig tesztel, leellenőrzi a bemeneteket, beállítja a megfelelő módon a kimeneteket. Ez egyszerű programok esetében működőképes megoldás lehet, ám komplexebb feladatok esetében már túl sok tesztelést, elágazást tartalmaz a program. További hátránya, hogy pontos időzítést nem lehet megvalósítani ezekben a programokban, mivel az egyes instrukciók időigényét még meg lehet becsülni, de azt hogy az esetleges bemenetek mikor milyen állapotban lesznek, azt már nem. Abban az esetben pedig, amikor a bemenetek állapota befolyásolja a program futásának menetét – mondjuk egy gombnyomásra elkezd villogni egy lámpa – lehetetlenné válik a műveleti idő kiszámítása. Egy másik megközelítésben, ha csak végtelen tesztelő ciklusokat használunk, a várt események nem azonnal váltják ki hatásukat a program futására, csak mikor a megfelelő elágazásra kerül a sor. Az ilyen események lekezelésére találták ki a megszakításokat, interruptokat. A másik megoldás éppen 13. ábra - main függvény a megszakításokra épül. Azok a programok, amik külső interakciót, méréseket tartalmaznak, ezzel a másik technológiával célszerű megtervezni. Ez esetben a működéshez szükséges utasítások zöme a megszakításokat lekezelő blokkokban van, és legtöbbször üres végtelen ciklus gondoskodik arról, hogy a program futása ne érjen véget. A lehetőség adott mindkét programozási technika 25
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
egyidejű alkalmazására, sőt sok esetben célravezető lehet. Mivel a mérőműszerbe tervezett firmware egyrészt felhasználói interakciókra épül, másrészt az adatgyűjtő szoftvertől kap parancsokat, ez utóbbi technológia alkalmazása látszott célravezetőnek. További érv a megszakításos vezérlés mellett, hogy pontos időmérésre, és mintavételezési frekvenciára volt szükség. A gyakorlat során fejlesztett program alapvetően megszakításokon alapul, így egy üres végtelen ciklus képezi a magot. A valós funkciók lekezelése minden esetben a megszakításokat lekezelő rutinokban találhatóak. Az oldalt látható folyamatábra a main függvény folyamatábrája nagyvonalakban. A függvény elején az inicializáló blokkoknak egyszer elegendő lefutniuk. Az inicializálás lépéseit az átláthatóság kedvéért külön függvényekben definiáltam, így a main függvény mindössze néhány függvényhívást, és egy végtelenciklust tartalmaz. A perifériák inicializálása a következő fontos lépéseket tartalmazza: • változók, tömbök inicialiálása int main(void){ int i; • I/O portok konfigurálása for(i=0;i<10;i++){ • UART inicializálás heart[i]=0; } o órajel beállítása //generateSine(); // for test mode o adó és vevőáramkörök engedélyezése random_time=generateRandom(); initPorts();// data direction registers • SPI inicializálás (óra, szerepkör beállítása) initUART(); // clock, • Időzítők beállítása initSPI_Master();// clock, role o Timer0 – csipogó, PWM üzemmód initADC(); // mux initTimer();// timers init and start o Timer1 – milliszekundumos initReady();// system ready signal (blink) megszakítások sei(); // let's run • ADC beállítása while(1){ } • Megszakítások engedélyezése
4.3 Időzítő
}
//never reached line ☺ // end main
A firmware működése szempontjából a legfontosabb modul a Timer1. Ez a számláló, időzítő modul generál milliszekundumonként egy megszakítást. Ezen megszakítást lekezelő blokkban történik a mérési funkciók végrehajtása. Az időzítő számláló modulok működéséről érdemes pár szóban megemlékezni. Az alap koncepció a számlálók esetében az, hogy egy bejövő jelsorozat (például órajel) meghatározott szakaszaira (felfutó/ lefutó élre) inkrementálja egy regiszter tartalmát. Innentől gyakorlatilag testre szabható, az igényeinkhez igazítható a mikrokontrollerben lévő időzítő működése. Meghatározhatjuk, hogy belső vagy külső órajelet kapjon, esetleg más jelsorozatot - például egy szállítószalagon az érzékelő előtt elhaladó termékek által generált jelzéseit - hogy felfutó vagy lefutó élre léptessen, illetve úgynevezett előosztás is beállítható. Esetünkben a mikrovezérlő órajelét használjuk 1024-es előosztással. Az előosztás is egy számláló regiszter gyakorlatilag, viszont teljesen hardwarees működésű, és nem vesz el egyetlen órajelnyi processzoridőt sem a CPU-tól. Az Atmega32ben 3 időzítő található. (Timer/Counter0, Timer/Counter1, Timer/Counter2) Mindhárom időzítő némiképp eltér egymástól, így más-más jellegű feladatokra lehet használni. 26
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.3.1 Timer1 inicializálása Az ATMega32 Timer/Counter1 áramköre egy 16 bites számláló időzítő. A számláló alkalmas pontos időzítési feladatok megvalósítására, hanghullám generálására. Noha a számláló 16 bites, a mikrovezérlő és az adat buszok is 8 bitesek. A 16 bites regiszterekhez tartozik egy ideiglenes 8 bites regiszter a magas helyiértékű 8 bit tárolására, hogy a két read művelet alatt a kiolvasott adatot ne változtathassa meg a számláló esetleges továbblépése. Négy különböző interrupt forrása lehet. A számláló túlcsordulására jegyezhető be megszakítás, valamint az aktuális értéke összehasonlítható két tetszőlegesen beállítható úgynevezett OCR – Output Compare Register értékével, ami egyezés esetén szintén interrupt forrása lehet. Egy külső megszakítást is tud kezelni a számláló az Input Capture Pin1 bemenetről. A következőkben az inicializálásnak lépéseit mutatom be. Tipikusan olyan programsorokról van szó, amelyek mindössze néhány instrukciót tartalmaznak, egyszerű értékadó utasítások, de a helyes bitsorozat megállapítása időigényes. A Timer1 kontrol regisztereit az alábbi két ábra mutatja.
14. ábra - Timer Counter1 Control Register A
15. ábra - Timer Counter1 Control Register B
Azokat a biteket, amelyeket a jelen konfiguráció érint, röviden a következőképpen lehet bemutatni. Az initTimer() az időzítőt inicializáló függvény részlete: void initTimer(){ // […] // Timer 1 Time(ms)
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode TIMSK |= (1 << OCIE1A); // Enable CTC interrupt OCR1A = 10; // Set CTC compare value, TCCR1B |= ((1 << CS12) | (1 << CS10)); // Start timer }
27
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
A regiszter alapállapotában minden bit értéke 0. A regiszterek értékeinek megadására számos módszer létezik. Megadhatjuk közvetlenül binárisan, vagy más számrendszer használatával (hexadecimális, oktális, decimális) egyszerű értékadásként: OCR1A = 10;
A fejlesztőkörnyezet sok előre definiált konstans használatával segíti az átlátható programozást. Vannak konstansok, melyek memóriacímeket helyettesítenek, a fenti kódrészletben ilyen például a TCCR1B, illetve vannak, amelyek bit sorszámot (tehát 0-7 intervallumba eső egész számot helyettesítenek), mint például a WGM12. A másik értékadási módszer a bitműveletekkel történő leírás. Ez alapján a következő sor jelentése az, hogy a TCCR1B által megcímzett regiszterbe (Timer Counter1 Control Register B, 0x2E ) a WGM12 helyi értékre (azaz a 3. bit helyére) egyest írunk. TCCR1B |= (1 << WGM12);
Az időzítő működését tekintve ez a művelet a következőt jelenti. Mivel a TCCR1B regiszter alapértelmezett tartalma 0b00000000, de a 3. (WGM12) bitet 1-be billentettük, a következőt kapjuk: 0b00001000. Az alábbi táblázatrészlet pedig a magyarázat, ez a beállítás a CTC (Clear Timer on Compare match) mód. Gyakorlatias megfogalmazásban a számláló (TCNT1 regiszterpár) értéke addig növekszik, míg az OCR1A regiszterpár értékével egyenlővé nem válik. Ekkor a számlálás újra indul, a TCNT1 regiszterpár nullára inicializálódik.
16. ábra - TCCR regiszter flagjeinek jelentése
A számláló újraindulására megszakítást lehet bejegyezni, amihez a TIMSK (Timer Counter Interrupt Mask Register) megfelelő bitjét (OCIE1A Output Compare A Match Interrupt Enable) kell 1-re állítani, és az inicializáló blokk végén globálisan is engedélyezni kell a megszakításokat. TIMSK |= (1 << OCIE1A);
// Enable CTC interrupt
Az OCR1A regiszterpár értéke az órajeltől függ. Ezzel, és az előosztással állíthatjuk be, milyen időközönként keletkezzen ez a megszakítás. Esetünkben gyors számolással megállapítható, hogy miért pont 10 az OCR1A értéke, és 1024 az előosztás.
28
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Órajel: 11,0592MHz 11059200Hz 1024-es előosztás után: 10800Hz (1/sec) Milliszekundum (1000/s): 10,8 (ütés/ms)
A számolásból látható, hogy nem minden esetben egész szám jön ki. Ilyenkor mérlegelni kell, megengedhető-e a hiba. Esetünkben a mintavételezés időzítésénél eltekinthetünk a hibától, a véletlen időintervallumok generálásakor sem számít, a reakcióidő esetében viszont gondot kell fordítani rá. Egy egyszerű kompenzációval pontosítható az eredmény, kiszámítható ugyanis, hogy esetünkben 55ms-enként 1milliszekundummal kapunk nagyobb értéket a valós reakcióidőnél, így ezt ki kell vonni, mielőtt elküldjük az eredményt. Az alábbi makró gondoskodik erről. #define REAL_RT rt=rt-(int)(rt/55)
// 11059200Hz
Két lépés maradt az időzítő inicializálásából, ám ezeket egy művelettel lehet végrehajtani. Az előosztás beállítása, és a számláló elindítása ugyanazon flagek állításával történik. Ha minden jelzőbit 0, a számláló áll, ha az alábbi előosztások bármelyikét beállítjuk, a számláló el is indul. TCCR1B |= ((1 << CS12) | (1 << CS10));
// Start timer
A TCCR1B regiszter 3 Clock Select Bit-et tartalmaz. Ezek segítségével az alábbi táblázatban összefoglalt üzemmódok állíthatóak.
17. ábra - Clock Select Bitek leírása
Ezen lépés után fut a számlálónk, milliszekundumonként generálja a megszakításokat, ám ezek a megszakítások még el vannak maszkolva. Van ugyanis egy globális interrupt vezérlő flag az MCUCR-ben (Microcontroller Unit Control Regiszter) ahol szintén engedélyezni kell az interruptokat a GIE bit 1-re állításával. Ezt azonban csak az inicializáló blokk legvégén célszerű engedélyezni, nehogy az inicializálás további lépéseit megszakítsa valamilyen esemény.
29
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.3.2 A megszakítást lekezelő programrész A milliszekundumonként keletkező megszakítást a következőkben bemutatott programrészek kezelik le. A megszakítás kiváltása után a számláló azonnal újraindul, így a következő a műveleti időtől függetlenül pontosan 1 ezredmásodperc elteltével jelentkezik. Arra figyelmet kell szentelni, hogy 1ms alatt a legrosszabb esetben is végig fusson a kód, különben a megszakítások összetorlódnak. A 11,0592MHz-es kristállyal 1 milliszekundumra 11059 órajel jut, ebbe kell beleférnie a lekezelő rutinoknak. A megszakítás lekezelése a folyamatábrán látható módon történik úgy, hogy végigfut a vezérlés az alapfunkciókon, és amennyiben be vannak kapcsolva, annál elvégzi a mérést és az adatok továbbítását. Amennyiben nem aktív az adott mérés, továbblép. Az hogy melyik mérés aktív, egy változó értéke jelzi. // Timer interrupt (1000Hz = every ms) ISR(TIMER1_COMPA_vect){ millsec++; […] }
18. ábra - Timer1 megszakítása
A folyamatábrán nincs feltüntetve, de a reakcióidő és a hangjelzések közti véletlen idő számolására egy globális változó értékét egyel kell növelni minden alkalommal. Ennek a változónak több dologban is lesz szerepe, például a másik két vizsgálat ütemezésében. Azokat ugyanis nem szükséges minden milliszekundumban elvégezni, ez 1kHz-es mintavételezésnek felelne meg. 4.3.2.1 Pletizmográfia A Pletizmográfia vizsgálat esetén 250Hz elegendő a mintavételezési frekvenciának. Minden 4. megszakításban kell csak futtatni az analóg digitális átalakító értékét kiolvasó, és elküldő kódrészletet. A kód gyorsabb olvashatósága érdekében több konstanst is bevezettem. Az ON 1, az OFF 0 értéket jelent. A különböző mérésekhez is tartoznak konstansok. Az alábbi if elágazás tehát akkor igaz, ha a Pletizmográfia vizsgálat (P_PLET) be van kapcsolva, és minden 4. ezredmásodpercben teljesül a feltétel: if((process[P_PLET]==ON)&&((millsec%4)==0))
// 250Hz
Azért hogy ne terheljük túlságosan a kommunikációs csatornát, a mért adatokat kettesével küldjük a keretformátumban meghatározott 4 adatbájt két mérés eredményeképpen áll elő. Egy buffer tömbbe olvassuk az ADC által mért értékeket. 30
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Az AVR-ben lévő AD konverter felbontása 10 bit. Az egységes kirajzolás érdekében a szoftver 16bites értékekkel dolgozik, ezért egy egyszerű biteltolással meg van szorozva az eredmény elküldés előtt. tempAdc[plet_temp_pointer]=readADC()<<6;
// *64 to fill full scale (10bit->16bit)
Ha nem fut reakcióidő mérés párhuzamosan ezzel a vizsgálattal, akkor a mért jelsorozatban egy függvény megkeresi azokat a csúcsokat, amik a szívdobbanásokat jelzik. Az aktuális konfigurációnak megfelelően sípszó, vagy egy LED felvillanása jelzi a szívverések gyakoriságát. Reakcióidő mérés közben azért nem használható ez a funkció, mert megzavarná a vizsgálat menetét. 4.3.2.2 Tremor analízis A tremor analízishez a gyorsulásmérő adatait kell elküldeni a feldolgozó szoftvernek. A digitális gyorsulásmérő konfigurációja, és elindítása után a megfelelő című regisztereket kell kiolvasni, és továbbítani a feldolgozó szoftvernek. A konfiguráció elején célszerű tesztelni az eszközt. Sok esetben a szenzor működését is lehet ellenőriztetni úgynevezett „self-test” rutin hívásával, de minden digitális eszköznek van valamilyen azonosítója, amit mindenképp érdemes kiolvasni, és ellenőrizni. Ez esetben a WHO_AM_I regiszter tartalma 0x3A kel hogy legyen. A gyorsulásmérőben lévő AD átalakító 12 bites felbontással dolgozik. Ennek megfelelően két bájtot foglal egy érték. Csak úgy, mint a mikrokontroller AD konvertere esetében, rendelkezni kell a konfiguráció során az eredmény rendezéséről (Data Alignment Selection bit). A kézremegés esetén előjeles 12 bites értéket kapunk. Az adatfeldolgozó szoftverben a megjelenítésnél ennek megfelelően kell kezelni a kapott adatokat, mert egy konverzió a mikrokontrollerben erőforrás pazarló lenne. Azt is meg kell határozni, milyen sebességgel kívánjuk kiolvasni az adatokat. A gyorsulásmérővel történő kommunikáció forgatókönyve a következő. Van egy státusz regiszter a gyorsulásmérő 0x27 címén. A regiszter tartalmát a táblázatban foglaltak magyarázzák. Először ezt a regisztert kell kiolvasni, és ha mindhárom koordináta adatai elérhetőek, akkor lehet őket kiolvasni. ZYXOR Z,Y,X Overrun (túlcsordulás) Egy másik megoldás az lehetne, ha Z Overrun ZOR egyesével ellenőrizzük és olvassuk ki a Y Overrun YOR koordinátákat, de mivel mindhárom X Overrun XOR adatra szükség van, így nem célszerű ZYXDA Z,Y,X Data Available (adat elérhető) részekre bontani a műveletet. Azért van Z Data Available ZDA szükség erre a vizsgálatra, mert Y Data Available YDA különben fals adatokat olvashatnánk ki X Data Available XDA az adatregiszterekből, ha azok feltöltése éppen folyamatban van az olvasáskor. Az adatok továbbítása pedig a kommunikációs csatorna jobb kihasználása érdekében pufferelt, akár csak a pletizmográfia vizsgálat esetében. Mivel ezek a már ismertetett write_register(), read_register() hívások, a forráskód bemutatásától eltekintek. 31
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.3.2.3 Reakcióidő mérés Az időzítő megszakítását lekezelő rutin folytatásaként a reakcióidő mérés egy külön ábrára került, mert több elágazást tartalmaz, és érdemes külön magyarázatot fűzni hozzá. A belépési pont a 18. ábra (Timer1 megszakítása) folytatása, a kilépési pont pedig az egész Timer1 megszakítás-kezelő blokk vége.
19. ábra - Reakcióidő mérés folyamatábrája
A reakcióidő mérés során az eltelt ezredmásodpercekkel más és más műveletet kell végezni. Amikor sípszó előtt vagyunk, az eltelt ezredmásodperceket össze kell hasonlítani a generált véletlen számmal. Amikor a globális számláló értéke eléri a generált véletlen időt, meg kell szólalni a sípszónak. Ha cRT vizsgálat fut, szintén egy véletlen szám határozza meg, hány célinger elhangzása után következik zavaró jel, amire nem kell reagálni. 32
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Ez alapján a sípszó típusát meg kell határozni. A sípszó hossza 150ms körül kell, hogy legyen, ám arra az esetre is fel kell készülni, hogy közben már meg is nyomja a gombot a páciens. A sípszó generálásáról később lesz szó, most elegendő annyit tudni róla, hogy egy önálló modul generálja, amit elindítani és megállítani kell csupán. Tehát ha elindítottuk a sípszógenerátort, el kell kezdeni számolni az eltelt időt, mert ez lesz a valós reakcióig eltelő idő, amit majd továbbítunk. Ha lejárt a sípszó hosszára beállított idő, ki kell kapcsolni. Eztán két eset fordulhat elő. A páciens a maximum válaszidőn belül megnyomja a gombot. Ekkor a reakcióidőt el kell küldeni a feldolgozó egységnek. Új véletlen időt kell generálni, és kezdődik minden elölről. Ha nem nyomja meg a gombot, időtúllépés történik 1,5 másodperc elteltével, amiről szintén üzenetet kell küldeni, és új véletlen időt generálni, újraindítani a számlálót. // Measure RT? if(process[P_RT]==ON){ if(mode==0){ // waiting random time if(millsec>random_time){ mode=1; // count next tick millsec=0; // start count from 0 if(process[P_CRT]==ON){//cRT if(db<1){ startBeep(LOW); sendEmptyPacket(BEEP_L); low=1; // set how much high beep will be before the next low db=(int)rand()%10; }else{ startBeep(HIGH); sendEmptyPacket(BEEP_H); low=0; db--; } }else{ // sRT startBeep(HIGH); sendEmptyPacket(BEEP_H); } // end sRT } // end "reached random time" }else if(mode==1){ // counting reaction time if((millsec>BEEP_LENGTH) && (beep==1 )){ stopBeep(); // end beep } if(millsec>MAX_REACTION_TIME){// time over if(low!=1){// no timeout after low beep sendEmptyPacket(TIMEOUT); } millsec=0; mode=0; random_time=generateRandom(); } // end timeout } // end count rt } // end RT
33
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
4.3.2.4 Gombnyomás interrupt A reakcióidő mérő gombnyomás külső megszakításként van lekezelve. A kezelő blokk folyamatábrája a 20. ábrán látható. A rutin elején meg kell állapítani, volt-e szükség a gombnyomásra. Ha épp számolja a program a reakcióidőt, a gombnyomás helyes, ellenkező esetben nem. Helyes gombnyomás esetén a sípszót ki kell kapcsolni, ha még aktív. Megvizsgálni, hogy valóban szól-e a sípszó, költséges lenne. Helyette mindenképpen beírjuk a 0-t, amivel deaktiváljuk a PWM modult, még ha ez a művelet „hatástalan” is, azaz már 0 van a megfelelő helyen. Attól függően, hogy mély vagy magas sípszóra történt a gombnyomás, a reakcióidőt a változóból kiolvasva, a megfelelő keretben el kell küldeni, majd új véletlenszámot generálni, és a változókat nullára 20. ábra - gombnyomás interrupt visszaállítani. Mielőtt azonban elküldenénk a reakcióidőt, egy kompenzációt kell rajta végezni, mert a milliszekundumos időzítésnek van egy jól meghatározható hibája. Mivel a kristályoszcillátor frekvenciájának osztásánál nem egész érték jött ki, kristálytól függően minden x milliszekundumonként ±1ms kompenzációt kell végrehajtani a reakcióidőn. A megszakítást kezelő kód az INT1_vect címtől kezdődik a programmemóriában. Első lépésként szoftveres prell-mentesítést valósítottam meg. A prell-jelenség a nyomógombok esetén azt jelenti, hogy a benyomás, felengedés valójában nem egyetlen impulzust generál, hanem a rúgó hatására a gomb elengedése után az érintkezők még többször összeérnek. Azért hogy csak egyszer kezeljük le a gombnyomást, az áramkörbe építhetünk RC-tagot, ami megfelelően választott R és C értékek esetén elnyomja a jelenséget, de szoftveresen is biztosíthatjuk, hogy az első gombnyomás után egy meghatározott ideig (esetünkben 10ms-ig) ignorálja a gombnyomásokat. Ez látható az alábbi sorban. A prell változó értékét a Timer1 megszakítását lekezelő blokk inkrementálja. // RT button interrupt ISR(INT1_vect){ if(prell>10){ // ignore prell prell=0; // […]
34
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
Ezt követően tehát megvizsgáljuk, hogy volt-e szükség gombnyomásra. Ha nem, BTN_ERR üzenet formájában értesítjük a feldolgozó szoftvert. Ez esetben biztosan nem aktív a sípszó generátor, ezért ezzel be is fejeztük a megszakítás lekezelését. if(mode==0){ // invalid button press sendEmptyPacket(BTN_ERR); }else{ // valid button press stopBeep(); // stop even if it doesn’t beep rt=millsec; // calculate real [ms] for RT REAL_RT; // see includes.h sendFix16bitPacket(BTN,rt,1); // send results random_time=generateRandom(); //new random time millsec=0; // reset flags, counter mode=0; low=0; } // end valid button press } // end prell }// end INT
A másik ágban a PWM kikapcsolását a kompenzáció követi, amit makró függvénybe tettem azért, hogy a programkódot egy helyen kelljen a kristályoszcillátor cseréje esetén módosítani. A kompenzáció után kapott eredmény elküldése következik, majd új véletlenszámot kell generálni, és néhány változót, flag-et visszaállítani a kezdőértékre.
4.3.3 A directory struktúra, programozás körülményei A programrészek ismertetésének végén pár szóban kiemelném a verziókövetés, a „HelloWorld” kódok gondos archiválása és a jól tagolt program írásának fontosságát. Munkám során tanultam bele, hogyan is kell gondoskodni az említett szempontok betartásáról, ám ezek előnyeit is megismertem. Mikrokontrolleres fejlesztés során gyakran kell regiszter címekkel, speciális és egyedi műveletekkel operálni. Ezek egy-egy eszköz esetén, mint például a gyorsulásmérő használata, az absztrakt függvény megírása után nem kerülnek a programozó szeme elé, és akár néhány héttel később elővéve a kódot kérdések merülhetnek fel. Arról nem is beszélve, ha egy egyszer már használt eszközt újból alkalmaz az ember. Ilyenkor nagyon jól jön, ha van a dokumentumok közt egy egyszerű „HelloWold” alkalmazás, aminek átnézésével a már egyszer megtanult módszerek felidézhetőek. Legtöbbször ugyanis ezeket az egyszerű programrészeket rengeteg kód takarja el egy valós alkalmazásban. A program írásakor arra is figyeltem, hogy ha egy komponens zavarja a másikat a tesztelés során, ez egy-két sor ki kommentezésével kikapcsolható legyen. A main() függvény elején ezért látható annyira tagoltan az inicializálás. A fejlesztés során gyakran kellett megnézni, pontosan hogyan is implementáltam egy-egy segédfüggvényt. Ha egy nagy terjedelmű fájlban kellett volna keresgetni, még ha valamilyen rendszer szerint vannak is benne, jóval időigényesebb lett volna, mint modulonként külön fájlból előszedni. A fejlesztőkörnyezet sok támogatást nyújt ehhez, és az editor ablak mellett fa szerkezetben a projekthez tartozó fájlok tallózhatóak. Érdemes ezeket az apró trükköket alkalmazni bármilyen program írásáról legyen szó.
35
Firmware programozás egészségügyi állapotfelmérő rendszerhez
5
Ferenc István Csaba
Hova tovább…
Az egészségügyi állapotfelmérő műszer fejlesztése folyamatban van, és a dolgozatban ismertetett megoldásokon túl további fejlesztések is tervezés alatt állnak. Ezek közül talán érdemes néhányat meg is említeni. A jelenlegi szoftver összetevők a szoftverfejlesztés korai stádiumában vannak, és a klasszikus szoftverfejlesztési modell számos állomása várja még a fejlesztőket, legyen szó bármelyik eszközre készített szoftverkomponensről. A számítógépes adatfeldolgozó szoftver Java nyelven készül, az objektumorientált programozás, és a platformfüggetlenség előnyeit szem előtt tartva. Ebből adódóan Linux operációs rendszeren is kiválóan fut a program. A kommunikációs csatornák terén azonban vannak platformfüggő kívánalmak. A soros port azonban kiválóan használható a Java program módosítása nélkül. A szoftver komponensek kevés hibakereső, hibajavító megoldással rendelkeznek egyelőre, ami szintén azzal magyarázható, hogy a rendeltetésszerű működés programozásának folyamata zajlik jelenleg is. Természetesen nem feledkeztünk el ezen programrészekről sem, és folyamatos tervezés és implementálás alatt vannak az adatok helyességét ellenőrző modulok is. A mérőműszer miniatürizálása is számos lehetőséget nyújt még a projekt folyatatására. A mostani eszköz is jóval kisebb, mint a feltaláló által készített régi műszer, és jóval könnyebben kezelhető. Ám némi anyagi ráfordítással a most használt technológiáknál maradva is akár karóra méretűre csökkenthető a mérőeszköz. Ehhez azonban komolyabb anyagi támogatásra, és további kutató, tervező munkára van szükség. Az EEPROM memóriák tárolókapacitása ma már lehetővé tenné azt is, hogy magában a műszerben történjen az adatrögzítés, ami szintén egyszerűsíthetne a mérőrendszer összetételén. Mint minden szoftvernek, így a mérőműszerben lévőnek is lehetnek későbbi változtatásai. A mikrokontrolleres környezet kiforrottsága akár már azt is lehetővé teszi, hogy a vezetéknélküli Bluetooth kapcsolaton keresztül történjen a firmware frissítése. Kiváló feladat egy apró bootoló monitor rendszer írása, ami a működtető programot képes lecserélni, illetve alapvető perifériakezelési rutinokat szolgáltat az alkalmazás(ok) számára. Különösen nagy szerepe van egy ilyen szoftverkomponensnek, ha több mikrokontrolleres projektben is használhatja a programozó. Ezek persze sok munkát, és időt igényelnek, illetve önmagukban is kellően nagy feladatok egy-egy önálló dolgozat témájának is. A projekt azonban tovább folytatódik a dolgozat megírása után is, új hallgatókat is bevezetve a műszerfejlesztés, és a projektmunka világába, így további előrelépések várhatóak akár az itt említett irányokban, akár új ötletek nyomán.
36
Firmware programozás egészségügyi állapotfelmérő rendszerhez
6
Ferenc István Csaba
Összegzés
Egy sorozatgyártásra alkalmas műszer terveinek és prototípusának elkészítése volt a cél. A berendezés osztott intelligenciájú rendszer, amelyet számítógépes feldolgozó szoftver, és egy célhardver együttese alkot. A célhardver programozása, a firmware megírása volt a feladatom. A kísérleti paneleken az orvosi vizsgálatok elvégzéséhez alkalmas hardware és software együttest állítottunk össze, így laboratóriumi tesztelésre alkalmas a rendszer, és referenciaként használható az elkészített tervekhez. A mérőrendszernek négy fő funkciója van, kétféle reakcióidő mérés, pletizmográfia és fiziológiás tremor analízis. A szenzorok kezelésén és a reakcióidő mérés megvalósításán túl kommunikációs feladatokat kellett megvalósítani. A számítógépes – vagy mobiltelefonos – feldolgozó szoftverrel való kétirányú kommunikációra vezetékes és vezeték nélküli alternatívát is implementáltam. Vezetékes csatornán RS-232, vezetéknélküli csatornán Bluetooth protokollt használ a rendszer. A kommunikáció a mért adatok továbbítását és a célhardver távvezérlését foglalja magába. A kommunikációhoz egyedi keretrendszert alakítottam ki. A perifériák kezeléshez réteges struktúrát alkalmazva saját függvényeket hoztam létre, amik az infravörös érzékelő jeleinek feldolgozásától a reakcióidő mérésén át a gyorsulásmérő adatainak továbbításáig minden feladathoz kész megoldásokat szolgáltatnak. Az „off-board” – a mérőeszköz és az adatfeldolgozó szoftverek valamelyike közt folytatott – kommunikáció kétirányúvá vált, és a mérőrendszer távvezérelhető is. A firmware monitor program jelleggel olyan programrészeket tartalmaz, melyek lehetővé teszik az Analóg Digitális átalakító segítségével analóg input perifériák kezelését. A kiértékeléshez kellő mintavételezési sebességgel és pontossággal képes adatokat szolgáltatni. Egy egyszerűsített analóg kimenet a sípszó generálására használt pulzusszélesség modulációt megvalósító Timer/Counter modul, ami a célnak – jelesül kétféle hangjelzés kiadása – megfelelő megoldást nyújt. Digitális perifériakezeléshez az I/O portokhoz, és a kommunikációs interfészekhez (Bluetooth, RS-232, SPI, UART) egyszerű hozzáférni a megírt komponensek által. Speciális eszközként a gyorsulásmérőhöz tartozó kommunikációs protokollt is implementáltam az SPI kiegészítéseként. Az „off-board” kommunikációt úgy valósítja meg a firmware, hogy rugalmasan kezeli az átviteli közegeket, így vezetékes és vezeték nélküli alternatíva is választható a mérőrendszer használatához. Az újrahasznosítható kódok mellett speciálisan a mérőrendszerhez írt programrészek jól elkülöníthetőek. A fő feladat az adatok gyors és pontos továbbítása a perifériák felől, ám a kiértékelés bizonyos részeit már a mikrokontrollerben lehetőség van elvégezni. Ilyen például a reakcióidő mérés kezelése. Az időmérést, időtúllépést, gombnyomások helyességét már a firmware végzi, és a kész adatokat csupán megjeleníteni kell, illetve statisztikát készíteni a feldolgozó számítógépes szoftvernek. A pletizmográfia adatsorából pedig a pulzus detektálására is lehetőség van a mérőeszközön. Természetesen a komolyabb kiértékelés nagyobb erőforrás igényű, és a számítógépes szoftver feladata. A projekt folytatásának a tervei is rendelkezésre állnak, és amennyiben kellő referenciák birtokában sikerül támogatókat szerezni, a nagyobb anyagi erőforrás igényű fejlesztéseket is megvalósítjuk. Új tagok bevonása is történik, a projekt ugyanis nem közvetlenül 37
Firmware programozás egészségügyi állapotfelmérő rendszerhez
Ferenc István Csaba
személyekhez, hanem az egyetemi tanulmányokhoz kapcsolódik. Minél több mérnök hallgató tud bekapcsolódni ebbe – vagy hasonló – projektekbe, annál több tapasztalattal rendelkező mérnök kerülhet ki egyetemünkről, ami véleményem szerint mindig is célkitűzés kell legyen mind a hallgatók részéről – hiszen nem mindegy hogy kikkel fognak együtt dolgozni – mind az oktatók részéről.
7
Köszönetnyilvánítás
A projekt minden résztvevőjének köszönettel tartozom, hogy ez a TDK dolgozat elkészülhetett. Első sorban a csapat tagjainak, akiknek nélkülözhetetlen munkája által nem csak a mikrokontroller programozásról szól a dolgozat, hanem egy komplett egészségügyi projekt egy állomása lehet. Másodsorban Dr. Kellényi Lóránd úrnak, aki megkeresett minket a találmányával, és megtisztelt a bizalmával, hogy a fejlesztési munkát is elvégezhetjük. Mindez persze nem lett volna kivitelezhető a konzulensek szakmai segítsége nélkül, jelesül Dr. Gáti Attila, a tanszék docense és Dr. Pungor András. A projekt vezetésében és az erőforrások előteremtésében játszott szerepéjért köszönet illeti Dr. Zambóné Benkő Máriát. Végül, de nem utolsó sorban az Elektrotechnikai- Elektronikai Tanszék tanszékvezetőjét és dolgozóit, akik engedélyezték és tolerálták jelenlétünket és munkánkat a tanszék laboratóriumában.
38
Firmware programozás egészségügyi állapotfelmérő rendszerhez
8
Ferenc István Csaba
Tartalom 1
2
Honnan…..................................................................................................................... 2 1.1 Mérőrendszer rövid bemutatása ............................................................................... 3 1.1.1
A mérőrendszerrel végzett vizsgálatok ....................................................................... 3
1.1.2
A mérőrendszer fizikai felépítése ................................................................................ 4
Hogyan…..................................................................................................................... 4 2.1 A digitális áramkörök kiválasztása .......................................................................... 5 2.1.1
Mikrokontroller ........................................................................................................... 5
2.1.2
Gyorsulásmérő ............................................................................................................ 7
2.1.3
Interfész modulok........................................................................................................ 8
2.1.4
Kvarc oszcillátorok – külső órajel a mikrovezérlőhöz .................................................. 8
2.2 Prototípus építése ................................................................................................... 10 3 Tesztelő kártya készítése ........................................................................................... 10 4 A mérőeszköz programozása ..................................................................................... 12 4.1 Perifériakezelés, driverek ....................................................................................... 14 4.1.1
I/O portok konfigurálása ........................................................................................... 14
4.1.2
Megszakítások ........................................................................................................... 15
4.1.3
SPI driver – „on-board” kommunikáció ..................................................................... 15
4.1.4
U(S)ART driver – „off-board” kommunikáció ............................................................ 18
4.1.5
Bluetooth modul driver ............................................................................................. 20
4.1.6
ADC driver.................................................................................................................. 21
4.1.7
PWM Beep driver ...................................................................................................... 23
4.2 A firmware fő programrésze (a main függvény) ................................................... 25 4.3 Időzítő .................................................................................................................... 26
5 6 7 8 9
4.3.1
Timer1 inicializálása................................................................................................... 27
4.3.2
A megszakítást lekezelő programrész ....................................................................... 30
4.3.3
A directory struktúra, programozás körülményei ..................................................... 35
Hova tovább… ........................................................................................................... 36 Összegzés................................................................................................................... 37 Köszönetnyilvánítás................................................................................................... 37 Tartalom..................................................................................................................... 39 Irodalomjegyzék ........................................................................................................ 40
39
Firmware programozás egészségügyi állapotfelmérő rendszerhez
9
Ferenc István Csaba
Irodalomjegyzék
Szigorúan véve a TDK dolgozatom megírásához a következő irodalom felhasználására került sor, ez azonban apró töredéke annak az irodalomnak, amit a projekt során tanulmányozni kellett. Írott források [1] AJTONYI István: Digitális Rendszerek, ISBN 9636613995, Miskolci Egyetemi Kiadó, 2006. [2] GÁRDUS Zoltán: Digitális Rendszerek Szimulációja, ISBN 9789639634558, Maxima Cs-A Kft. Miskolc, 2007. [3] KOVÁCS Norbert: Electrophysiological investigations in neurosorgically treated movement disorders, Ph.D. thesis, University of Pécs, Pécs, 2008. [4] KOVÁCS Norbert, BALÁS István, ILLÉS Zsolt, KELLÉNYI Lóránt, NAGY Ferenc: A tremorometria szerepe az ablatív műtétek eredményességének előrejelzésében, Ideggyógyászati Szemle 2006;59(11–12):438–440. oldal, [5] Simple and choice reaction times are prolonged following extracorporeal circulation: A potential method for the assessment of acute neurocognitive deficit, © Med Sci Monit, 2009; 15(9): CR470-476, PMID: 19721398 [6] TANNENBAUM, Andrew S.: Számítógép hálózatok, ISBN: 9789635453849, Panem Kft. Budapest, 2004.
Elektronikus források [7] ATMega32(L) official datasheet, Atmel Corporation, Rev. 2503D-AVR-02/03 http://www.atmel.com/dyn/resources/prod_documents/doc2503.pdf [8] avr-libc Online Documentation, Nongnu.org, February 2011 http://www.nongnu.org/avr-libc/ [9] LIS3LV02DQ official datasheet, ST Microelectronics, October 2005 http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERA TURE/DATASHEET/CD00047926.pdf [10] Open Source Initiative – The BSD 3 Clause License http://www.opensource.org/licenses/BSD-3-Clause [11] Rayson BTM-112 datasheet (2006) http://www.hestore.hu/files/btm-112.pdf
40