### Install Python dependencies Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/README.md Set up a virtual environment and install necessary libraries for the recorder and analysis tools. ```bash $ virtualenv max30100env $ source max30100env/bin/activate $ pip install -Ur requirements.txt ``` -------------------------------- ### Configure MAX30100 LED Current Levels Source: https://context7.com/oxullo/arduino-max30100/llms.txt This example shows how to set the current for the Infrared (IR) and Red LEDs. Proper current configuration is essential for accurate readings, as it needs to be adjusted based on factors like skin tone and ambient light to prevent signal clipping and maintain a good signal-to-noise ratio. ```cpp #include #include "MAX30100.h" MAX30100 sensor; void setup() { Serial.begin(115200); if (!sensor.begin()) { Serial.println("FAILED"); for(;;); } // Available LED current options (from MAX30100_Registers.h): // MAX30100_LED_CURR_0MA - 0.0 mA (LED off) // MAX30100_LED_CURR_4_4MA - 4.4 mA // MAX30100_LED_CURR_7_6MA - 7.6 mA // MAX30100_LED_CURR_11MA - 11.0 mA // MAX30100_LED_CURR_14_2MA - 14.2 mA // MAX30100_LED_CURR_17_4MA - 17.4 mA // MAX30100_LED_CURR_20_8MA - 20.8 mA // MAX30100_LED_CURR_24MA - 24.0 mA // MAX30100_LED_CURR_27_1MA - 27.1 mA // MAX30100_LED_CURR_30_6MA - 30.6 mA // MAX30100_LED_CURR_33_8MA - 33.8 mA // MAX30100_LED_CURR_37MA - 37.0 mA // MAX30100_LED_CURR_40_2MA - 40.2 mA // MAX30100_LED_CURR_43_6MA - 43.6 mA // MAX30100_LED_CURR_46_8MA - 46.8 mA // MAX30100_LED_CURR_50MA - 50.0 mA (default) // Set IR LED to 50mA, Red LED to 27.1mA sensor.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_27_1MA); // For PulseOximeter class, only IR LED can be adjusted: // pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA); // Red LED current is automatically managed by the bias algorithm } void loop() { // Application code } ``` -------------------------------- ### Configure MAX30100 Sampling Rate and Pulse Width Source: https://context7.com/oxullo/arduino-max30100/llms.txt This example demonstrates how to configure the sensor's sampling rate (50Hz to 1000Hz) and pulse width (200µs to 1600µs). Higher pulse widths offer better ADC resolution but may limit the maximum sampling rate. Ensure valid combinations are used as per the MAX30100 datasheet. ```cpp #include #include "MAX30100.h" MAX30100 sensor; void setup() { Serial.begin(115200); if (!sensor.begin()) { Serial.println("FAILED"); for(;;); } // Available sampling rates: // MAX30100_SAMPRATE_50HZ - 50 samples/second // MAX30100_SAMPRATE_100HZ - 100 samples/second (default) // MAX30100_SAMPRATE_167HZ - 167 samples/second // MAX30100_SAMPRATE_200HZ - 200 samples/second // MAX30100_SAMPRATE_400HZ - 400 samples/second // MAX30100_SAMPRATE_600HZ - 600 samples/second // MAX30100_SAMPRATE_800HZ - 800 samples/second // MAX30100_SAMPRATE_1000HZ - 1000 samples/second // Available pulse widths (determines ADC resolution): // MAX30100_SPC_PW_200US_13BITS - 200µs, 13-bit resolution // MAX30100_SPC_PW_400US_14BITS - 400µs, 14-bit resolution // MAX30100_SPC_PW_800US_15BITS - 800µs, 15-bit resolution // MAX30100_SPC_PW_1600US_16BITS - 1600µs, 16-bit resolution (default) sensor.setMode(MAX30100_MODE_SPO2_HR); sensor.setSamplingRate(MAX30100_SAMPRATE_100HZ); sensor.setLedsPulseWidth(MAX30100_SPC_PW_1600US_16BITS); // Enable high-resolution mode (required for 16-bit data) sensor.setHighresModeEnabled(true); } void loop() { // Application code } ``` -------------------------------- ### Import Libraries for Data Analysis Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Imports necessary libraries for plotting, data manipulation, signal processing, and data recording. Ensure these libraries are installed before running the script. ```python %matplotlib inline from matplotlib import pyplot as plt import pandas as pd from scipy import signal import numpy as np import recorder ``` -------------------------------- ### Measure Die Temperature with MAX30100 Source: https://context7.com/oxullo/arduino-max30100/llms.txt Initiates temperature sampling and polls for completion. Ensure the sensor is initialized and in SPO2/HR mode before starting. The temperature reading should be within a reasonable range. ```cpp #include #include "MAX30100.h" MAX30100 sensor; void setup() { Serial.begin(115200); if (!sensor.begin()) { Serial.println("FAILED"); for(;;); } sensor.setMode(MAX30100_MODE_SPO2_HR); // Start temperature sampling (asynchronous operation) Serial.print("Sampling die temperature.."); sensor.startTemperatureSampling(); // Poll for temperature ready (with timeout) uint32_t startTime = millis(); while (!sensor.isTemperatureReady()) { if (millis() - startTime > 1000) { Serial.println("ERROR: Temperature sampling timeout"); for(;;); } } // Retrieve temperature value float temperature = sensor.retrieveTemperature(); Serial.print("done, temp="); Serial.print(temperature); Serial.println("°C"); // Validate reading (should be reasonable room/body temperature) if (temperature < 5 || temperature > 50) { Serial.println("WARNING: Temperature probe reported an unusual value"); } } void loop() { // Application code } ``` -------------------------------- ### Run beat analysis notebook Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/README.md Launch the Jupyter notebook environment to perform beat analysis on recorded data. ```bash $ jupyter notebook beat_analysis.ipynb ``` -------------------------------- ### Import Data Analysis Libraries Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Initializes the environment with necessary libraries for data processing and plotting. ```python %matplotlib inline from matplotlib import pyplot as plt import pandas as pd from scipy import signal import numpy as np import recorder ``` ```python %load_ext autoreload %autoreload 2 ``` -------------------------------- ### Initialize and Read MAX30100 Sensor Data Source: https://context7.com/oxullo/arduino-max30100/llms.txt This snippet demonstrates how to initialize the MAX30100 sensor, configure its operational mode, LED currents, pulse width, sampling rate, and high-resolution mode. It then continuously reads raw IR and Red LED values from the sensor's FIFO buffer. ```cpp #include #include "MAX30100.h" // Configuration constants - refer to MAX30100 datasheet tables 8 and 9 #define SAMPLING_RATE MAX30100_SAMPRATE_100HZ #define IR_LED_CURRENT MAX30100_LED_CURR_50MA #define RED_LED_CURRENT MAX30100_LED_CURR_27_1MA #define PULSE_WIDTH MAX30100_SPC_PW_1600US_16BITS #define HIGHRES_MODE true MAX30100 sensor; void setup() { Serial.begin(115200); Serial.print("Initializing MAX30100.."); if (!sensor.begin()) { Serial.println("FAILED"); for(;;); } Serial.println("SUCCESS"); // Configure sensor parameters sensor.setMode(MAX30100_MODE_SPO2_HR); // Heart rate + SpO2 mode sensor.setLedsCurrent(IR_LED_CURRENT, RED_LED_CURRENT); sensor.setLedsPulseWidth(PULSE_WIDTH); sensor.setSamplingRate(SAMPLING_RATE); sensor.setHighresModeEnabled(HIGHRES_MODE); // Enable 16-bit resolution } void loop() { uint16_t ir, red; // Fetch new samples from the sensor's FIFO sensor.update(); // Read all available samples from internal buffer while (sensor.getRawValues(&ir, &red)) { Serial.print(ir); Serial.print('\t'); Serial.println(red); } } // Expected Serial Output (use Arduino Serial Plotter): // 45231 23456 // 45342 23567 // 45198 23489 ``` -------------------------------- ### Initialize and Read Pulse Oximeter Data Source: https://context7.com/oxullo/arduino-max30100/llms.txt This snippet demonstrates how to initialize the PulseOximeter class, register a beat detection callback, and periodically report heart rate and SpO2. Ensure proper I2C wiring and power supply for successful initialization. ```cpp #include #include "MAX30100_PulseOximeter.h" #define REPORTING_PERIOD_MS 1000 PulseOximeter pox; uint32_t tsLastReport = 0; // Callback fired when a heartbeat is detected void onBeatDetected() { Serial.println("Beat!"); } void setup() { Serial.begin(115200); Serial.print("Initializing pulse oximeter.."); // Initialize the PulseOximeter instance // Returns false if I2C wiring is improper, power supply missing, or wrong chip if (!pox.begin()) { Serial.println("FAILED"); for(;;); // Halt on failure } else { Serial.println("SUCCESS"); } // Optional: Adjust IR LED current (default is 50mA) // Lower current may improve accuracy for some skin types // pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA); // Register beat detection callback pox.setOnBeatDetectedCallback(onBeatDetected); } void loop() { // CRITICAL: Call update() as fast as possible to avoid missing samples pox.update(); // Report heart rate and SpO2 periodically // A value of 0 indicates invalid/no reading if (millis() - tsLastReport > REPORTING_PERIOD_MS) { Serial.print("Heart rate: "); Serial.print(pox.getHeartRate()); Serial.print(" bpm / SpO2: "); Serial.print(pox.getSpO2()); Serial.println("%"); tsLastReport = millis(); } } // Expected Serial Output: // Initializing pulse oximeter..SUCCESS // Beat! // Heart rate: 72.50 bpm / SpO2: 97% // Beat! // Heart rate: 73.20 bpm / SpO2: 98% ``` -------------------------------- ### Configure Pulse Oximeter Debugging Modes Source: https://context7.com/oxullo/arduino-max30100/llms.txt This snippet shows how to initialize the PulseOximeter with different debugging modes to output raw or processed signal data for analysis. The output format varies depending on the selected mode and can be visualized with the provided Processing sketch. ```cpp #include #include "MAX30100_PulseOximeter.h" PulseOximeter pox; void onBeatDetected() { Serial.println("B:1"); // Format for rolling_graph visualization } void setup() { Serial.begin(115200); // Available debugging modes: // PULSEOXIMETER_DEBUGGINGMODE_NONE - No debug output (default) // PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES - Raw IR and Red LED values // PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES - Values after DC removal filter // PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT - Filtered pulse and beat threshold if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT)) { Serial.println("ERROR: Failed to initialize pulse oximeter"); for(;;); } pox.setOnBeatDetectedCallback(onBeatDetected); } void loop() { pox.update(); // Debug output is automatically sent based on mode: // RAW_VALUES: "R:45231,23456" (IR,Red raw values) // AC_VALUES: "R:123.45,67.89" (IR,Red AC components) // PULSEDETECT: "R:89.12,45.00" (filtered pulse, threshold) } ``` -------------------------------- ### Configure Filter Parameters Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Sets the sampling rate and frequency cutoffs for the bandpass filter. ```python # Sample rate and desired cutoff frequencies (in Hz) # lowcut = 0.7*60 = 42bpm # highcut = 3*60 = 180bpm fs = 100.0 lowcut = 0.7 highcut = 3 ``` -------------------------------- ### Record sensor session Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/README.md Capture raw data samples from the serial device to a file for debugging or analysis. ```bash $ ./recorder.py --samples 1000 /dev/ttyACM0 test.out ``` -------------------------------- ### Visualize Frequency Response Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Plots the frequency response of the filter for different filter orders. ```python # Plot the frequency response for a few different orders. plt.figure(1) plt.clf() plt.xlim(xmax=10) for order in [2, 3, 6, 9]: b, a = butter_bandpass(lowcut, highcut, fs, order=order) w, h = signal.freqz(b, a, worN=2000) plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order) plt.plot([0, 0.5 * fs], [np.sqrt(0.5), np.sqrt(0.5)], '--', label='sqrt(0.5)') plt.xlabel('Frequency (Hz)') plt.ylabel('Gain') plt.grid(True) plt.legend(loc='best') ``` -------------------------------- ### Run MAX30100 diagnostic routine Source: https://context7.com/oxullo/arduino-max30100/llms.txt Use this routine to verify hardware connectivity and sensor functionality. It performs a series of tests including I2C communication, LED bias configuration, and temperature sampling. ```cpp #include #include "MAX30100.h" MAX30100 sensor; void setup() { Serial.begin(115200); // Test 1: I2C connectivity and chip identification Serial.print("Initializing MAX30100.."); if (!sensor.begin()) { Serial.print("FAILED: "); uint8_t partId = sensor.getPartId(); if (partId == 0xff) { Serial.println("I2C error - check wiring and pullups (4.7kΩ)"); } else { Serial.print("wrong part ID 0x"); Serial.print(partId, HEX); Serial.print(" (expected: 0x11)"); } for(;;); } Serial.println("Success"); // Test 2: Mode configuration Serial.print("Enabling HR/SPO2 mode.."); sensor.setMode(MAX30100_MODE_SPO2_HR); Serial.println("done."); // Test 3: LED current configuration Serial.print("Configuring LEDs biases to 50mA.."); sensor.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_50MA); Serial.println("done."); delay(1000); Serial.print("Lowering the current to 7.6mA.."); sensor.setLedsCurrent(MAX30100_LED_CURR_7_6MA, MAX30100_LED_CURR_7_6MA); Serial.println("done."); delay(1000); // Test 4: Power management Serial.print("Shutting down.."); sensor.shutdown(); Serial.println("done."); delay(1000); Serial.print("Resuming normal operation.."); sensor.resume(); delay(500); Serial.println("done."); // Test 5: Temperature sensor Serial.print("Sampling die temperature.."); sensor.startTemperatureSampling(); uint32_t tsTempStart = millis(); while (!sensor.isTemperatureReady()) { if (millis() - tsTempStart > 1000) { Serial.println("ERROR: timeout"); for(;;); } } float temperature = sensor.retrieveTemperature(); Serial.print("done, temp="); Serial.print(temperature); Serial.println("C"); if (temperature < 5) { Serial.println("WARNING: Temperature probe reported an odd value"); } else { Serial.println("All tests pass."); } Serial.println("\nPress any key to enter sampling loop mode"); while (!Serial.available()); sensor.resetFifo(); } void loop() { uint16_t ir, red; sensor.update(); while (sensor.getRawValues(&ir, &red)) { Serial.print("IR="); Serial.print(ir); Serial.print(" RED="); Serial.println(red); } } // Expected successful output: // Initializing MAX30100..Success // Enabling HR/SPO2 mode..done. // Configuring LEDs biases to 50mA..done. // Lowering the current to 7.6mA..done. // Shutting down..done. // Resuming normal operation..done. // Sampling die temperature..done, temp=24.94C // All tests pass. ``` -------------------------------- ### Load and Plot Recorded Data Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Reads the recorded data from a CSV file and visualizes the raw samples. ```python # Read from the recorded session df = pd.read_csv('test.out', delimiter='\t', index_col=0) ``` ```python # Plot the sampled data, skipping the first samples df[4:].plot() ``` -------------------------------- ### MAX30100 Power Management: Shutdown and Resume Source: https://context7.com/oxullo/arduino-max30100/llms.txt Enters and exits low-power shutdown mode based on serial commands ('s' to shutdown, 'r' to resume). Resuming requires a short delay and FIFO reset for sensor stabilization. This is ideal for battery-powered applications. ```cpp #include #include "MAX30100.h" MAX30100 sensor; bool isSleeping = false; void setup() { Serial.begin(115200); if (!sensor.begin()) { Serial.println("FAILED"); for(;;); } sensor.setMode(MAX30100_MODE_SPO2_HR); sensor.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_50MA); Serial.println("Sensor initialized and running"); } void loop() { // Check for serial command to toggle power state if (Serial.available()) { char cmd = Serial.read(); if (cmd == 's' && !isSleeping) { // Enter shutdown mode sensor.shutdown(); isSleeping = true; Serial.println("Sensor shutdown - low power mode"); } else if (cmd == 'r' && isSleeping) { // Resume normal operation sensor.resume(); delay(500); // Allow sensor to stabilize sensor.resetFifo(); // Clear any stale data isSleeping = false; Serial.println("Sensor resumed - normal operation"); } } // Only sample when not in sleep mode if (!isSleeping) { uint16_t ir, red; sensor.update(); while (sensor.getRawValues(&ir, &red)) { Serial.print("IR="); Serial.print(ir); Serial.print(" RED="); Serial.println(red); } } } // For PulseOximeter class, same methods are available: // pox.shutdown(); // pox.resume(); ``` -------------------------------- ### Record Sensor Data Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Captures raw sensor data from the specified serial port and saves it to a file. ```python # Record 2000 samples worth of data, delaying acquisition by 5 seconds # this can be done also using the command line interface of recorder.py recorder.run(port='/dev/ttyACM0', outfile='test.out', holdoff=5, debug=False, samples=2000) ``` -------------------------------- ### Configure Serial Port for Rolling Graph Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/rolling_graph/README.md Adjust this line to match the serial port your microcontroller is connected to on Linux or Windows systems. OSX should auto-detect the port. ```processing final String serialPort = "/dev/ttyACM0"; ``` -------------------------------- ### Arduino MAX30100 I2C Wiring Diagram Source: https://context7.com/oxullo/arduino-max30100/llms.txt Illustrates the I2C connection between an Arduino UNO and the MAX30100 sensor. Ensure correct pull-up resistors (4.7kΩ or less) are used on SDA and SCL lines. The I2C address is fixed at 0x57. For 3.3V MCUs, pull SDA/SCL to 3.3V. ```text Arduino Wiring Diagram (I2C Connection): Arduino UNO MAX30100 Sensor ----------- --------------- 5V ──────────── VIN (or 3.3V for 3.3V boards) GND ──────────── GND A4 (SDA) ─────┬── SDA │ [4.7kΩ] │ 5V A5 (SCL) ─────┬── SCL │ [4.7kΩ] │ 5V Notes: - Use 4.7kΩ (or less) pull-up resistors on SDA and SCL - I2C address is fixed at 0x57 - INT pin is optional (not used by this library) - For 3.3V MCUs, pull SDA/SCL to 3.3V instead - ATmega328p (Arduino UNO) considers 3.0V+ as HIGH, so 5V pullups work even with 3.3V sensor breakouts ``` -------------------------------- ### Apply Filter to Data Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Applies the bandpass filter to the dataframe and plots the resulting signal. ```python # Apply the filter to the dataframe order = 2 df_filtered = df.apply(lambda x: butter_bandpass_filter(x, lowcut, highcut, fs, order=order)) ``` ```python # Plot the filtered dataframe, skipping the initial transition df_filtered[250:].plot(figsize=(15,7)) ``` -------------------------------- ### Record Sensor Data Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Records sensor data for a specified number of samples, with an option to delay the acquisition. This function is used to capture raw data from the sensor for later analysis. ```python # Record 200 samples worth of data, delaying acquisition by 5 seconds # this can be done also using the command line interface of recorder.py recorder.run(port='/dev/ttyACM0', outfile='test.out', holdoff=5, debug=False, samples=200) ``` -------------------------------- ### Read Recorded Data into Pandas DataFrame Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Reads data from a tab-delimited output file into a Pandas DataFrame. The first column is set as the index, which typically contains timestamps. ```python # Read from the recorded session df = pd.read_csv('test.out', delimiter='\t', index_col=0) ``` -------------------------------- ### Generate Histogram of Time Differences Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Generates a histogram of all time differences between samples. This provides a statistical overview of the sampling intervals and their distribution. ```python df_ts_diffs.hist() ``` -------------------------------- ### Calculate Time Differences Between Samples Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Creates a DataFrame containing the time differences between consecutive samples. This is useful for analyzing the sampling rate and identifying any jitter. ```python df_ts = pd.DataFrame(df.index) df_ts_diffs = df_ts.diff() ``` -------------------------------- ### Plot Time Differences Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Plots the time differences between samples for a specific range (10 to 40). This visualization helps in identifying variations in sampling intervals. ```python df_ts_diffs[10:40].plot() ``` -------------------------------- ### Define Butterworth Bandpass Filter Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/beat_analysis.ipynb Implements a Butterworth bandpass filter using Scipy signal processing functions. ```python # Copied from http://scipy.github.io/old-wiki/pages/Cookbook/ButterworthBandpass def butter_bandpass(lowcut, highcut, fs, order=5): nyq = 0.5 * fs low = lowcut / nyq high = highcut / nyq b, a = signal.butter(order, [low, high], btype='band') return b, a def butter_bandpass_filter(data, lowcut, highcut, fs, order=5): b, a = butter_bandpass(lowcut, highcut, fs, order=order) y = signal.lfilter(b, a, data) return y ``` -------------------------------- ### Enable Automatic Reloading of Modules Source: https://github.com/oxullo/arduino-max30100/blob/master/extras/recorder/sampling_analysis.ipynb Enables autoreload for Python modules, which automatically reloads modules before executing code. This is useful during development to see changes without restarting the kernel. ```python %load_ext autoreload %autoreload 2 ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.