This is an old revision of the document!
Student: Serban Emilia-Bianca, 333CC
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.
Mod de funcționare
Schema bloc
Mediu de dezvoltare: Arduino IDE
Biblioteci:
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ă:
Valori prestabilite si corespondenta cu LED-urile
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.
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.
#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; } }