sparkfun / SparkFun_MAX3010x_Sensor_Library

An Arduino Library for the MAX3015 particle sensor and MAX30102 Pulse Ox sensor
Other
229 stars 147 forks source link

HR betweem 150 to 250 #17

Open talal44 opened 6 years ago

talal44 commented 6 years ago

what am I missing here? what do I have to adjust to get the right numbers? untitled

nseidle commented 6 years ago

Did you follow the hookup guide? I'm hoping you used a rubber band or other positive pressure device to hold the sensor against your finger?

talal44 commented 6 years ago

Thanks for your prompt reply. I did everything as the guide explains, the spo2 looks great, however the hr is always high. 150 and above, that doesn't seem to be right. I am quite relaxed and alive.....

nseidle commented 6 years ago

Let's check the basics.

What platform are you connected to? What voltage are you running at? Do you have a link to the board you purchased?

On Thu, Aug 9, 2018, 9:30 PM talal44 notifications@github.com wrote:

Thanks for your prompt reply. I did everything as the guide explains, the spo2 looks great, however the hr is always high. 150 and above, that doesn't seem to be right. I am quite relaxed and alive.....

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-411964930, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHJbuLs2Isb4S5VlnOV6n5fl-1urX3Bks5uPP43gaJpZM4V3goW .

talal44 commented 6 years ago

I have two boards, arduino uno and elegoo mega2560 r3. It doesn't make any difference whether I connect my sparkfun max30105 to 5v or 3.3v. I got almost same reading both ways.

nseidle commented 6 years ago

And just to be clear, are you using the SparkFun board?

Looks like you're running example 8. Do you see different output when you run example 5_HeartRate? The IC is configured differently in Example 5.

talal44 commented 6 years ago

I am using the red Sparkfun max30105 board. I get better better sensible and logical hr numbers with example 5.

nseidle commented 6 years ago

Ah, ok. Sounds like the hardware is functioning. Both examples depend on Maxim's algorithms. We can support the library but you'll need to talk to Maxim for support on the algorithms.

A quick search turned up some other options. This example might get you started down a better Sp02 detection.

talal44 commented 6 years ago

Thanks a lot for your guidance. However, I still didn't got it, am I the only one who has this problem with the HR numbers in example_8? even when I use my new Sparkfun esp8266 thing board I get the same results. When I opened this issue I was hoping that there is someone who had the same issue and found a solution somehow.

ThingEngineer commented 6 years ago

I have run across the exact same problem. I'm running a MAX30102 on a DIYmall breakout board. http://a.co/d/d31zetS On an ESP8266 (AI-Thinker) - (Adafruit Feather Huzzah equivalent).

All of the examples work as expected except the SPO2 example 8. I get readings like this: red=105481, ir=121830 red=105500, ir=121889 red=105502, ir=121942 red=105521, ir=122030, HR=166, HRvalid=1, SPO2=100, SPO2Valid=1 red=105529, ir=122088, HR=166, HRvalid=1, SPO2=100, SPO2Valid=1 red=105498, ir=121597, HR=166, HRvalid=1, SPO2=100, SPO2Valid=1 red=105229, ir=121368, HR=166, HRvalid=1, SPO2=100, SPO2Valid=1

The calculated values do fluctuate but they seem like complete garbage.

My heart rate during the above measurement was between 50 and 60 bpm with a tight finger strap (velcro) and clean red/ir signals (seen if I switch to plotting them like this): Serial.print(redBuffer[i], DEC); Serial.print(F(",")); Serial.println(irBuffer[i] - 17000, DEC);

The - 17000 on the ir was to move it closer to the red so the plotter is zoomed in better. (I hate you Arduino serial plotter, but you're convenient.)

I was hoping for a quick on chip solution to this so I could move on but looks like I'll have to dig in a bit more. I haven't dug into the yet but I'll share my results when I do.

I'm curious, has ANYONE seen this example work properly?

UPDATE: Tired again on an Adafruit Feather M0, same results.

pzink commented 6 years ago

Having the same issue, same board as ThingEngineer. Anyone find another board/code example that works for SpO2?

anning865 commented 5 years ago

Same issue. It is not about the board, it is about the code, or specifically the algorithm. The code from Maxim can work sometimes, but it doesn't work well at the most time ,especially under the external light interference. I had checked the waveform of raw data and found it worse when I turned on the table lamp next to me. So you can use some black item to cover the sensor board and try it again. But I still think the code from Maxim is too sensitive to the interference and we need to improved it.

soluna1 commented 4 years ago

Hi, couple of years later still finding the same issue with HR with using code from example 8, based on spo2_algorithm.h library. But, I get reasonable good data with example 5, based on "heartRate.h" lib. So, has anyone solved this questions. Is it possible to combine HR calculated from example 5 and spo2 from example 8? BTW both seems to work fin in MAX30100. I hope there is still someone interested in this.

thanks

caferrick commented 4 years ago

I am also having the same issue. Heart Rate is just all over the place the Oxygen reading seems good. When i combine 5 and 8 the heart rate is still all over the place. Soluna1 I will keep report back with any additional information.

lfssp commented 4 years ago

I am also struggling with this issue! Example 5 works like a charm for HR. Example 8 shows SPO correctly, but HR is completely messed up. I've been trying to combine them, but apparently the issue is when you call setup() with different values. Setup() conf for example 5 doesn't work with spo and setup parameters from example 8 doesn't get correct HR.

caferrick commented 4 years ago

I have a new algorithm that seems to work fairly well. I will reply to this email in a little bit.

On Mon, Jun 15, 2020 at 3:51 AM lfssp notifications@github.com wrote:

I am also struggling with this issue! Example 5 works like a charm for HR. Example 8 shows SPO correctly, but HR is completely messed up. I've been trying to combine them, but apparently the issue is when you call setup() with different values. Setup() conf for example 5 doesn't work with spo and setup parameters from example 8 doesn't get correct HR.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-643964972, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNPQOO5XIE5Q4SXPTLDRWXHJTANCNFSM4FO6BILA .

lfssp commented 4 years ago

That's a good news @caferrick . Waiting to see your progress.

caferrick commented 4 years ago

I did not strip anything out so please use what you like. The program send the SPO2 and HBM via bluetooth. The device that I am using is an Arduino feather.

/**** *

include "BluefruitConfig.h"

// BlueTooth

if SOFTWARE_SERIAL_AVAILABLE

include

endif

Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

include

include "MAX30105.h" //sparkfun MAX3010X library

MAX30105 particleSensor;

//#define MAX30105 //if you have Sparkfun's MAX30105 breakout board , try

define MAX30105

/ BlueTooth service information /

int32_t ServiceId; int32_t hrmMeasureCharId; int32_t hrmLocationCharId; int32_t spoMeasureCharId;

/** heart rate *****/ static double fbpmrate = 0.95; // low pass filter coefficient for HRM in bpm static uint32_t crosstime = 0; //falling edge , zero crossing time in msec static uint32_t crosstime_prev = 0;//previous falling edge , zero crossing time in msec static double bpm = 40.0; static double ebpm = 40.0; static double eir = 0.0; //estimated lowpass filtered IR signal to find falling edge without notch static double firrate = 0.85; //IR filter coefficient to remove notch , should be smaller than frate static double eir_prev = 0.0;

define TIMETOBOOT 3000 // wait for this time(msec) to output SpO2

define SCALE 88.0 //adjust to display heart beat and SpO2 in the same scale

define SAMPLING 5 //if you want to see heart beat more precisely , set

SAMPLING to 1

define FINGER_ON 30000 // if red signal is lower than this , it indicates

your finger is not on the sensor

define MINIMUM_SPO2 80.0

define FINGER_ON 50000 // if ir signal is lower than this , it indicates

your finger is not on the sensor

define LED_PERIOD 100 // light up LED for this period in msec when zero

crossing is found for filtered IR signal

define MAX_BPS 180

define MIN_BPS 45

// A small helper void error(const __FlashStringHelper*err) { Serial.println(err); while (1); }

define USEFIFO

void setup() {

boolean success; Serial.begin(115200); Serial.println("Initializing...");

Serial.println(F("Adafruit Bluefruit Heart Rate Monitor (HRM) Example")); Serial.println(F("---------------------------------------------------"));

/ Initialise the module / Serial.print(F("Initialising the Bluefruit LE module: "));

if ( !ble.begin(VERBOSE_MODE) ) { error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); } Serial.println( F("OK!") );

/ Perform a factory reset to make sure everything is in a known state / Serial.println(F("Performing a factory reset: ")); if (! ble.factoryReset() ){ error(F("Couldn't factory reset")); }

/ Disable command echo from Bluefruit / ble.echo(false); ble.info();

// this line is particularly required for Flora, but is a good idea // anyways for the super long lines ahead! // ble.setInterCharWriteDelay(5); // 5 ms

/ Change the device name to make it easier to find / Serial.println(F("Setting device name to 'Bluefruit HRM': "));

if (! ble.sendCommandCheckOK(F("AT+GAPDEVNAME=HMHS Health Monitor")) ) { error(F("Could not set device name?")); }

/ Add the Heart Rate Service definition / / Service ID should be 1 / Serial.println(F("Adding the Heart Rate Service definition (UUID = 0x180D): ")); success = ble.sendCommandWithIntReply( F("AT+GATTADDSERVICE=UUID=0x180D"), &ServiceId); if (! success) { error(F("Could not add HRM service")); }

/ Add the Heart Rate Measurement characteristic / / Chars ID for Measurement should be 1 / Serial.println(F("Adding the Heart Rate Measurement characteristic (UUID = 0x2A37): ")); success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=2, VALUE=00-40"), &hrmMeasureCharId); if (! success) { error(F("Could not add HRM characteristic")); }

/ Add the Body Sensor Location characteristic / / Chars ID for Body should be 2 / // Serial.println(F("Adding SPO2 Sensor characteristic (UUID = 0x2A29): ")); // success = ble.sendCommandWithIntReply( F("AT+GATTADDCHAR=UUID=0x2901, PROPERTIES=0x10, MIN_LEN=2, MIN_LEN=2, VALUE=00-41"), &spoMeasureCharId); // if (! success) { // error(F("Could not add BSL characteristic")); // }

/ Add the Heart Rate Service to the advertising data (needed for Nordic apps to detect the service) / Serial.print(F("Adding Heart Rate Service UUID to the advertising payload: ")); ble.sendCommandCheckOK( F("AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18") );

/ Reset the device for the new service setting changes to take effect / Serial.print(F("Performing a SW reset (service changes require a reset): ")); ble.reset();

Serial.println();

// Initialize sensor if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed { Serial.println("MAX30102 was not found. Please check wiring/power/solder jumper at MH-ET LIVE MAX30102 board. "); while (1); }

//Setup MAX30102 byte ledBrightness =70; //Options: 0=Off to 255=50mA byte sampleAverage = 2; //Options: 1, 2, 4, 8, 16, 32 byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green //Options: 1 = IR only, 2 = Red + IR on MH-ET LIVE MAX30102 board int sampleRate = 400; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200 int pulseWidth = 411; //Options: 69, 118, 215, 411 int adcRange = 4096; //Options: 2048, 4096, 8192, 16384 // Set up the wanted parameters particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings

}

double avered = 0; double aveir = 0; double sumirrms = 0; double sumredrms = 0; int i = 0; int Num = 100;//calculate SpO2 by this sampling interval

double ESpO2 = 95.0;//initial value of estimated SpO2 double FSpO2 = 0.7; //filter factor for estimated SpO2 double frate = 0.95; // .95 default low pass filter for IR/red LED value to eliminate AC component

void loop() {

uint32_t ir, red , green; double fred, fir; double SpO2 = 0; //raw SpO2 before low pass filtered int idx=0;

ifdef USEFIFO

particleSensor.check(); //Check the sensor, read up to 3 samples

int Ebpm = 60;

while (1) {//do we have new data

ifdef MAX30105

red = particleSensor.getRed(); //Sparkfun's MAX30105 ir = particleSensor.getIR(); //Sparkfun's MAX30105

else

red = particleSensor.getRed(); //why getFOFOIR outputs Red data by

MAX30102 on MH-ET LIVE breakout board ir = particleSensor.getIR(); //why getFIFORed outputs IR data by MAX30102 on MH-ET LIVE breakout board

endif

i++;
fred = (double)red;
fir = (double)ir;
avered = avered * frate + (double)red * (1.0 - frate);//average red

level by low pass filter aveir = aveir frate + (double)ir (1.0 - frate); //average IR level by low pass filter sumredrms += (fred - avered) (fred - avered); //square sum of alternate component of red level sumirrms += (fir - aveir) (fir - aveir);//square sum of alternate component of IR level

 Ebpm = (int) HRM_estimator(fir, aveir); //Ebpm is estimated BPM

    if (ir < FINGER_ON)
       ESpO2 = MINIMUM_SPO2; //indicator for finger detached

if ((i % Num) == 0) {
  double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
   SpO2 = -23.3 * (R - 0.4) + 100;
   ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;
    Serial.print(SpO2);Serial.print(",");Serial.print(ESpO2);

Serial.print(" BPM : "); Serial.print(Ebpm);Serial.print(", R :");Serial.println(R); sumredrms = 0.0; sumirrms = 0.0; i = 0;

  Serial.print("Heart Rate: ");
  Serial.println(Ebpm);
  sendHRData(Ebpm, ESpO2);
  //sendSPOData(ESpO2);
  break;
      }
particleSensor.nextSample(); //We're finished with this sample so move

to next sample

// Serial.println(SpO2); }

endif

}

void sendHRData(int heartRate, int spo2) {

Serial.print("HR : "); Serial.print(heartRate); Serial.print(" SPo2 :"); Serial.println(spo2);

ble.print( F("AT+GATTCHAR=") );
ble.print( hrmMeasureCharId );
ble.print( F(",") );
ble.print(spo2, HEX);
ble.print("-");
ble.println(heartRate, HEX);

if ( !ble.waitForOK() ) {
  Serial.println(F("Failed to get response HeartRate ....."));
}

} // end sendData

double HRM_estimator( double fir , double aveir) {

int CTdiff;

// Heart Rate Monitor by finding falling edge eir = eir firrate + fir (1.0 - firrate); //estimated IR : low pass filtered IR signal

if ( ((eir - aveir) * (eir_prev - aveir) < 0 ) && ((eir - aveir) < 0.0)) { //find zero cross at falling edge crosstime = millis();//system time in msec of falling edge //Serial.print(crosstime); Serial.print(",CRT,"); Serial.println(crosstime_prev);

  //Serial.print("Cross Time :");
  CTdiff = crosstime-crosstime_prev;
  //Serial.println(CTdiff);

//if ( ((crosstime - crosstime_prev ) > (60 * 1000 / MAX_BPS)) &&

((crosstime - crosstime_prev ) < (60 * 1000 / MIN_BPS)) ) {

if ( ( CTdiff > 333 ) && ( CTdiff < 1333 ) ) {
  bpm = 60.0 * 1000.0 / (double)(crosstime - crosstime_prev) ; //get bpm
    // Serial.println("crossed");
  ebpm = ebpm * fbpmrate + (1.0 - fbpmrate) * bpm;//estimated bpm by

low pass filtered

ifdef LED_SOUND_INDICATOR

  if (aveir > FINGER_ON) {
    digitalWrite(LEDPORT, HIGH);
    tone(BLIPSOUND-(100.0-ESpO2)*10.0);//when SpO2=80% BLIPSOUND drops

200Hz to indicate anormaly }

endif

} else {
  //Serial.println("faild to find falling edge");
}
crosstime_prev = crosstime;

} eir_prev = eir; return (ebpm); }

On Mon, Jun 15, 2020 at 3:32 PM lfssp notifications@github.com wrote:

That's a good news @caferrick https://github.com/caferrick . Waiting to see your progress.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644334118, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNKBGG27YFY7APVZD5LRWZZMNANCNFSM4FO6BILA .

soluna1 commented 4 years ago

Hi @caferrick , thank you for the updated code!! I'll let you know asap how it works. Sure it's great!

adeelahmad94 commented 4 years ago

@caferrick Nice job up there! (using MAX30102 + ESP8266) I Eliminated the Bluetooth relevant code, I can see drastic improvement in HR but SpO2 is pretty unstable in for me here (spanning 60-110 randomly)

adeelahmad94 commented 4 years ago

(using MAX30102 + ESP8266) Example_08 for HR+SpO2 is giving my random values, not even being close to accurate, with SpO2 being -999, invalid for the most part

caferrick commented 4 years ago

I noticed with the sensor that I am using my finger has to be fairly stable on the device. Also the 20 seconds or the numbers are all over the place

On Tue, Jun 16, 2020 at 6:04 AM Adeel ahmad notifications@github.com wrote:

@caferrick https://github.com/caferrick Nice job up there! (using MAX30102 + ESP8266) I Eliminated the Bluetooth relevant code, I can see drastic improvement in HR but SpO2 is pretty unstable in for me here (spanning 60-110 randomly)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644667399, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNJFEMMXRCDJN3D4M4DRW47UHANCNFSM4FO6BILA .

adeelahmad94 commented 4 years ago

@caferrick can you share any supporting research/study based on which, you have come up with your algortihm? I'd like to tweak FSpO2 or something there to make SpO2 consistent, a top threshold of 100 is also required.

caferrick commented 4 years ago

I found the original Algorithm on the Web and modified it slightly based on the MAX3012 data sheet. I will try to tweak the code a little more and if you have any luck please let me know.

On Tue, Jun 16, 2020 at 7:34 AM Adeel ahmad notifications@github.com wrote:

@caferrick https://github.com/caferrick can you share any supporting research/study based on which, you have come up with your algortihm? I'd like to tweak FSpO2 or something there to make SpO2 consistent, a top threshold of 100 is also required.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644707421, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNNMQNKZI6SZ6G5C7JTRW5KENANCNFSM4FO6BILA .

adeelahmad94 commented 4 years ago

@caferrick Can you share the literature/link? That'd help me to better understand various other aspects/factors and i may be able to effectively tweak the code.

caferrick commented 4 years ago

here is just on site

https://pdfserv.maximintegrated.com/en/an/AN6409.pdf You can search for spec sheets for MAX30102

On Tue, Jun 16, 2020 at 8:00 AM Adeel ahmad notifications@github.com wrote:

@caferrick https://github.com/caferrick Can you share the literature/link? That'd help me to better understand various other aspects/factors and i may be able to effectively tweak the code.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644718765, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNOE53SYAXQQSIITZ5DRW5NHNANCNFSM4FO6BILA .

adeelahmad94 commented 4 years ago

I see, i have the specs sheet, was trying various MAX30101 algorithms to run on MAX30102 by updating registers mapping, didn't get any success yet.

adeelahmad94 commented 4 years ago

@caferrick which sensor are you using? is it Maxim's 30102 or some other vendor?

caferrick commented 4 years ago

30102 5 connector pins on one side the other just had the LED and two mounting holes

On Tue, Jun 16, 2020 at 11:52 AM Adeel ahmad notifications@github.com wrote:

@caferrick https://github.com/caferrick which sensor are you using? is it Maxim's 30102 or some other vendor?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644851451, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNPMOCV45QXFDYCQ2YTRW6IK3ANCNFSM4FO6BILA .

caferrick commented 4 years ago

this is the unit that i am using HiLetgo MAX30102 Low Power Heart Rate Click Sensor Breakout Board Module for Arduino Pulse Oximetry Solution SpO2 Replace MAX30100 https://www.amazon.com/gp/product/B07QC67KMQ/ref=ppx_yo_dt_b_asin_title_o09_s01?ie=UTF8&psc=1

On Tue, Jun 16, 2020 at 8:26 PM Charles Ferrick caferrick@gmail.com wrote:

30102 5 connector pins on one side the other just had the LED and two mounting holes

On Tue, Jun 16, 2020 at 11:52 AM Adeel ahmad notifications@github.com wrote:

@caferrick https://github.com/caferrick which sensor are you using? is it Maxim's 30102 or some other vendor?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-644851451, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNPMOCV45QXFDYCQ2YTRW6IK3ANCNFSM4FO6BILA .

bbogdanmircea commented 4 years ago

Hello, I just want to confirm the same thing about the examples for the SparkFun library. The heart Rate Plotter and Normal example seems to work nice. But the SPO2 example seems to show very unstable values.

I tried to run different drivers with other algorithms, that I found on instructables and the web, but most algorithms use the interrupt line from the sensor. I found 2 sources that have a very good documentation for the algorithms, I will post them here. I am using the driver on a MAX30102 board that I bought from eBay, the pullups for the I2C signals where wrongly connected to 1.8V so I had to cut the track and solder them to 3.3V. The code is running on a TTGO ESP32 board that has also an OLED display, I hope that I can display the graphic for the heart rate on the display like in the Plotter and make some nice menus for other options, but first I need some reliable algorithms.

bbogdanmircea commented 4 years ago

Hello,

I took the code posted by caferrick and made a sketch out of it. I made some modifications, added some defines for the BT board and also for various debugging on Serial. The signal for the Heart Beat looks ok from what I can see, but the SPO2 calculation seems to be still wrong. This is running on an ESP32 board, but it should also work on an Arduino without problems.

caferrick_max30100.zip

caferrick commented 4 years ago

I wonder why the SPO2 is an issue on my Arduino Feather. My SPO2 seems good. You have wait about 30 seconds for the readings to normalize.

On Thu, Jun 18, 2020 at 10:31 AM bbogdanmircea notifications@github.com wrote:

Hello,

I took the code posted by caferrick and made a sketch out of it. I made some modifications, added some defines for the BT board and also for various debugging on Serial. The signal for the Heart Beat looks ok from what I can see, but the SPO2 calculation seems to be still wrong. This is running on an ESP32 board, but it should also work on an Arduino without problems.

caferrick_max30100.zip https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/files/4799184/caferrick_max30100.zip

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-646056897, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNMAZA55ZJAMPZM725DRXIQM7ANCNFSM4FO6BILA .

adeelahmad94 commented 4 years ago

I just discovered that chinese replica breakout boards has swapped IR and LED registers! that caused me all the trouble (using MH-ET Live Max30102). Here is my implementation of pulse oximeter, a port of MAX30102_by_RF for NodeMCU that works perfectly for Original Maxim or chinese replica sensors.

kiranshashiny commented 4 years ago

I am having the same problem - the number is all over the place 150 to 200, and it cycles thru. Hope the developers upgrade or update the code to newest !

ROdoka commented 3 years ago

I don't think anyone develops at all :o I just started a project with MAX30102 and try to figure out how to use it (and we want to use it on a horse, don't ask ;) ) IOW: I have the same problems like the others here, HR is somewhere between 125 and 250 on an Arduino Uno (since ESP32 doesn't work)

Swadhin21 commented 3 years ago

I am also facing the same problem I.e. the heart rate values are going above 150BPM but the SpO2 value seems to be accurate in the example 8 of spark fun library. So, please anyone can help me if anyone have solved the problem

caferrick commented 3 years ago

Did you try the code I listed a few months ago? I am using an Arduino Feather U32 and I am not having the issue.

On Sat, Apr 17, 2021 at 6:21 AM Swadhin Nagulpelli @.***> wrote:

I am also facing the same problem I.e. the heart rate values are going above 150BPM but the SpO2 value seems to be accurate in the example 8 of spark fun library. So, please anyone can help me if anyone have solved the problem

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-821801499, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNNLYM4VGUWKJJJO353TJFOKPANCNFSM4FO6BILA .

ROdoka commented 3 years ago

actually, I think I didn't try it, I had to find a quick working solution because of deadline reasons and got the sparkfun sensor hub PCB with MAX30101 and MAX32664, this works fine with its lib on ESP32.

after I got the ESP back, I will try your code above.

perohlin commented 3 years ago

hello some times with tuning led brightnes and lowest in 0x10 to 0x20 module work fine but not always. i think this module is very sensetive to distance between finger and chip and config parameters

anuragmehra24 commented 3 years ago

Hi i am also getting issues in accuracy of heart rate. I tried the code shared by caferrick but heart rate is not coming accurate. Even in just sitting positing it is going above 100 using MAX30102 sensor and when i measure with mobile apps which are using mobile flash and mobile camera, the heart rate is coming in normal range.

caferrick commented 3 years ago

I am also using MAX30102 with Arduino Feather I am not having the issue that you are seeing. Do you try the suggestion from perohlin. These sensors can be a bit touchy

On Wed, May 12, 2021 at 2:41 AM anuragmehra24 @.***> wrote:

Hi i am also getting issues in accuracy of heart rate. I tried the code shared by caferrick but heart rate is not coming accurate. Even in just sitting positing it is going above 100 using MAX30102 sensor and when i measure with mobile apps which are using mobile flash and mobile camera, the heart rate is coming in normal range.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-839505776, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNPMNLLM2WJ2NK33IG3TNIPKRANCNFSM4FO6BILA .

capitalfuse commented 3 years ago

I just discovered that chinese replica breakout boards has swapped IR and LED registers! that caused me all the trouble (using MH-ET Live Max30102). Here is my implementation of pulse oximeter, a port of MAX30102_by_RF for NodeMCU that works perfectly for Original Maxim or chinese replica sensors.

I bought Max30102 module at Aliexpress. I tried Spo2 sample code on ESP32, but it doesn't seem to work correctly. Also the presence sample code doesn't (Red LED is disabled to be 0 power in this code). So, I changed the followings;

LED1 < --- > LED2 sense.red < --- > sense.IR

MAX30105.cpp

.....
.....
void MAX30105::setPulseAmplitudeRed(uint8_t amplitude) {
  writeRegister8(_i2caddr, MAX30105_LED2_PULSEAMP, amplitude);
}

void MAX30105::setPulseAmplitudeIR(uint8_t amplitude) {
  writeRegister8(_i2caddr, MAX30105_LED1_PULSEAMP, amplitude);
}
.....
.....
.....
while (toGet > 0)
      {
        sense.head++; //Advance the head of the storage struct
        sense.head %= STORAGE_SIZE; //Wrap condition

        byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long
        uint32_t tempLong;

        //Burst read three bytes - RED
        temp[3] = 0;
        temp[2] = _i2cPort->read();
        temp[1] = _i2cPort->read();
        temp[0] = _i2cPort->read();

        //Convert array to long
        memcpy(&tempLong, temp, sizeof(tempLong));

        tempLong &= 0x3FFFF; //Zero out all but 18 bits

        sense.IR[sense.head] = tempLong; //Store this reading into the sense array

        if (activeLEDs > 1)
        {
          //Burst read three more bytes - IR
          temp[3] = 0;
          temp[2] = _i2cPort->read();
          temp[1] = _i2cPort->read();
          temp[0] = _i2cPort->read();

          //Convert array to long
          memcpy(&tempLong, temp, sizeof(tempLong));

          tempLong &= 0x3FFFF; //Zero out all but 18 bits

          sense.red[sense.head] = tempLong;
        }

Got good results for HR and Spo2 outputs. This is Right???

caferrick commented 3 years ago

Nice!

On Tue, May 18, 2021 at 9:53 AM Takanobu Fuse @.***> wrote:

I just discovered that chinese replica breakout boards has swapped IR and LED registers! that caused me all the trouble (using MH-ET Live Max30102). Here is my implementation of pulse oximeter https://github.com/linkindrew/pulseoximeter_max30102, a port of MAX30102_by_RF https://github.com/aromring/MAX30102_by_RF for NodeMCU that works perfectly for Original Maxim or chinese replica sensors.

I bought Max30102 module at Aliexpress. I tried Spo2 sample code on ESP32, but it doesn't seem to work correctly. Also the presence sample code doesn't (Red LED is disabled to be 0 power in this code). So, I changed the followings;

LED1 < --- > LED2 sense.red < --- > sense.IR

max30105.cpp

..... ..... void MAX30105::setPulseAmplitudeRed(uint8_t amplitude) { writeRegister8(_i2caddr, MAX30105_LED2_PULSEAMP, amplitude); }

void MAX30105::setPulseAmplitudeIR(uint8_t amplitude) { writeRegister8(_i2caddr, MAX30105_LED1_PULSEAMP, amplitude); } ..... ..... ..... while (toGet > 0) { sense.head++; //Advance the head of the storage struct sense.head %= STORAGE_SIZE; //Wrap condition

    byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long
    uint32_t tempLong;

    //Burst read three bytes - RED
    temp[3] = 0;
    temp[2] = _i2cPort->read();
    temp[1] = _i2cPort->read();
    temp[0] = _i2cPort->read();

    //Convert array to long
    memcpy(&tempLong, temp, sizeof(tempLong));

  tempLong &= 0x3FFFF; //Zero out all but 18 bits

    sense.IR[sense.head] = tempLong; //Store this reading into the sense array

    if (activeLEDs > 1)
    {
      //Burst read three more bytes - IR
      temp[3] = 0;
      temp[2] = _i2cPort->read();
      temp[1] = _i2cPort->read();
      temp[0] = _i2cPort->read();

      //Convert array to long
      memcpy(&tempLong, temp, sizeof(tempLong));

    tempLong &= 0x3FFFF; //Zero out all but 18 bits

    sense.red[sense.head] = tempLong;
    }

Got good results for HR and Spo2 outputs. This is Right???

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/17#issuecomment-843191546, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA65HNMNJRO3Y245BHLRUEDTOJWMDANCNFSM4FO6BILA .

AhmedAymanNegmm commented 3 years ago

what am I missing here? what do I have to adjust to get the right numbers? untitled

@talal44 How did you get correct SpO2 values? I am using example 8 and getting very wrong numbers. please help

capitalfuse commented 3 years ago

Get more accurate value after changing to "byte sampleAverage = 1;" in example 8. (NO. OF SAMPLES AVERAGED PER FIFO SAMPLE 000 1 (no averaging)) Its HR value almost matches with HR value in example 5. This is FIFO sampling issue? (I checked it on ESP32+MAX30102)

denisandroid commented 2 years ago

MH-ET LIVE, rev: 3 part: 15, esp8266

I confirm that the Chinese MAX30102 sensor assembled on a black scarf has the correct pinout and 3.3 volt pull-ups, but the red LED and infrared are confused with each other from the factory.

Without altering the libraries to a different order of receiving I2C data, the sensor refuses to give adequate values at all, it's not about sampling or configuration, it's about this feature.

Code of another adapted library (MAX30102_by_RF) bool maxim_max30102_read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led) { uint32_t un_temp; *pun_ir_led=0; *pun_red_led=0; // read 1 byte from registers (values are discarded) maxim_max30102_eventread(REG_INTR_STATUS_1); maxim_max30102_eventread(REG_INTR_STATUS_2); yield(); Wire.beginTransmission(I2C_WRITE_ADDR); Wire.write(REG_FIFO_DATA); Wire.endTransmission(); delayMicroseconds(1); yield(); Wire.beginTransmission(I2C_READ_ADDR); Wire.requestFrom(I2C_READ_ADDR,6); #if defined(IS_EXISTS_SWAP_IR_AND_RED_LED) un_temp = Wire.read(); un_temp <<= 16; *pun_ir_led += un_temp; // IR! un_temp = Wire.read(); un_temp <<= 8; *pun_ir_led += un_temp; un_temp = Wire.read(); *pun_ir_led += un_temp; un_temp = Wire.read(); un_temp <<= 16; *pun_red_led += un_temp; // RED un_temp = Wire.read(); un_temp <<= 8; *pun_red_led += un_temp; un_temp = Wire.read(); *pun_red_led += un_temp; #else un_temp=Wire.read(); un_temp<<=16; *pun_red_led += un_temp; // RED! un_temp=Wire.read(); un_temp<<=8; *pun_red_led += un_temp; un_temp=Wire.read(); *pun_red_led += un_temp; un_temp=Wire.read(); un_temp<<=16; *pun_ir_led += un_temp; // IR! un_temp=Wire.read(); un_temp<<=8; *pun_ir_led += un_temp; un_temp = Wire.read(); *pun_ir_led += un_temp; #endif Wire.endTransmission(); *pun_red_led &= 0x03FFFF; //Mask MSB [23:18] *pun_ir_led &= 0x03FFFF; //Mask MSB [23:18] return true; }
matheuszap commented 2 years ago

Has anyone managed to run max30105 with esp8266? I'm trying but I don't have any results. In the compilation everything happens normally, but when I run it no LED lights up.

VitoDrofenik commented 2 years ago

@matheuszap I am not using the 30105 but the 30102 and on a custom board with a STM32L processor but I think the setup should be quite the same. Did you set the 0x0C, 0x0D and 0x0E registers? Also check that you are not setting bit 7 to 1 in the 0x09 register.

mariagambelli5 commented 2 years ago

@caferrick With my group we trying to use your code for sensor max30102 with an Arduino UNO because we really appreciate your code but we have some issues because we aren't expert in this field. Have you any advice for using this code for an Arduino UNO in order to obtain reasonable values of HR and SpO2? Thanks for helping us!

VitoDrofenik commented 2 years ago

What seems to be your problem? Maybe include some raw red and ir readings (at least 100).