torstai 29. joulukuuta 2016

”TerveysTutka”, versio 0.0

Aikamoinen johtohässäkkä.
Tässä sovelluksessa on käytössä moduulit KY-039 (sydämen lyönnin indikaattori) ja KY-013 (termistorilla toteutettu lämpötila-anturi). Näyttönä on SUNTAI SC.2002A2BLYY-W kaksirivinen ja 20 merkkipaikkainen LCD-näyttö. Pääasia ei tietenkään ole terveyden tarkkailu, vaan pieni ohjelmasovellus näihin ihmisen ja moduuleiden rajapintaan. Esimerkki sydämen sykinnästä on videolla antinarduvideo31.youtube.com.
Tuo LCD-näyttö on jo varsin vanhaa ja poistuvaa tyyppiä. Sitä on kuitenkin jäänyt roikkumaan Yleiselektroniikka Oy:n hyllylle. Jäljellä olevat näytöt myydään pilkkahintaan. Kannattaa hyödyntää ne pois. Ei kirpaise niin pahasti, jos tuhoutuu kokeilussa.
 
Tämä LCD-näyttömalli ei sisällä ”ääkkösiä”, joten ne on ladattava kirjastoon (#LiquidCrystal.h) erikseen. Pienet ä ja ö sisältyvän tämän näytön kirjastoon, samoin kuin asteen merkki, mutta eivät kuitenkaan ole aivan samat, mitä ASCII-taulukko osoittaa. Suuret Ä ja Ö pitää muodostaa ja ladata aivan erikseen, piste pisteeltä, kuten myöskin ”sydämen imu- ja puristusvaiheet”. Noita isoja ääkkösiä ei tässä tekstissä tarvita.
     Tuo lämpötila-anturi (KY-013) perustuu NTC-termistoriin (NTC = Negative Temperature Coefficient = negatiivinen lämpötilakerroin), minkä vastus siis pienenee lämpötilan kasvaessa. Vastuksen muutos EI ole lineaarinen lämpötilan muutokseen nähden. Tässä sovelluksessa mittausta EI ole linearisoitu. Ohjelmassa on mittaus ja näyttö kalibroitu kahdessa pisteessä: 1. mittausta verrattu huoneen lämpötilaan ja säädetty näyttämään samaa. 2. Anturilla on mitattu ihon lämpötila = ”kainalokalibrointi” (37C). On mahdollista, että nuo pisteet ovat melko tarkkoja, mutta muut lämpötilat heittävät enemmän tai vähemmän.
     Anturissa KY-039 on IR-LEDi osoittamassa valotransistoria (tässä myös IR-alueelle herkkä) kohti. Infrapunasäteily tunkeutuu näiden kahden komponentin väliin laitetun sormen läpi. Veren erilainen määrä sormen päässä muuttaa säteilyn intensiteettiä, joten mooduulin lähdöstä on saatavissa vastaava signaali. Valotransistoriin vaikuttaa myös ympäristö. Siksi sovelluksessa on kaksi kondensaattoria, joilla pitkittäin olevalla erotetaan anturin antama tasajännite (pohjalukema) sekä hitaat muutokset. (Ohjelmallisesti en onnistunut sauodatuksessa.) Poikittain oleva pienempi kondensaattori suodattaa nopeat, esim. huoneen valaistuksen ym. häriöt. Sen rinnalla on 100 kilo-ohmin purkausvastus. Aikavakiot sopivat sydämen lyöntirytmiin. Täten on mahdollista saada sydämen kuvio sykkimään lyöntien tahtiin. Signaali on varsin pieni – muutaman kymmenen millivoltin luokkaa. Onneksi kuitenkin ja luotan vakaasti, että SOTE-porukalla tulee olemaan oleellisesti korkeatasoisemmat tutkimusvälineen kuin tässä esittämäni.
Moduulien ja LCD-näytön kytkentä Arduinoon
Ohjeman aluksi määritellään ja tuodaan kirjasto: #include <LiquidCrystal.h>. Seuraavana kirjastomoduulille kerrotaan ohjausbitit. Ne eivät välttämättä tarvitse olla juuri nuo, mutta niiden järjestys on oleellinen. Sitten kirjastolle määritellään binääritietoina ä, ö ja aste. Ne löytyvät näytön ominaisuuksista. Sitten kaksi kahdeksan (8) bitin binääritaulukkoa, joilla kirjastolle määritellään sydämen näytön kaksi tilaa.
     Näiden jälkeen muiden muuttujien määrittelyt ja aliohjelmat. Asetuksissa kirjoitetaan vakiotekstit, ja täten vain kerran. Sydänkuvio, lyöntinopeus sekä lämpötila päivitetään omille kohdilleen ohjelman aikana.
     Ohjelman aluksi mitataan sisäistä aikaa (millis()) ja lasketaan lämpötila. Sydämen lyönnin valvonta koostuu kolmen askeleen sekvenssistä. Sekvenssi odottaa sykettä askeleessa 1. Kun sellainen havaitaan analogiatulossa, talletetaan tämä aikalukema askeleessa 1 ja siirrytään askeleeseen 2 odottamaan uutta sykäystä. Kun se on tullut, talletetaan sykkeiden väliaika ja hypätään askeleeseen 3. Siellä lasketaan ja muunnetaan väliaika sydämenlyönneiksi minuutissa, sekä päivitetään tämä ja lämpötilan lukema näyttöön. Sekvenssi hyppää takaisin askeleeseen yksi odottamaan seuraavaa lyöntiä.
Viimeisenä ohjelmassa on muutama lause, joilla pienen viiveen jälkeen palauttetaan sydänkuvio ”imutilaan”.

OHJELMA 31
/**************************************
* Ohjelma 31
* 28.12.2016
* Kehon lämpötila ja sydänpulssit
**************************************/
// MÄÄRITTELYT:
   #include <LiquidCrystal.h>
   LiquidCrystal lcd(12, 11, 5, 4,3,2);

   const byte api = B11100001; // ä
   const byte opi = B11101111; // ö
   const byte ast = B11011111; // aste
   byte Syd1[8] = // Sydämen reunat
                           {B00000,B00000,B01010,B10101,
                           B10001,B10001,B01010,B00100};
   byte Syd2[8] = // Sydämen sisus
                           {B00000,B00000,B00000,B01010,
                           B01110,B01110,B00100,B00000};
   int i = 0;

// Ajastukset
   unsigned long Ulo_MilliSek = 0;
   unsigned long Ulo_EdellinenMilliSek = 0;
   const int Con_Kierrokset = 40;
   unsigned int Unt_Kierrokset = 0;
   int Int_Kierrokset = 0;
   boolean Bol_Aika = false;

// Sydän-määritykset
   const int Con_Pulssi = A1;
   int Int_PulssiRaaka = 0;
   unsigned int Unt_SykeVali = 0;
   float Flo_PulsPerMin = 0;
   unsigned int Unt_Pulssit = 0;
   boolean Bol_SydSyk = false;
   int Seq_Syke = 1;

// Lämpötilan mittaus
   const int Con_LampAnturi = A0;
   int Int_LampoRaaka = 0;
   float Flo_LampoTila = 0.0;

// ALIOHJELMAT
// Sydämen syke näyttöön
   void Fun_Sydan(int i){
      lcd.setCursor(10,0);
      lcd.print(" ");
      lcd.write(i);
   }// Syke loppu

// Pulssit näyttöön
   void Fun_Pulssit(int p){
      lcd.setCursor(13,0);
     lcd.print(p);
   }

//Lämpötila näyttöön
   void Fun_Lampo(float t){
      lcd.setCursor(11,1);
      lcd.print(t);
      lcd.setCursor(15,1);
      lcd.write(ast);
      lcd.print("C");
   }

// ASETUKSET:
   void setup(){
      Serial.begin(9600); // Sarjaliikenteen alustus
      lcd.createChar(0,Syd1); // Sydämen reunat
      lcd.createChar(1,Syd2); // Sydämen sisus
      lcd.begin(20,2);
      lcd.clear();
// Tekstit näyttöön, suoritetaan kerran
      lcd.setCursor(0, 0);
      lcd.print("Syd");
      lcd.write(api);
      lcd.print("nly");
      lcd.write(opi);
      lcd.print("n:         p/min");
      lcd.setCursor(0, 1);
      lcd.print("L");
      lcd.write(api);
      lcd.print("mp");
      lcd.write(opi);
      lcd.print("tila:");
   }// Asetuksen loppu

// PÄÄLOOPPI
   void loop(){
      Ulo_MilliSek = millis();
      Int_LampoRaaka = analogRead(Con_LampAnturi);
      int Temp = constrain((335 - Int_LampoRaaka), 0, 100);
      Flo_LampoTila = 22.7 + 0.17 * Temp;
      Int_PulssiRaaka = analogRead(Con_Pulssi);
      if(Int_PulssiRaaka > 2){
            Bol_SydSyk = true;
            if(Seq_Syke == 1) {Bol_SydSyk = true;}
      } // Pulssin mittaus loppu

// Sydän supistuu
      switch (Seq_Syke) {
            case 1:
                  if(Bol_SydSyk == true){
                        Ulo_EdellinenMilliSek = Ulo_MilliSek;
                        Bol_SydSyk = false;
                        delay(300);
                  Seq_Syke = 2;
                  }
            break;
            case 2:
                  if(Int_PulssiRaaka > 2){
                        Unt_SykeVali = Ulo_MilliSek - Ulo_EdellinenMilliSek;
                        Unt_SykeVali = constrain(Unt_SykeVali, 10, 2999);
                        Bol_SydSyk = false;
                  if(Unt_SykeVali < 3000){
                        Seq_Syke = 3;
                  }}
            break;
            case 3:
                  Flo_PulsPerMin = 1000.0 / Unt_SykeVali * 60.0;
                  Unt_Pulssit = Flo_PulsPerMin;
                  Unt_Pulssit = constrain(Unt_Pulssit, 20, 99);
                  i = 1;
                        Fun_Sydan(i);
                        Fun_Pulssit(Unt_Pulssit);
                        Bol_SydSyk = false;
                        Fun_Lampo(Flo_LampoTila);
                  Seq_Syke = 1;
                  break;
            }// Sekvenssi loppu

// Sydän avautuu
      Unt_Kierrokset++;
      if(Unt_Kierrokset > Con_Kierrokset){
            Bol_SydSyk = false;
            i = 0;
            Fun_Sydan(i);
            Unt_Kierrokset = 0;} // Kierroslaskuri loppu

      delay(1);
} // Pääohjelma LOPPU

Ei kommentteja:

Lähetä kommentti