Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

MAX30101 I2C communication with nRF52 - DK

Hi, I'm currently designing a system which requires Heart Rate monitorization and I'm using the MAX30101 chip to do so. I will be using I2C communication and, therefore, based my code on the twi_sensor example for the nRF52 -DK dev kit. However, I just can not get any values from the sensor. Can anybody help me understand what I'm doing wrong? Thanks in advance.  

#include <stdio.h>
#include "boards.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"


#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

/* TWI instance ID. */
#define TWI_INSTANCE_ID     0

/* Common addresses definition for temperature sensor. */
#define LM75B_ADDR          (0x90U >> 1)

#define MAX30101_ADDRESS     0x57
#define MAX30101_CONF_REG    0x09
#define MAX30101_MODE_HR     0x02
#define MAX30101_MODE_SPO2   0x03
#define MAX30101_FIFO_DATA   0x07
#define MAX30101_FIFO_WR_PT  0x04
#define MAX30101_FIFO_RD_PT  0x06

#define LM75B_REG_TEMP      0x00U
#define LM75B_REG_CONF      0x01U
#define LM75B_REG_THYST     0x02U
#define LM75B_REG_TOS       0x03U

/* Mode for LM75B. */
#define NORMAL_MODE 0U

/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;

/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

/* Buffer for samples read from temperature sensor. */
static uint8_t m_sample;

static uint8_t m_wr_ptr, m_rd_ptr, m_num_samples;

static uint8_t tx_fifo[2];

/**
 * @brief Function for setting active mode on MMA7660 accelerometer.
 */
void LM75B_set_mode(void)
{
    ret_code_t err_code;

    /* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
    uint8_t reg[2] = {MAX30101_CONF_REG, MAX30101_MODE_SPO2};
    err_code = nrf_drv_twi_tx(&m_twi, MAX30101_ADDRESS, reg, sizeof(reg), false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    /* Writing to pointer byte. */
    reg[0] = MAX30101_FIFO_WR_PT;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, MAX30101_ADDRESS, reg, 1, false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
    err_code = nrf_drv_twi_rx(&m_twi, MAX30101_ADDRESS, &m_wr_ptr, sizeof(m_wr_ptr));
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

/**
 * @brief Function for handling data from temperature sensor.
 *
 * @param[in] temp          Temperature in Celsius degrees read from sensor.
 */
__STATIC_INLINE void data_handler(uint8_t temp)
{
    NRF_LOG_INFO("Values SpO2: %d .", temp);
}

/**
 * @brief TWI events handler.
 */
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
        if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                data_handler(m_sample);
            }
            m_xfer_done = true;
            break;
        default:
            break;
    }
}

/**
 * @brief UART initialization.
 */
void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_lm75b_config = {
       .scl                = ARDUINO_SCL_PIN,
       .sda                = ARDUINO_SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

/**
 * @brief Function for reading data from temperature sensor.
 */
static void read_sensor_data()
{
    ret_code_t err_code;
    
    m_xfer_done = false;

     /* Writing to pointer byte. */
    tx_fifo[0] = MAX30101_FIFO_RD_PT;
    m_xfer_done = false;
    err_code = nrf_drv_twi_tx(&m_twi, MAX30101_ADDRESS, tx_fifo, 1, false);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    /* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
    err_code = nrf_drv_twi_rx(&m_twi, MAX30101_ADDRESS, &m_sample, sizeof(m_sample));
    APP_ERROR_CHECK(err_code);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("\r\nTWI sensor example started.");
    NRF_LOG_FLUSH();

    twi_init();
    NRF_LOG_INFO("\r\nI2C Communication initialized.");
    NRF_LOG_FLUSH();

    LM75B_set_mode();
    NRF_LOG_INFO("\r\nMAX30101 Initialized.");
    NRF_LOG_FLUSH();

    while (true)
    {
        nrf_delay_ms(500);

        do
        {
            __WFE();
        }while (m_xfer_done == false);

        read_sensor_data();
        NRF_LOG_FLUSH();
    }
}

  • Hi! Hope you're feeling better!

    I've been reading the datasheet and trying multiple stuff and tink I have actually resolved the problem! Thanks for the help anyway! I do have another question, if maybe you could help. To acquire the values from the FIFO, I'm not sure how to proceed. Could you maybe help with that? The following code is the function I'm using to acquire the values.

    void MAX30101_FIFO_HR (uint32_t *pun_red_led)
    {
        uint8_t status_1;
        uint32_t temp_32 = 0;
        uint8_t temp_array[3];
        
        *pun_red_led = 0;
    
        MAX30101_regRD(MAX30101_INT_ST_1, &status_1);
        MAX30101_regRD(MAX30101_FIFO_DATA, temp_array);
    
    
        temp_32 |= temp_array[0];
        temp_32 <<= 8;
        temp_32 |= temp_array[1];
        temp_32 <<= 8;
        temp_32 |= temp_array[2];
        *pun_red_led = temp_32;
    
        *pun_red_led &= 0x00FFFFFF;
    
    }

  • Hi

    Could you explain what you're trying to do and what part of it isn't working? That would make it easier for me to help you.

    Also, what was causing your previous issue? Would be nice to know if someone has similar issues.

    -Einar

  • My initialization was not correct, there were a lot of configurations missing. The following code is the initialization: 

    void MAX30101_init (void)
    {
        //Initialization and Configuration of MAX30101
        MAX30101_regWR(MAX30101_INT_EN_1, 0xC0);
        MAX30101_regWR(MAX30101_INT_EN_2, 0x00);
        
        MAX30101_regWR(MAX30101_FIFO_WR_PT, 0x00);
        MAX30101_regWR(MAX30101_OVF_CNT, 0x00);
        MAX30101_regWR(MAX30101_FIFO_RD_PT, 0x00);
    
        MAX30101_regWR(MAX30101_FIFO_CONF, 0x1F);
        MAX30101_regWR(MAX30101_CONF_REG, 0x03); //0x02 - HR; 0x03 - SpO2; 0x07 - Multi_LED
        MAX30101_regWR(MAX30101_SPO2_CONF, 0x27);
        MAX30101_regWR(LED1_PA, 0x3F);    // LED1 - RED
        //MAX30101_regWR(LED2_PA, 0x3F);    // LED2 - IR
        //MAX30101_regWR(LED3_PA, 0x3F);    // LED3 - GREEN
        //MAX30101_regWR(LED4_PA, 0x3F);    // LED4 - GREEN
    
        MAX30101_regRD(MAX30101_FIFO_WR_PT, &m_wr_ptr);
        MAX30101_regRD(MAX30101_FIFO_RD_PT, &m_rd_ptr);
    
        NRF_LOG_INFO("Initialization and Configuration of MAX30101 done");
        NRF_LOG_FLUSH();
    }
    

    Right now I'm trying to readthe values from the FIFO where the data is storred, on the MAX30101. The values that I'm getting don't make much sense I think.

  • They don't make sense in what way?

    As long as it isn't random gibberish data, I would have a look in the sensor data sheet to see what it says about how the data is represented.

    -Einar

Related