aromring / MAX30102_by_RF

Arduino C code for MAX30102 pulse oximetry sensor (MAXIM Integrated, Inc.)
166 stars 73 forks source link

nrf52832&Max30102 #10

Closed Lashca-Rombot closed 4 years ago

Lashca-Rombot commented 4 years ago
Screen Shot 2020-04-09 at 2 25 51 PM

Hi, i have a custom project using the nrf5283 SoC from Nordic.

I have used the maxim algorithm to test the data i am receiving but the data seems to be incorrect. I have attached a batch of data...from analyzing the data could you possibly tell me where to find my fault. I have also attached the two functions, the reading of fifo and the heart rate algorithm.

Screen Shot 2020-04-09 at 2 24 37 PM

Any help will be much appreciated. [nrf52_max30102.pdf] (https://github.com/aromring/MAX30102_by_RF/files/4456066/nrf52_max30102.pdf)

@aromring

aromring commented 4 years ago

I will be happy to help, but first let me make sure I understand you correctly: You have some other sensor whose documentation I can't even find (according to Nordic, there are only two chips that start with nRF5283 and both are "2.4 GHz RF transceivers" (??)) and some other code - what does this have to do with my code? I did take a look at your output and all I can advise at this point is for you to format the output of the sensor's RED and IR data into three tab-separated columns, like this:

sample_numberRED_valueIR_value

so that you can copy the three columns into Excel and plot RED and IR values as functions of sample_number. If your sensor works like MAX30102, then you should see a plot like this: https://github.com/aromring/MAX30102_by_RF/blob/master/ExpectedGoodQualitySignals.png If the plot of both signals is good, then your sensor is OK and your mysterious problem ("mysterious" because all you revealed was "the data seems to be incorrect" ) is in your code. If the plots are bad, then the reason is in the sensor or its connections.

Lashca-Rombot commented 4 years ago

Hi Aromring, thank you for your response and your willingness to help me. I really appreciate it.

Just to clear up a few things.

  1. I am using the MAX30102 sensor.

  2. I am using the nrf52832 MCU from Nordic Semiconductor( I am not using Arduino)

  3. The project is developed on a custom pcb

  4. I have attached a pdf from the data I have collected but I will do as you say and tabulate the data in a excell and send it back to you very soon.

  5. One of my concerns as seen in the pdf i sent....my ' i ' values in the for loop skip iterations. is that normal?

Looking forward to hearing from you. Regards, Lashca Pieterse.


From: Molecular Descriptor notifications@github.com Sent: Friday, April 10, 2020 8:52:15 PM To: aromring/MAX30102_by_RF MAX30102_by_RF@noreply.github.com Cc: Lashca Pieterse lashca@rombot.com; Author author@noreply.github.com Subject: Re: [aromring/MAX30102_by_RF] nrf52832&Max30102 (#10)

I will be happy to help, but first let me make sure I understand you correctly: You have some other sensor whose documentation I can't even find (according to Nordic, there are only two chips that start with nRF5283https://infocenter.nordicsemi.com/index.jsp?topic=/com.nordic.infocenter.nrf52832.ps.v1.1/uicr.html and both are "2.4 GHz RF transceivers" (??)) and some other code - what does this have to do with my code? I did take a look at your output and all I can advise at this point is for you to format the output of the sensor's RED and IR data into three tab-separated columns, like this:

sample_numberRED_valueIR_value

so that you can copy the three columns into Excel and plot RED and IR values as functions of sample_number. If your sensor works like MAX30102, then you should see a plot like this: https://github.com/aromring/MAX30102_by_RF/blob/master/ExpectedGoodQualitySignals.png If the plot of both signals is good, then your sensor is OK and your mysterious problem ("mysterious" because all you revealed was "the data seems to be incorrect" ) is in your code. If the plots are bad, then the reason is in the sensor or its connections.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/aromring/MAX30102_by_RF/issues/10#issuecomment-612168118, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ALCTEWXNUDIXPPEMWDY42NDRL5TF7ANCNFSM4MEWA5BQ.

aromring commented 4 years ago

Hi Lashca, Regarding point 5: No, it's not normal to have skipped values in the 'for' loop. Clearly, the culprit is either your read_fifo() routine or NRF_LOG_INFO(). The former is more likely. I can't help you when you send me incomplete data, I'll need values for all 'i'. I know for a fact that the MAX30102 does send all 100 samples intact, so your best option is to get the raw data directly from the sensor. It's very easy to do in my code 'RD117_ARDUINO.ino'. For details, please open the README file here: https://github.com/aromring/MAX30102_by_RF/blob/master/README.md scroll down to HOW TO REPORT BUGS section and follow instructions therein.

Now, regarding the subject of this whole matter, this is the fourth exchanged message and I still don't know what the problem exactly is! Would you care to clearly explain it? What do you mean by "the data seems to be incorrect"?

Lashca-Rombot commented 4 years ago

Hi Aromring, So the main issue i have is that i am not getting valid heart rate and spo2 values from the

"heart_rate_and_oxygen_saturation()" function.

With this being said, i am searching for my fault from the base which is why i am looking at the raw data first to see if my data is correct. Below i have attached a pdf that shows my data array when reading from the fifo. Is it normal for my dataArray[0] & dataArray[3] to always be empty? and does my ir&red data array seem correct?

I do agree with you that my reading fifo routine might be the problem. I think this is what leads my "heart_rate_and_oxygen_saturation()" to invalid output values.

Thanks. Regards, Lashca Pieterse.


From: Molecular Descriptor notifications@github.com Sent: Sunday, April 12, 2020 9:10 PM To: aromring/MAX30102_by_RF MAX30102_by_RF@noreply.github.com Cc: Lashca Pieterse lashca@rombot.com; Author author@noreply.github.com Subject: Re: [aromring/MAX30102_by_RF] nrf52832&Max30102 (#10)

Hi Lashca, Regarding point 5: No, it's not normal to have skipped values in the 'for' loop. Clearly, the culprit is either your read_fifo() routine or NRF_LOG_INFO(). The former is more likely. I can't help you when you send me incomplete data, I'll need values for all 'i'. I know for a fact that the MAX30102 does send all 100 samples intact, so your best option is to get the raw data directly from the sensor. It's very easy to do in my code 'RD117_ARDUINO.ino'. For details, please open the README file here: https://github.com/aromring/MAX30102_by_RF/blob/master/README.md scroll down to HOW TO REPORT BUGS section and follow instructions therein.

Now, regarding the subject of this whole matter, this is the fourth exchanged message and I still don't know what the problem exactly is! Would you care to clearly explain it? What do you mean by "the data seems to be incorrect"?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/aromring/MAX30102_by_RF/issues/10#issuecomment-612662384, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ALCTEWT6QAXYHQVKBK3MO5TRMIG3RANCNFSM4MEWA5BQ.

aromring commented 4 years ago

Hi Lashca, I'm sorry, but your answer came without an attachment.

Lashca-Rombot commented 4 years ago

dataArray_of_MAX30102.pdf

sorry about that...here it is. @aromring

Lashca-Rombot commented 4 years ago

pun&aun_buffer_data.pdf iv noticed that my output data (uint32_t pun_red_led, uint32_t pun_ir_led) from reading fifo() differs from the aun_buffer data that i pass into the reading fifo(). see attached pdf please. @aromring

Lashca-Rombot commented 4 years ago

This is my code...

void` read_fifo(uint32_t *pun_red_led, uint32_t *pun_ir_led)
{

     *pun_red_led=0;
     *pun_ir_led=0;
      uint8_t clearINT1;
      uint8_t clearINT2;
      uint8_t dataArray[6];
      uint32_t temp_32=0;

      ret_code_t err_code;

      err_code = rb_twi_read_buf(MAX30102_ADDRESS, INT_STATUS_1, &clearINT1, sizeof(clearINT1));
      err_code = rb_twi_read_buf(MAX30102_ADDRESS, INT_STATUS_2, &clearINT2, sizeof(clearINT2));

      err_code = rb_twi_read_buf(MAX30102_ADDRESS, FIFO_DATA, dataArray, sizeof(dataArray));
      APP_ERROR_CHECK(err_code);

      NRF_LOG_INFO("dataArray[0]: %d \r\n",dataArray[0]);
      NRF_LOG_INFO("dataArray[1]: %d \r\n",dataArray[1]);
      NRF_LOG_INFO("dataArray[2]: %d \r\n",dataArray[2]);
      NRF_LOG_INFO("dataArray[3]: %d \r\n",dataArray[3]);
      NRF_LOG_INFO("dataArray[4]: %d \r\n",dataArray[4]);
      NRF_LOG_INFO("dataArray[5]: %d \r\n",dataArray[5]);

      temp_32|=dataArray[0];
      temp_32<<=8;

      temp_32|=dataArray[1];
      temp_32<<=8;

      temp_32|=dataArray[2];

      *pun_red_led = temp_32;
      NRF_LOG_INFO("*pun_red_led: %d",*pun_red_led);

      *pun_red_led&=0x0003FFFF;

      temp_32=0;

      temp_32|=dataArray[3];

      temp_32<<=8;
      temp_32|=dataArray[4];

      temp_32<<=8;
      temp_32|=dataArray[5];

      *pun_ir_led = temp_32;

      *pun_ir_led&=0x0003FFFF;

      NRF_LOG_INFO("*pun_ir_led: %d",*pun_ir_led);

}
void hr_algo()
{

uint32_t aun_ir_buffer[BUFFER_SIZE];
uint32_t aun_red_buffer[BUFFER_SIZE];
int32_t pn_spo2; //SPO2
int8_t pch_spo2_valid; // indication to show that spo2 is valid
int32_t pn_heart_rate; // heart rate value
int8_t pch_hr_valid; // indication to show that heart rate is valid
int32_t i;

//buffer length of BUFFER_SIZE stores ST seconds of samples running at FS sps
//read BUFFER_SIZE samples, and determine the signal range
for(i=0;i<BUFFER_SIZE;i++)
{
read_fifo((aun_red_buffer+i),(aun_ir_buffer+i));
NRF_LOG_INFO("i: %d\r\n",i);
NRF_LOG_INFO("aun_red_buffer: %d\r\n",aun_red_buffer);
NRF_LOG_INFO("aun_ir_buffer: %d\r\n",aun_ir_buffer);
NRF_LOG_FLUSH();
}

maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &pn_spo2, &pch_spo2_valid, &pn_heart_rate, &pch_hr_valid);

//if(pch_spo2_valid && pch_hr_valid)
//{

NRF_LOG_INFO("SP02: %d",pn_spo2);
NRF_LOG_INFO("Heart rate: %d",pn_heart_rate);

}

@aromring

aromring commented 4 years ago

All right, attachments came in, but please do help me help you. Do you honestly expect me to manually type hundreds of numbers from your PDF into Excel, one by one? I am going an extra mile to help with a problem that has nothing to do with my code, sacrificing my very busy time. At least have a courtesy to honor my polite request from previous message: "(...) format the output of the sensor's RED and IR data into three tab-separated columns, like this: sample_number RED_value IR_value so that you can copy the three columns into Excel and plot RED and IR values as functions of sample_number." Comment out unnecessary NRF_LOG_INFO() calls, unnecessary strings like "dataArray[n]", etc. However you do it, if you still want my help then you make and send me images of the following two plots:

1) Raw RED signal as a function of sample number 2) Raw IR signal as a function of sample number

Your code does not help much, either, since I have no idea what rb_twi_read_buf() is or what it does. Consequently, I don't have the foggiest idea what "dataArray" is supposed to represent. Ah, one more thing I've noticed in your code. In the following calls

NRF_LOG_INFO("aun_red_buffer: %d\r\n",aun_red_buffer); NRF_LOG_INFO("aun_ir_buffer: %d\r\n",aun_ir_buffer);

you print values of the pointers to aun_red_buffer and aun_ir_buffer arrays, respectively, not the values in these arrays. Fix this as follows:

NRF_LOG_INFO("aun_red_buffer: %d\r\n",aun_red_buffer[i]); NRF_LOG_INFO("aun_ir_buffer: %d\r\n",aun_ir_buffer[i]);

Or better change the whole output in hr_algo() like this:

for(i=0;i<BUFFER_SIZE;i++) { read_fifo((aun_red_buffer+i),(aun_ir_buffer+i)); NRF_LOG_INFO("%d\t%d\t%d\r\n",i,aun_red_buffer[i],aun_ir_buffer[i]); NRF_LOG_FLUSH(); }

Comment out every other instance of NRF_LOG_INFO() in the entire code

aromring commented 4 years ago

It's also possible that all that printing inside read_fifo() slows this routine down to the point of missing a lot of samples. What is APP_ERROR_CHECK(err_code)?

Lashca-Rombot commented 4 years ago

Thanks @aromring , you were right...the logs were slowing down the routine. I will find another method to get the data with sampling and then send it through.

Lashca-Rombot commented 4 years ago

RED_IR_DATA.zip Hi @aromring i have collected the data you have requested. Can you verify that my sensor is working correctly and that the values i am receiving from the MAX30102 are valid. Thank you.

aromring commented 4 years ago

Thank you for the data. Well, the first anomaly that is immediately obvious are the negative numbers in RED buffer of active signal. How is that even possible? All the related variables in your code are uint32_t! Have you changed your code? Besides that, your active signals look really strange: image High frequency noise obscures the real signal. The "noise" is very regular: odd numbered samples are down with respect to even numbered ones. I wonder if this is due to some artifact in your code.

Lashca-Rombot commented 4 years ago

Hi @aromring thanks for the insight. iv noticed on your "HOW TO REPORT BUGS" point 3: https://reedpaper.wordpress.com/2018/08/22/pulse-oximeter-max30100-max30102-how-to-fix-wrong-board/

My board is from China, do you think this could be my issue?

Lastly, i did change my code a bit to send the buffer data over BLE....i will make a point of it to change my int32 to uint32.

aromring commented 4 years ago

Yup, cheap clone board might very well be the problem. I am old enough to realize that time is much more valuable than money. Although the original board from Maxim may be a bit more expensive, it may also save a lot of lost time and aggravation afforded by poorly designed clones.