From ee87b1892b4669bfc0b8eebf7a41045f17ef2d4f Mon Sep 17 00:00:00 2001 From: Chris Idema Date: Thu, 10 Dec 2020 16:25:02 +0100 Subject: [PATCH 1/2] -this fix seems to work --- src/SparkFun_Bio_Sensor_Hub_Library.cpp | 7 +++++-- src/SparkFun_Bio_Sensor_Hub_Library.h | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/SparkFun_Bio_Sensor_Hub_Library.cpp b/src/SparkFun_Bio_Sensor_Hub_Library.cpp index cae0684..7b6f9ac 100644 --- a/src/SparkFun_Bio_Sensor_Hub_Library.cpp +++ b/src/SparkFun_Bio_Sensor_Hub_Library.cpp @@ -42,10 +42,13 @@ uint8_t SparkFun_Bio_Sensor_Hub::begin( TwoWire &wirePort ) { _i2cPort = &wirePort; // _i2cPort->begin(); A call to Wire.begin should occur in sketch // to avoid multiple begins with other sketches. + + digitalWrite(_resetPin, HIGH); + delay(30); digitalWrite(_mfioPin, HIGH); digitalWrite(_resetPin, LOW); - delay(10); + delay(30); digitalWrite(_resetPin, HIGH); delay(1000); pinMode(_mfioPin, INPUT_PULLUP); // To be used as an interrupt later @@ -1327,7 +1330,7 @@ uint8_t* SparkFun_Bio_Sensor_Hub::readFillArray(uint8_t _familyByte, uint8_t _in _i2cPort->requestFrom(_address, static_cast(arraySize + sizeof(statusByte))); statusByte = _i2cPort->read(); // Got it - if( statusByte ){// SUCCESS (0x00) + if( (statusByte!=0) && (statusByte!=255) ){// SUCCESS (0x00) for(uint8_t i = 0; i < arraySize; i++){ array[i] = 0; } diff --git a/src/SparkFun_Bio_Sensor_Hub_Library.h b/src/SparkFun_Bio_Sensor_Hub_Library.h index 8cf098f..e2af8d2 100644 --- a/src/SparkFun_Bio_Sensor_Hub_Library.h +++ b/src/SparkFun_Bio_Sensor_Hub_Library.h @@ -23,8 +23,8 @@ #define ADC_MASK 0x9F #define READ_ADC_MASK 0x60 -#define ENABLE_CMD_DELAY 45 // Milliseconds -#define CMD_DELAY 6 // Milliseconds +#define ENABLE_CMD_DELAY 60 // Milliseconds +#define CMD_DELAY 20 // Milliseconds #define MAXFAST_ARRAY_SIZE 6 // Number of bytes.... #define MAXFAST_EXTENDED_DATA 5 #define MAX30101_LED_ARRAY 12 // 4 values of 24 bit (3 byte) LED values From 1c887251a90540becd9126d557c89a620ae3708b Mon Sep 17 00:00:00 2001 From: Chris Idema Date: Thu, 10 Dec 2020 18:40:19 +0100 Subject: [PATCH 2/2] -no more fifo delay issues and no more "unknown error" code --- .../Example5_fast_print.ino | 175 ++++++++++++++++++ src/SparkFun_Bio_Sensor_Hub_Library.cpp | 80 ++++++-- src/SparkFun_Bio_Sensor_Hub_Library.h | 7 +- 3 files changed, 241 insertions(+), 21 deletions(-) create mode 100644 examples/Example5_fast_print/Example5_fast_print.ino diff --git a/examples/Example5_fast_print/Example5_fast_print.ino b/examples/Example5_fast_print/Example5_fast_print.ino new file mode 100644 index 0000000..51ca2c5 --- /dev/null +++ b/examples/Example5_fast_print/Example5_fast_print.ino @@ -0,0 +1,175 @@ +/* + This example displays a more manual method of adjusting the way in which the + MAX30101 gathers data. Specifically we'll look at how to modify the pulse + length of the LEDs within the MAX30101 which impacts the number of samples + that can be gathered, so we'll adjust this value as well. In addition we + gather additional data from the bioData type: LED samples. This data gives + the number of samples gathered by the MAX30101 for both the red and IR LEDs. + As a side note you can also choose MODE_ONE and MODE_TWO for configSensorBpm + as well. + A summary of the hardware connections are as follows: + SDA -> SDA + SCL -> SCL + RESET -> PIN 4 + MFIO -> PIN 5 + + Author: Elias Santistevan + Date: 8/2019 + SparkFun Electronics + + If you run into an error code check the following table to help diagnose your + problem: + 1 = Unavailable Command + 2 = Unavailable Function + 3 = Data Format Error + 4 = Input Value Error + 5 = Try Again + 255 = Error Unknown +*/ + +#include +#include + +// Reset pin, MFIO pin +int resPin = 32; +int mfioPin = 5; + +// Possible widths: 69, 118, 215, 411us +int width = 411; +// 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 = 100; +int pulseWidthVal; +int sampleVal; + +// Takes address, reset pin, and MFIO pin. +SparkFun_Bio_Sensor_Hub bioHub(resPin, mfioPin); + +bioData body; +// ^^^^^^^^^ +// What's this!? This is a type (like "int", "byte", "long") unique to the SparkFun +// Pulse Oximeter and Heart Rate Monitor. Unlike those other types it holds +// specific information on the LED count values of the sensor and ALSO the +// biometric data: heart rate, oxygen levels, and confidence. "bioLedData" is +// actually a specific kind of type, known as a "struct". I chose the name +// "body" but you could use another variable name like "blood", "readings", +// "ledBody" or whatever. Using the variable in the following way gives the +// 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); + + #ifdef ARDUINO_ESP32_DEV + delay(2000);//delay for printing after reset + Serial.println("ARDUINO_ESP32_DEV"); + #endif + + Wire.begin(21,22,400000); + int result = bioHub.begin(); + if (result == 0) // Zero errors! + Serial.println("Sensor started!"); + + Serial.println("Configuring Sensor...."); + int error = bioHub.configSensorBpm(MODE_ONE); // Configure Sensor and BPM mode , MODE_TWO also available + if (error == 0){// Zero errors. + Serial.println("Sensor configured."); + } + else { + Serial.println("Error configuring sensor."); + Serial.print("Error: "); + Serial.println(error); + } + + // Set pulse width. + error = bioHub.setPulseWidth(width); + if (error == 0){// Zero errors. + Serial.println("Pulse Width Set."); + } + else { + Serial.println("Could not set Pulse Width."); + Serial.print("Error: "); + Serial.println(error); + } + + // Check that the pulse width was set. + pulseWidthVal = bioHub.readPulseWidth(); + Serial.print("Pulse Width: "); + Serial.println(pulseWidthVal); + + // Set sample rate per second. Remember that not every sample rate is + // available with every pulse width. Check hookup guide for more information. + error = bioHub.setSampleRate(samples); + if (error == 0){// Zero errors. + Serial.println("Sample Rate Set."); + } + else { + Serial.println("Could not set Sample Rate!"); + Serial.print("Error: "); + Serial.println(error); + } + + // bioHub.set_report_period(100); + + + // Check sample rate. + sampleVal = bioHub.readSampleRate(); + Serial.print("Sample rate is set to: "); + Serial.println(sampleVal); + + // Data lags a bit behind the sensor, if you're finger is on the sensor when + // it's being configured this delay will give some time for the data to catch + // up. +// Serial.println("Loading up the buffer with data...."); +// delay(4000); + +} + +void loop(){ + + uint16_t t = millis(); + static uint16_t t_old = 0; + int16_t t_diff; + + // Information from the readSensor function will be saved to our "body" + // variable. + + uint8_t samples = bioHub.numSamplesOutFifo(); + + //read all samples in fifo and use most recent one + while(samples){ + body = bioHub.readSensorBpm(); + samples--; + } + + + t_diff = t - t_old; + if(t_diff>=500){ + t_old += 500; + +// Serial.print(samples); +// Serial.print(","); + Serial.print(body.heartRate); + Serial.print(","); + Serial.println(body.oxygen); + + samples = bioHub.numSamplesOutFifo(); + } + + //clear fifo before delay + while(samples){ + body = bioHub.readSensorBpm(); + samples--; + } + + + + delay(10); +} diff --git a/src/SparkFun_Bio_Sensor_Hub_Library.cpp b/src/SparkFun_Bio_Sensor_Hub_Library.cpp index 7b6f9ac..2f518ce 100644 --- a/src/SparkFun_Bio_Sensor_Hub_Library.cpp +++ b/src/SparkFun_Bio_Sensor_Hub_Library.cpp @@ -88,7 +88,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::beginBootloader( TwoWire &wirePort ) { // The following function checks the status of the FIFO. uint8_t SparkFun_Bio_Sensor_Hub::readSensorHubStatus(){ - uint8_t status = readByte(0x00, 0x00); // Just family and index byte. + uint8_t status = readByte_fast(0x00, 0x00); // Just family and index byte. return status; // Will return 0x00 } @@ -710,7 +710,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::setFifoThreshold(uint8_t intThresh) { // This function returns the number of samples available in the FIFO. uint8_t SparkFun_Bio_Sensor_Hub::numSamplesOutFifo() { - uint8_t sampAvail = readByte(READ_DATA_OUTPUT, NUM_SAMPLES); + uint8_t sampAvail = readByte_fast(READ_DATA_OUTPUT, NUM_SAMPLES); return sampAvail; } @@ -1043,7 +1043,7 @@ bool SparkFun_Bio_Sensor_Hub::eraseFlash() { _i2cPort->write(BOOTLOADER_FLASH); _i2cPort->write(ERASE_FLASH); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(1)); uint8_t statusByte = _i2cPort->read(); @@ -1062,7 +1062,7 @@ version SparkFun_Bio_Sensor_Hub::readBootloaderVers(){ _i2cPort->write(BOOTLOADER_INFO); _i2cPort->write(BOOTLOADER_VERS); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(4)); uint8_t statusByte = _i2cPort->read(); @@ -1089,7 +1089,7 @@ version SparkFun_Bio_Sensor_Hub::readSensorHubVersion(){ _i2cPort->write(IDENTITY); _i2cPort->write(READ_SENSOR_HUB_VERS); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(4)); uint8_t statusByte = _i2cPort->read(); @@ -1116,7 +1116,7 @@ version SparkFun_Bio_Sensor_Hub::readAlgorithmVersion(){ _i2cPort->write(IDENTITY); _i2cPort->write(READ_ALGO_VERS); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(4)); uint8_t statusByte = _i2cPort->read(); @@ -1148,7 +1148,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::enableWrite(uint8_t _familyByte, uint8_t _index _i2cPort->write(_indexByte); _i2cPort->write(_enableByte); _i2cPort->endTransmission(); - delay(ENABLE_CMD_DELAY); + delayMicroseconds(ENABLE_CMD_DELAY*1000); // Status Byte, success or no? 0x00 is a successful transmit _i2cPort->requestFrom(_address, static_cast(1)); @@ -1171,7 +1171,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::writeByte(uint8_t _familyByte, uint8_t _indexBy _i2cPort->write(_indexByte); _i2cPort->write(_writeByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); // Status Byte, success or no? 0x00 is a successful transmit _i2cPort->requestFrom(_address, static_cast(1)); @@ -1197,7 +1197,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::writeByte(uint8_t _familyByte, uint8_t _indexBy _i2cPort->write((_val >> 8)); // MSB _i2cPort->write(_val); // LSB _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); // Status Byte, success or no? 0x00 is a successful transmit _i2cPort->requestFrom(_address, static_cast(1)); @@ -1220,7 +1220,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::writeByte(uint8_t _familyByte, uint8_t _indexBy _i2cPort->write(_writeByte); _i2cPort->write(_writeVal); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); // Status Byte, 0x00 is a successful transmit. _i2cPort->requestFrom(_address, static_cast(1)); @@ -1250,7 +1250,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::writeLongBytes(uint8_t _familyByte, uint8_t _in } _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); // Status Byte, 0x00 is a successful transmit. _i2cPort->requestFrom(_address, static_cast(1)); @@ -1263,7 +1263,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::writeLongBytes(uint8_t _familyByte, uint8_t _in // requests. It starts a request by writing the family byte an index byte, and // then delays 60 microseconds, during which the MAX32664 retrieves the requested // information. An I-squared-C request is then issued, and the information is read. -uint8_t SparkFun_Bio_Sensor_Hub::readByte(uint8_t _familyByte, uint8_t _indexByte ) +uint8_t SparkFun_Bio_Sensor_Hub::readByte(uint8_t _familyByte, uint8_t _indexByte) { uint8_t returnByte; @@ -1273,7 +1273,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::readByte(uint8_t _familyByte, uint8_t _indexByt _i2cPort->write(_familyByte); _i2cPort->write(_indexByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(sizeof(returnByte) + sizeof(statusByte))); statusByte = _i2cPort->read(); @@ -1282,11 +1282,52 @@ uint8_t SparkFun_Bio_Sensor_Hub::readByte(uint8_t _familyByte, uint8_t _indexByt returnByte = _i2cPort->read(); return returnByte; // If good then return the actual byte. +} + +uint8_t SparkFun_Bio_Sensor_Hub::readByte_fast(uint8_t _familyByte, uint8_t _indexByte) +{ + + uint8_t returnByte; + uint8_t statusByte; + + _i2cPort->beginTransmission(_address); + _i2cPort->write(_familyByte); + _i2cPort->write(_indexByte); + _i2cPort->endTransmission(); + //delayMicroseconds(CMD_DELAY*1000); + + _i2cPort->requestFrom(_address, static_cast(sizeof(returnByte) + sizeof(statusByte))); + statusByte = _i2cPort->read(); + if( statusByte )// SUCCESS (0x00) - how do I know its + return statusByte; // Return the error, see: READ_STATUS_BYTE_VALUE + + returnByte = _i2cPort->read(); + return returnByte; // If good then return the actual byte. +} +uint8_t SparkFun_Bio_Sensor_Hub::readByte_fast(uint8_t _familyByte, uint8_t _indexByte, uint8_t _writeByte) +{ + uint8_t returnByte; + uint8_t statusByte; + + _i2cPort->beginTransmission(_address); + _i2cPort->write(_familyByte); + _i2cPort->write(_indexByte); + _i2cPort->write(_writeByte); + _i2cPort->endTransmission(); + //delayMicroseconds(CMD_DELAY*1000); + + _i2cPort->requestFrom(_address, static_cast(sizeof(returnByte) + sizeof(statusByte))); + statusByte = _i2cPort->read(); + if( statusByte )// SUCCESS (0x00) - how do I know its + return statusByte; // Return the error, see: READ_STATUS_BYTE_VALUE + returnByte = _i2cPort->read(); + return returnByte; // If good then return the actual byte. } + // This function is exactly as the one above except it accepts also receives a // Write Byte as a paramter. It starts a request by writing the family byte, index byte, and // write byte to the MAX32664 and then delays 60 microseconds, during which @@ -1304,7 +1345,7 @@ uint8_t SparkFun_Bio_Sensor_Hub::readByte(uint8_t _familyByte, uint8_t _indexBy _i2cPort->write(_indexByte); _i2cPort->write(_writeByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, sizeof(returnByte) + sizeof(statusByte)); statusByte = _i2cPort->read(); @@ -1326,11 +1367,12 @@ uint8_t* SparkFun_Bio_Sensor_Hub::readFillArray(uint8_t _familyByte, uint8_t _in _i2cPort->write(_familyByte); _i2cPort->write(_indexByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + //delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(arraySize + sizeof(statusByte))); statusByte = _i2cPort->read(); // Got it - if( (statusByte!=0) && (statusByte!=255) ){// SUCCESS (0x00) + //if( (statusByte!=0) && (statusByte!=255) ){// SUCCESS (0x00) + if( statusByte!=0 ){// SUCCESS (0x00) for(uint8_t i = 0; i < arraySize; i++){ array[i] = 0; } @@ -1361,7 +1403,7 @@ uint16_t SparkFun_Bio_Sensor_Hub::readIntByte(uint8_t _familyByte, uint8_t _inde _i2cPort->write(_indexByte); _i2cPort->write(_writeByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(sizeof(returnByte) + sizeof(statusByte))); statusByte = _i2cPort->read(); @@ -1393,7 +1435,7 @@ uint32_t SparkFun_Bio_Sensor_Hub::readLongByte(uint8_t _familyByte, uint8_t _ind _i2cPort->write(_indexByte); _i2cPort->write(_writeByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, (sizeof(returnByte) * 3) + sizeof(statusByte) ); statusByte = _i2cPort->read(); @@ -1427,7 +1469,7 @@ int32_t* SparkFun_Bio_Sensor_Hub::readMultipleBytes(uint8_t _familyByte, uint8_t _i2cPort->write(_indexByte); _i2cPort->write(_writeByte); _i2cPort->endTransmission(); - delay(CMD_DELAY); + delayMicroseconds(CMD_DELAY*1000); _i2cPort->requestFrom(_address, static_cast(sizeof(int32_t) * _numOfReads + sizeof(statusByte))); statusByte = _i2cPort->read(); diff --git a/src/SparkFun_Bio_Sensor_Hub_Library.h b/src/SparkFun_Bio_Sensor_Hub_Library.h index e2af8d2..138cda0 100644 --- a/src/SparkFun_Bio_Sensor_Hub_Library.h +++ b/src/SparkFun_Bio_Sensor_Hub_Library.h @@ -23,8 +23,8 @@ #define ADC_MASK 0x9F #define READ_ADC_MASK 0x60 -#define ENABLE_CMD_DELAY 60 // Milliseconds -#define CMD_DELAY 20 // Milliseconds +#define ENABLE_CMD_DELAY 45 // Milliseconds +#define CMD_DELAY 6 // Milliseconds #define MAXFAST_ARRAY_SIZE 6 // Number of bytes.... #define MAXFAST_EXTENDED_DATA 5 #define MAX30101_LED_ARRAY 12 // 4 values of 24 bit (3 byte) LED values @@ -661,6 +661,9 @@ class SparkFun_Bio_Sensor_Hub // delays 60 microseconds, during which the MAX32664 retrieves the requested // information. An I-squared-C request is then issued, and the information is read and returned. uint8_t readByte(uint8_t, uint8_t); + + uint8_t readByte_fast(uint8_t _familyByte, uint8_t _indexByte); + uint8_t readByte_fast(uint8_t _familyByte, uint8_t _indexByte, uint8_t _writeByte); // This function is exactly as the one above except it accepts a Write Byte as // a paramter. It starts a request by writing the family byte, index byte, and