Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 - Gap in raw data #26

Open
christian-nils opened this issue Jun 2, 2023 · 5 comments
Open

ESP32 - Gap in raw data #26

christian-nils opened this issue Jun 2, 2023 · 5 comments

Comments

@christian-nils
Copy link

Hi,

Thanks for this library. I bought the oximeter sensor from Sparkfun (https://www.sparkfun.com/products/15219). I am trying to read the IR led count data but there are some periodic gaps in the data. Here is a short excerpt of the Serial monitor: https://pastebin.com/85jETjyG

Here is a graph showing periodic plateaus in the data (which are typically just gaps in data as the ESP32 is just polling the same value until a new value is available).

Screenshot from 2023-06-02 21-07-59

I have the same behaviour when reading the data only on interrupt and when the data ready flag is set to 1 (I am using ESP-IDF for that test):

image

The code I used when using the Arduino library is the following:

#include <SparkFun_Bio_Sensor_Hub_Library.h>
#include <Wire.h>

// No other Address options.
#define DEF_ADDR 0x55

// Reset pin, MFIO pin
const int resPin = 26;
const int mfioPin = 25;

//#define SDA 21
//#define SCL 22

//#define SDA 27
//#define SCL 14

// Possible widths: 69, 118, 215, 411us
int width = 69; 
// Possible samples: 50, 100, 200, 400, 800, 1000, 1600, 3200 samples/second
// Not every sample amount is possible with every width; check out our hookup
// guide for more information.
int samples = 1600; 
int pulseWidthVal;
int sampleVal;

// Takes address, reset pin, and MFIO pin.
SparkFun_Bio_Sensor_Hub bioHub(resPin, mfioPin); 

bioData body; 

// following data: 
// body.irLed      - Infrared LED counts. 
// body.redLed     - Red LED counts. 
// body.heartrate  - Heartrate
// body.confidence - Confidence in the heartrate value
// body.oxygen     - Blood oxygen level
// body.status     - Has a finger been sensed?

void setup(){

  Serial.begin(115200);

  Wire.begin();
  int result = bioHub.begin();

  int error = bioHub.configSensor(); // Configure Sensor
  
  error = bioHub.setPulseWidth(width);
  error = bioHub.setSampleRate(samples);

  delay(1000);

}

void loop(){

    // Information from the readSensor function will be saved to our "body"
    // variable.  
    body = bioHub.readSensor();
    Serial.println(body.irLed); 
//    Serial.print("  ");
//    Serial.println(body.redLed); 
    // Slow it down or your heart rate will go up trying to keep up
    // with the flow of numbers
}

Any idea why I get those periodic gap in the raw data?

Thanks in advance!

@edspark
Copy link
Collaborator

edspark commented Jun 5, 2023

Thanks for the issue, it's on my list and I'll get to this issue if not today, then tomorrow!

@christian-nils
Copy link
Author

christian-nils commented Jun 5, 2023

Thank you for looking into that.
From my long investigation during the last days, I can see the following points (in the case you use MFIO as interrupt line):

  • It seems that the data are transmitted every 0.125s for some reason.
  • When the configured sampling frequency is increased the more data point you find in each chunk.
  • If you use 1600Hz as sampling rate, you need to make sure to set the I2C bus frequency to 400kHz
  • To retrieve raw data, you need to make sure the Wrist algo and the AGC algo are disabled
  • When using the wrist algo and AGC algo, the sampling rate of the raw data is always 100Hz (25Hz when no finger detected)
  • The structure of the data is interesting, the 10-12 bytes from the payload seem to correspond to a sample counter (I cannot find any reference of such counter in any datasheet as those bytes should be the LED4 counts). This is true for both configurations; sensor only or sensor + algo (one_mode, did not check the other configurations):

MicrosoftTeams-image (16)

  • It seems that by default there is some averaging done on the data points as I retrieve always half of the number of points for the configured sampling frequency (I can see from the MAX30101 datasheet that this is the default anyway, I will try to decrease that number and see if it changes anything). EDIT: changing the sample averaging value in the MAX30101 register 0x08, makes the trick. I could reach 1600 samples/s but it is a bit unstable. For the other configurations, no issues (e.g. set sampling frequency 1600Hz and sampling average of 32 gives me raw data at a rate of 50Hz). These are the functions I used for updating the sample averaging:
  // This function modifies the sample averaging of the MAX30101.
  // Default: 2 sample averaging.
  // Register: 0x08, bits [7:5]
  // SMP_AVE[2:0] - NO. OF SAMPLES AVERAGED PER FIFO SAMPLE
  //  000     -    1 (no averaging)
  //  001     -    2
  //  010     -    4
  //  011     -    8
  //  100     -    16
  //  101     -    32
  uint8_t Max32664Hub::set_sample_averaging(uint8_t sample_averaging)
  {
    uint8_t bits;
    uint8_t reg_val;

    // Make sure the correct pulse width is selected.
    if (sample_averaging <= 5)
    {
      bits = sample_averaging << 5;
    }
    else
    {
      return INCORR_PARAM;
    }

    // Get current register value so that nothing is overwritten.
    reg_val = read_register_max30101(MAX30101_FIFO_CONFIG_REGISTER);
    reg_val &= SAMP_AVG_MASK;                                        // Mask bits to change.
    reg_val |= bits;                                                 // Add bits
    write_register_max30101(MAX30101_FIFO_CONFIG_REGISTER, reg_val); // Write Register

    return SUCCESS;
  }

  // This function reads the register (0x08), bits [7:5] from the
  // MAX30101 Sensor. It returns the sample averaging setting.
  uint8_t Max32664Hub::read_sample_averaging()
  {
    uint8_t reg_val;

    reg_val = read_register_max30101(MAX30101_FIFO_CONFIG_REGISTER);
    reg_val &= READ_SAMP_AVG_MASK;

    return reg_val >> 5;
  }

Anyway, maybe some stuff is wrong (or everything), but I thought that it was worth mentioning those results if it helps. I will use the "counter" from the payload to sync the data.

@edspark
Copy link
Collaborator

edspark commented Jun 12, 2023

Thanks for the follow up, this may help quite a bit. This library has a few open issues that I'd like to tackle simultaneously as they have a common thread with the ESP32 platform. Unfortunately I got bludgeoned with illness last week and I'll need to do some catch up on my current projects before I get to this. I expect I'll have some time midweek. Talk to you soon.

@christian-nils
Copy link
Author

Thanks for following up :-) I hope you are feeling fine again, take care and good luck with all the catching-up! Let me know if I can help in any ways!

@edspark
Copy link
Collaborator

edspark commented Jun 15, 2023

I suspect it has something to do with the "CMD_DELAY" being significantly reduced in later firmware releases but I still need to test with a board that has the latest firmware which I do not have. This is still ongoing, thank you for your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants