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();
    }
}

Parents
  • I did a few changes, but still I get the same results. Here is the newer version of the code. Once again, 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
    
    #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 SPO2_CONF            0x0A
    #define SPO2_CONF_SET        0x04
    
    /* 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[10];
    static uint8_t read_array[10];
    
    /**
     * @brief Function for setting active mode on MMA7660 accelerometer.
     */
    void LM75B_set_mode(void)
    {
        ret_code_t err_code;
    
        /* Writing to MAX30101_CONF_REG to set SpO2 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. */
        tx_fifo[0] = MAX30101_FIFO_WR_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);
        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;
    
        read_array[0] = MAX30101_FIFO_DATA;
        m_xfer_done = false;
        err_code = nrf_drv_twi_tx(&m_twi, MAX30101_ADDRESS, read_array, 1, false);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);
    
        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!

    What have you done so far to debug the I2C?

    Are you able to use you I2C device at all? Is the problem reaching the sensor?

    Have you seen any error messages that could indicate what your problem is?

    Best regards,

    Einar

  • What exactly do you mean by detecting the sensor?

    Are you able to read other registers than the measurement data, such as a sensor device id maybe?

  • I used the twi_scanner code to get the slave ID.

  • ok I see, and then when you try to read anything you get only zeroes?

    Have you tried initializing your read array to something other than zero to differentiate between reading zeroes and not reading anything?

  • Yes, I have tried that and I still get zeros. 

    My guess is that I am not correctly reading the FIFO, but I cant't find what it is that I'm doing wrong.

  • Does the datasheet confirm the slave id?

    Depending on the type of sensor you're using there could potentially be more than one available slave id.

    Based on the behavior you're seeing it sounds like it could be either a wrong slave address or incomplete initialization of the sensor.

    If you're still having issues I can look into the data reading procedure on monday

    -Einar

Reply
  • Does the datasheet confirm the slave id?

    Depending on the type of sensor you're using there could potentially be more than one available slave id.

    Based on the behavior you're seeing it sounds like it could be either a wrong slave address or incomplete initialization of the sensor.

    If you're still having issues I can look into the data reading procedure on monday

    -Einar

Children
  • Yes, the datasheet confirms the slave ID. 

    It probably is an incomplete initialization, because the slave ID is correct. If you could help, I would be really thankful! I'll keep trying through the weekend. 

    Thanks in advance! 

  • Hello again, sorry for the late reply, I was home sick last week.

    I notice you're using this legacy driver, any reason you're not using the nrfx driver?

    What version of the SDK are you using?

    -Einar

  • 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.

Related