This is an old revision of the document!


Pulsometru

Student: Serban Emilia-Bianca, 333CC

Introducere

Proiectul presupune proiectarea unui dispozitiv care detectează și masoară pulsul cardiac al utilizatorului. Acest tip de dispozitiv se numește pulsometru și are scop medical, acesta verificând cât de bine pompează inima sângele în corp și fiind folosit pentru monitorizarea stării de sănătate a utilizatorilor.

Pentru realizarea pulsometrului, voi utiliza o placă de dezvoltare Arduino UNO R3, un senzor de puls, un buton, un buzzer care va reda bătăile inimii , un ecran OLED care va afisa valoarea si graficul ritmului cardiac, și LED-uri RGB care, dupa evaluarea pulsului, vor indica dacă acesta se află în parametrii normali.

Descriere generală

Mod de funcționare

  • Se apasă butonul pentru a porni dispozitivul
  • După apăsarea butonului, se înregistrează pulsul cardiac al utilizatorului prin intermediul senzorului de puls
  • Se afișează valoarea și graficul ritmului cardiac pe ecranul OLED și/sau în interfața serială a calculatorului
  • În timpul preluării pulsului, buzzer-ul va reda sunetul bătăilor inimii
  • Se evaluează valoarea pulsului și, în funcție de intervalul în care se încadrează, LED-urile vor avea culoarea verde (puls normal), galben (puls ușor ridicat) sau roșu (puls ridicat)

Schema bloc

Hardware Design

Listă de piese:

  • Arduino UNO R3 ATMEGA328P
  • Senzor de Puls XD-58C
  • Buzzer activ 5V
  • LED-uri RGB 4mm
  • Display OLED 0.96” I2C IIC Albastru

Mentionez ca in aceasta schema, senzorul de temperatura, de fapt, este un senzor de puls, iar buzzerul nu este acest model.

Software Design

Mediu de dezvoltare: Arduino IDE

Biblioteci:

  • Pentru ecranul OLED:
    • Adafruit_GFX.h
    • Adafruit_SSD1306.h
    • Wire.h
    • SPI.h
  • Pentru senzorul de puls:
    • PulseSensorPlayground.h

Descrierea codului

ISR si setup_interrupt_INT0(): Se implementează o întrerupere externă INT0, care va fi declanșată de un buton extern conectat la pinul PD2. În interiorul întreruperii, se actualizează variabila de stare pentru a indica că se dorește urmărirea pulsului.

setup(): Se inițializează comunicarea serială și afișajul OLED. Apoi, se configurează LED-urile, buzzerul si managerul senzorului de puls pentru a utiliza pinul A0 și se setează pragul pentru detecția pulsului. Dacă inițializarea senzorului de puls nu reușește, programul va rămâne într-o buclă infinită cu LED-ul pulsând pentru a indica eroarea.

loop(): Se efectuează următoarele acțiuni, în funcție de starea curentă:

  • Starea 0: Așteaptă declanșarea butonului pentru a începe monitorizarea pulsului. Se activează întreruperea externă INT0.
  • Starea 1: Se inițializează măsurătorile pulsului și se efectuează citiri periodice ale valorilor senzorului de puls timp de 20 secunde. Se calculează suma valorilor si numarul de valori citite (valori detectate care au trecut Threshold-ul). De asemenea, buzzerul va reda la fiecare citire un sunet. Acesta este menit sa redea acest sunet la fel de frecvent ca bataile inimii.
  • Starea 2: Dupa monitorizarea de 20 de secunde, se calculează rezultatele finale ca raportul dintre suma si numarul de valori citite, se afișează pe ecran și se evaluează valoarea medie a pulsului. In funcție de limitele prestabilite, LED-urile corespunzătoare se aprind în funcție de rezultat. După o pauză de 10 secunde, starea revine la 0, iar variabilele pentru suma și numărul de măsurători se resetează.

Valori prestabilite si corespondenta cu LED-urile

  • 60 BPM - 100 BPM : LED Verde
  • +/- 10 BPM față de cele normale: LED Galben
  • în afara valorilor mentionate mai sus: LED Roșu

Pulsul normal sau frecventa cardiaca normala variaza la adulti intre 60 si 100 de batai pe minut atunci cand se afla intr-o stare relaxata.

Rezultate Obţinute

  • Aici se gaseste un scurt demo.

Concluzii

Codul prezentat implementează o funcționalitate de bază pentru monitorizarea ritmului cardiac și evaluarea acestuia în funcție de anumite limite prestabilite. Utilizarea sa în scop medical ar necesita îmbunătățiri și validări suplimentare pentru a asigura acuratețea și siguranța datelor colectate și a rezultatelor furnizate. Înainte de a utiliza acest cod într-un scop medical, este important să se efectueze teste și validări riguroase pentru a verifica faptul că valorile măsurate sunt precise și că rezultatele obținute sunt în concordanță cu standardele medicale.

Trebuie mentionat faptul ca senzorul nu este de cea mai inalte calitate, acest fapt influentand datele colectate si corectitudinea lor. Totusi, este de apreciat faptul ca, daca persoana careia i se preiau datele se afla intr-o pozitie corecta, nemiscata si relaxata, datele sunt foarte apropiate de cele reale.

Download

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
 
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
#define USE_ARDUINO_INTERRUPTS false
#include <PulseSensorPlayground.h>
const int OUTPUT_TYPE = SERIAL_PLOTTER;
const int PULSE_INPUT = A0;
const int PULSE_BLINK = LED_BUILTIN;
const int PULSE_FADE = 5;
const int THRESHOLD = 518;   // Adjust this number to avoid noise when idle
 
byte samplesUntilReport;
const byte SAMPLES_PER_SERIAL_SAMPLE = 10; // 10
PulseSensorPlayground pulseSensor;
 
#define ORANGE_LOW_LIMIT 50
#define ORANGE_HIGH_LIMIT 110
#define LOW_LIMIT 60
#define HIGH_LIMIT 100
 
 
 
int state = 0;
unsigned long begin = 0;
unsigned long ts = 0;
const int buzzer = 8;
const int RED_PIN = 9;
const int GREEN_PIN = 11;
const int BLUE_PIN = 10;
int suma_BPM = 0;
int counter_BPM = 0;
 
 
ISR(INT0_vect)
{
  //cod întrerupere externă
  if(millis() - ts > 500){
    ts = millis();
    state = 1;
 
  }
}
 
void setup_interrupt_INT0() {
  // buton 1: PD2 / INT0
  // input
  DDRD &= ~(1 << PD2);
  // input pullup
  PORTD |= (1 << PD2);
  // configurare intrerupere INT0 pe falling edge
  EICRA |= (1 << ISC01);
  // activare intrerupere externa INT0
  EIMSK |= (1 << INT0);
}
 
void setup() {
  cli();
  sei();
  Serial.begin(115200);
 
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();
 
  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  // Display static text
  display.println("Hello!");
  display.display(); 
 
  // output buzzer
  pinMode(buzzer, OUTPUT);
  // output LEDuri RYG
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
 
  // Configure the PulseSensor manager.
  pulseSensor.analogInput(PULSE_INPUT);
  pulseSensor.blinkOnPulse(PULSE_BLINK);
  pulseSensor.fadeOnPulse(PULSE_FADE);
 
  pulseSensor.setSerial(Serial);
  pulseSensor.setOutputType(OUTPUT_TYPE);
  pulseSensor.setThreshold(THRESHOLD);
 
  // Skip the first SAMPLES_PER_SERIAL_SAMPLE in the loop().
  samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
 
 
  // Now that everything is ready, start reading the PulseSensor signal.
  if (!pulseSensor.begin()) {
    /*
       PulseSensor initialization failed,
       likely because our Arduino platform interrupts
       aren't supported yet.
 
       If your Sketch hangs here, try changing USE_PS_INTERRUPT to false.
    */
    for(;;) {
      // Flash the led to show things didn't work.
      digitalWrite(PULSE_BLINK, LOW);
      delay(50);
      digitalWrite(PULSE_BLINK, HIGH);
      delay(50);
    }
  }
}
 
 
 
void loop() {
  // put your main code here, to run repeatedly: 
  if (state == 0)
  {
    // activam intreruperea INT0 pe buton
    setup_interrupt_INT0();
    begin = 0 ;
 
  }
 
  if ( state == 1)
  {
    Serial.println("Tracking pulse...");
    if ( begin == 0)
    {
      begin = millis();
    }
 
    while ( millis() - begin <= 20000) {
 
      //incepem sa afisam bataile inimii
        if (pulseSensor.sawNewSample()) {
      /*
        Every so often, send the latest Sample.
        We don't print every sample, because our baud rate
        won't support that much I/O.
      */
        if (--samplesUntilReport == (byte) 0) {
          samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE;
 
          pulseSensor.outputSample();
 
          /*
            At about the beginning of every heartbeat,
            report the heart rate and inter-beat-interval.
          */
          if (pulseSensor.sawStartOfBeat()) {
 
            digitalWrite(buzzer, HIGH);
 
            //pulseSensor.outputBeat();
 
            int myBPM = pulseSensor.getBeatsPerMinute();  // Calls function on our pulseSensor object that returns BPM as an "int".
                                                          // "myBPM" hold this BPM value now. 
              suma_BPM += myBPM;
              counter_BPM++;
            display.setCursor(5, 10);
            display.clearDisplay();
            display.print(String(myBPM));
            display.print(" BPM");
            display.display();
            digitalWrite(buzzer, LOW);
 
 
          }
 
        }
      }
 
    }
    state = 2;
 
  }
 
  if ( state == 2)
  {
   int rezultat =  suma_BPM / counter_BPM;
   display.clearDisplay();
   display.setCursor(10, 10);
   display.setTextColor(WHITE);
   //display.print("* ");
   display.print(String(rezultat));
   display.print(" BPM");
   //display.print(" *");
   display.display();
 
   if ( rezultat < ORANGE_LOW_LIMIT || rezultat > ORANGE_HIGH_LIMIT)
   {
    // fa beculetul ROSU
    digitalWrite(RED_PIN, HIGH);
    Serial.println("Puls anormal. Va rugam consultati un medic!");
   }
   else if ( rezultat >= ORANGE_LOW_LIMIT && rezultat <= LOW_LIMIT || rezultat >= HIGH_LIMIT && rezultat <= ORANGE_HIGH_LIMIT)
   {
    // fa beculetul GALBEN
    digitalWrite(BLUE_PIN, HIGH);
    Serial.println("Puls usor crescut.");
   } else if(rezultat >= LOW_LIMIT && rezultat <= HIGH_LIMIT)
   {
    // fa beculetul VERDE
    digitalWrite(GREEN_PIN, HIGH);
    Serial.println("Puls normal.");
   }
   delay(10000);
 
   digitalWrite(RED_PIN, LOW);
   digitalWrite(GREEN_PIN, LOW);
   digitalWrite(BLUE_PIN, LOW);
 
   state = 0;
   suma_BPM = 0;
   counter_BPM = 0;
 
  }
}

Arhiva cu programul: serbanbianca_pulsometru2023.zip

Jurnal

  • 5 Mai: Creare pagină Wiki + documentație

Bibliografie/Resurse

Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe Resurse Software şi Resurse Hardware.

Export to PDF

pm/prj2023/danield/pulsometru.1685302633.txt.gz · Last modified: 2023/05/28 22:37 by emilia.serban
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0