单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:692|回复:2

基于Arduino uno的多功能血氧仪程序

[复制链接]
ID:1113970发表于 2024-3-24 16:55|显示全部楼层
#include< MAX3010x.h>
#include "filters.h"
#include< Adafruit_GFX.h>       //OLED   libraries
#include< SPI.h>
#include< Adafruit_GFX.h>
#include< Adafruit_SSD1306.h>
//#include< MAX30105extra.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,& Wire, OLED_RESET);
// Sensor (adjust to your sensor type)
MAX30105 sensor;
//MAX30105extra particleSensor;
const auto kSamplingRate = sensor.SAMPLING_RATE_400SPS;
const float kSamplingFrequency = 400.0;

// Finger Detection Threshold and Cooldown
const unsigned long kFingerThreshold = 10000;
const unsigned int kFingerCooldownMs = 500;

// Edge Detection Threshold (decrease for MAX30100)
const float kEdgeThreshold = -2000.0;

// Filters
const float kLowPassCutoff = 5.0;
const float kHighPassCutoff = 0.5;

// Averaging
const bool kEnableAveraging = false;
const int kAveragingSamples = 5;
const int kSampleThreshold = 5;

// limitation of sop2
const int spo2limit =95;
void setup() {
   Serial.begin(9600);
   display.begin(SSD1306_SWITCHCAPVCC,   0x3C); //Start the OLED display
   delay(3000);
   tone(3,1000);                           //And   tone the buzzer for a 100ms you can reduce it it will be better
   delay(1000);
   noTone(3);
   display.display();
   if(sensor.begin()&& sensor.setSamplingRate(kSamplingRate)) {
   Serial.println("Sensor initialized");
   }
   else {
   Serial.println("Sensor not found");  
   while(1);
   }
}

// Filter Instances
LowPassFilter low_pass_filter_red(kLowPassCutoff, kSamplingFrequency);
LowPassFilter low_pass_filter_ir(kLowPassCutoff, kSamplingFrequency);
HighPassFilter high_pass_filter(kHighPassCutoff, kSamplingFrequency);
Differentiator differentiator(kSamplingFrequency);
MovingAverageFilter<kAveragingSamples> averager_bpm;
MovingAverageFilter<kAveragingSamples> averager_r;
MovingAverageFilter<kAveragingSamples> averager_spo2;

// Statistic for pulse oximetry
MinMaxAvgStatistic stat_red;
MinMaxAvgStatistic stat_ir;

// R value to SpO2 calibration factors
float kSpO2_A = 1.5958422;
float kSpO2_B = -34.6596622;
float kSpO2_C = 112.6898759;

// Timestamp of the last heartbeat
long last_heartbeat = 0;

// Timestamp for finger detection
long finger_timestamp = 0;
bool finger_detected = false;

// Last diff to detect zero crossing
float last_diff = NAN;
bool crossed = false;
long crossed_time = 0;

int lowsopcount =0;

void loop() {

   unsigned int val; //定义变量val
   unsigned int dat;//定义变量dat
   val=analogRead(1);//将val设置为读取到的A0的数值
   dat=(500 * val) /1024; //计算出当前温度数字dat
   auto sample = sensor.readSample(1000);
   float current_value_red = sample.red;
   float current_value_ir = sample.ir;
   // Detect Finger using raw sensor value
   if(sample.red > kFingerThreshold) {
   if(millis() - finger_timestamp > kFingerCooldownMs) {
     finger_detected = true;
   }
   }
   else {
   // Reset values if the finger is removed
   differentiator.reset();
   averager_bpm.reset();
   averager_r.reset();
   averager_spo2.reset();
   low_pass_filter_red.reset();
   low_pass_filter_ir.reset();
   high_pass_filter.reset();
   stat_red.reset();
   stat_ir.reset();

   finger_detected = false;
   finger_timestamp = millis();
   }

   if(finger_detected) {
   current_value_red = low_pass_filter_red.process(current_value_red);
   current_value_ir = low_pass_filter_ir.process(current_value_ir);

   // Statistics for pulse oximetry
   stat_red.process(current_value_red);
   stat_ir.process(current_value_ir);

   // Heart beat detection using value for red LED
   float current_value = high_pass_filter.process(current_value_red);
   float current_diff = differentiator.process(current_value);

   // Valid values?
   if(!isnan(current_diff)&& !isnan(last_diff)) {

     // Detect Heartbeat - Zero-Crossing
     if(last_diff > 0&& current_diff< 0) {
       crossed = true;
       crossed_time = millis();
     }

     if(current_diff > 0) {
       crossed = false;
     }

     // Detect Heartbeat - Falling Edge Threshold
     if(crossed&& current_diff< kEdgeThreshold) {
       if(last_heartbeat != 0&& crossed_time - last_heartbeat > 300) {
       // Show Results
       int bpm = 60000/(crossed_time - last_heartbeat);
       float rred = (stat_red.maximum()-stat_red.minimum())/stat_red.average();
       float rir = (stat_ir.maximum()-stat_ir.minimum())/stat_ir.average();
       float r = rred/rir;
       float spo2 = kSpO2_A * r * r + kSpO2_B * r + kSpO2_C;

       if(bpm > 50&& bpm< 250) {
         // Average?
         if(kEnableAveraging) {
           int average_bpm = averager_bpm.process(bpm);
           int average_r = averager_r.process(r);
           int average_spo2 = averager_spo2.process(spo2);

           // Show if enough samples have been collected
           if(averager_bpm.count() >= kSampleThreshold) {
           Serial.print("Time (ms): ");
           Serial.println(millis());
           Serial.print("Heart Rate (avg, bpm): ");
           Serial.println(average_bpm);
           Serial.print("R-Value (avg): ");
           Serial.println(average_r);  
           Serial.print("SpO2 (avg, %): ");
           Serial.println(average_spo2);
           if( average_spo2 >100) average_spo2 = 100;  
           display.clearDisplay();                         //Clear the display    
           display.setTextSize(2);                         //Near   it display the average BPM you can display the BPM if you want
           display.setTextColor(WHITE);  
           display.setCursor(15,0);          
           display.println("BPM");          
           display.setCursor(70,0);          
           display.println(bpm);
           display.setCursor(15,18);          
           display.println("SpO2");          
           display.setCursor(70,18);          
           display.println((int)average_spo2);  
           display.setCursor(15,36);          
           display.println("TMP");          
           display.setCursor(70,36);          
           display.println((int)dat);  

           display.display();

           if ((int)average_spo2< spo2limit){
             lowsopcount++;
             if (lowsopcount >3) {
               tone(3,1000);                           //And   tone the buzzer for a 100ms you can reduce it it will be better
               delay(1000);
               noTone(3);              
             }
           }
           if((int)average_spo2 >spo2limit)   lowsopcount = 0;        
           }
         }
         else {
           Serial.print("Time (ms): ");
           Serial.println(millis());
           Serial.print("Heart Rate (current, bpm): ");
           Serial.println(bpm);  
           Serial.print("R-Value (current): ");
           Serial.println(r);
           Serial.print("SpO2 (current, %): ");
           Serial.println(spo2);
           if( spo2 >100) spo2 = 100;  
           display.clearDisplay();                         //Clear the display    
           display.setTextSize(2);                         //Near   it display the average BPM you can display the BPM if you want
           display.setTextColor(WHITE);  
           display.setCursor(15,0);          
           display.println("BPM");          
           display.setCursor(70,0);          
           display.println(bpm);
           display.setCursor(15,18);          
           display.println("SpO2");          
           display.setCursor(70,18);          
           display.println((int)spo2);
           display.setCursor(15,36);          
           display.println("TMP");          
           display.setCursor(70,36);          
           display.println((int)dat);  
           display.display();
           if ((int)spo2< spo2limit){
           lowsopcount++;
             if (lowsopcount >3) {
               tone(3,1000);                           //And   tone the buzzer for a 100ms you can reduce it it will be better
               delay(1000);
               noTone(3);              
             }
           }
           if((int)spo2 >spo2limit)   lowsopcount = 0;  
         }
       }

       // Reset statistic
       stat_red.reset();
       stat_ir.reset();
       }

       crossed = false;
       last_heartbeat = crossed_time;
     }
   }

   last_diff = current_diff;
   }
}
ID:161129发表于 2024-7-8 20:42|显示全部楼层
您好,您设计的这个程序显示屏是用哪个型号的?
ID:161129发表于 2024-7-9 16:13|显示全部楼层
这个程序缺少的库文件在哪里下载呀

手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网