This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problems reading MAX30100 sensor using nrf52

Hello,

 I'm having trouble adapting my code which works for reading the MAX30100 sensor using TWI input with the NRF51 DK kit. 

I would like to adapt this code to be used with the NRF52 DK, but I am receiving several errors and don't understand their meaning. I believe there are some specific differences between the NRF51 and NRF52 that need to be taken into account, but I don't know how this affects code. Could anyone who is familiar explain what needs to change in the code so that at may work with the NRF52?

I've attached my code here

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

#define UART_TX_BUF_SIZE 256
#define UART_RX_BUF_SIZE 1

/* TWI PINS */
#define TWI_SCL_PIN     7
#define TWI_SDA_PIN     30

/* MAX30100 I2C-ADDRESS */
#define MAX30100_ADDRESS   0x57

/* MAX30100 Register Map */
#define MAX30100_INT_STATUS     0x00  // Which interrupts are tripped
#define MAX30100_INT_ENABLE     0x01  // Which interrupts are active
#define MAX30100_FIFO_WR_PTR    0x02  // Where data is being written
#define MAX30100_OVRFLOW_CTR    0x03  // Number of lost samples
#define MAX30100_FIFO_RD_PTR    0x04  // Where to read from
#define MAX30100_FIFO_DATA      0x05  // Ouput data buffer
#define MAX30100_MODE_CONFIG    0x06  // Control register
#define MAX30100_SPO2_CONFIG    0x07  // Oximetry settings
#define MAX30100_LED_CONFIG     0x09  // Pulse width and power of LEDs
#define MAX30100_TEMP_INTG      0x16  // Temperature value, whole number
#define MAX30100_TEMP_FRAC      0x17  // Temperature value, fraction
#define MAX30100_REV_ID         0xFE  // Part revision
#define MAX30100_PART_ID        0xFF  // Part ID, normally 0x11

/* TWI instance. */
static const nrf_drv_twi_t m_twi_max30100 = NRF_DRV_TWI_INSTANCE(0);

static void uart_events_handler(app_uart_evt_t * p_event)
{
    switch (p_event->evt_type)
    {
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

/**
 * @brief UART initialization.
 */
static void uart_config(void)
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud38400
    };
    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_events_handler,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

/**
 * @brief Function for initializing the TWI peripheral.
 */
 
void twi_init (void)
{
    ret_code_t err_code;
    
    const nrf_drv_twi_config_t twi_max30100_config = {
        .scl            = TWI_SCL_PIN,
        .sda            = TWI_SDA_PIN,
        .frequency      = NRF_TWI_FREQ_400K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH
    };
    err_code = nrf_drv_twi_init(&m_twi_max30100, &twi_max30100_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_twi_enable(&m_twi_max30100);
}

/**
 * @brief Function for writing to registers on the MAX30100.
 */

ret_code_t max30100_I2C_register_write(uint8_t reg_addr, uint8_t * p_tx_data, uint8_t bytes)
{
    ret_code_t ret_code;
    uint8_t tx_data[bytes+1];
    tx_data[0] = reg_addr;
    
    for(uint8_t i = 0 ; i<bytes ; i++) 
    {
        tx_data[i+1] = p_tx_data[i];
    }   
    ret_code = nrf_drv_twi_tx(&m_twi_max30100, MAX30100_ADDRESS, tx_data, sizeof(tx_data), false);
    return ret_code;
}

/**
 * @brief Function for reading from registers on the MAX30100.
 */

 ret_code_t max30100_I2C_register_read( uint8_t reg_addr,  uint8_t * p_rx_data, uint32_t bytes)
{   
    ret_code_t ret_code;
    ret_code = nrf_drv_twi_tx(&m_twi_max30100,MAX30100_ADDRESS, &reg_addr, 1, false);
    if(ret_code != NRF_SUCCESS)
    {
        return ret_code;
    }
    ret_code = nrf_drv_twi_rx(&m_twi_max30100, MAX30100_ADDRESS, p_rx_data, bytes,NULL);
    return ret_code;
}

void max30100_read_hr_spo2(int16_t * p_hr_val, int16_t * p_spo2_val)
{
    ret_code_t err_code;
    
    // Raw HR& SPo2 data from FIFO
    uint8_t hr_H[1];
	  uint8_t hr_L[1];
	  uint8_t spo2_H[1];
	  uint8_t spo2_L[1];
    
    // Read the four data registers from MAX30100_FIFO_DATA
		err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_H,sizeof(hr_H));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_L,sizeof(hr_L));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_H,sizeof(spo2_H));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_L,sizeof(spo2_L));
    
    APP_ERROR_CHECK(err_code);
    
    /*  Combine the two 8-bit data registers to a 16-bit value
        for each HR and SPO2 by left shifting MAX30100_FIFO_DATA eight times 
        and OR it with HR& SPO2_L. */
    *p_hr_val = (hr_H[0]<<8)|hr_L[0];
    *p_spo2_val = (spo2_H[0]<<8)|spo2_L[0];
}
/**
 * @brief Function for application main entry.
 */
int main(void)
{  
	  uart_config();
    // Initialize the TWI peripheral
    twi_init();
    
		uint8_t tx_data= 0x0B;  // temp-en 1, Mode 011  (temp en, HR, SPO2 en)
		max30100_I2C_register_write(MAX30100_MODE_CONFIG, &tx_data, 1);
		tx_data = 0x44; // LED Current
		max30100_I2C_register_write(MAX30100_LED_CONFIG, &tx_data, 1);
		tx_data = 0x07; //SPO2 sample rate 100/1s, LED pulse width = 1600 , ADC Resolution = 16bit
		max30100_I2C_register_write(MAX30100_SPO2_CONFIG, &tx_data, 1);
     
    while (true)
    {
				int16_t hr_val;
				int16_t spo2_val;

				max30100_read_hr_spo2(&hr_val,&spo2_val);
				printf("%d, %d \r\n",hr_val, spo2_val);

				nrf_delay_ms(10);
    }
}
:
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "app_error.h"
#include "app_util_platform.h"
#include "app_uart.h"
#include "boards.h"

#define UART_TX_BUF_SIZE 256
#define UART_RX_BUF_SIZE 1

/* TWI PINS */
#define TWI_SCL_PIN     7
#define TWI_SDA_PIN     30

/* MAX30100 I2C-ADDRESS */
#define MAX30100_ADDRESS   0x57

/* MAX30100 Register Map */
#define MAX30100_INT_STATUS     0x00  // Which interrupts are tripped
#define MAX30100_INT_ENABLE     0x01  // Which interrupts are active
#define MAX30100_FIFO_WR_PTR    0x02  // Where data is being written
#define MAX30100_OVRFLOW_CTR    0x03  // Number of lost samples
#define MAX30100_FIFO_RD_PTR    0x04  // Where to read from
#define MAX30100_FIFO_DATA      0x05  // Ouput data buffer
#define MAX30100_MODE_CONFIG    0x06  // Control register
#define MAX30100_SPO2_CONFIG    0x07  // Oximetry settings
#define MAX30100_LED_CONFIG     0x09  // Pulse width and power of LEDs
#define MAX30100_TEMP_INTG      0x16  // Temperature value, whole number
#define MAX30100_TEMP_FRAC      0x17  // Temperature value, fraction
#define MAX30100_REV_ID         0xFE  // Part revision
#define MAX30100_PART_ID        0xFF  // Part ID, normally 0x11

/* TWI instance. */
static const nrf_drv_twi_t m_twi_max30100 = NRF_DRV_TWI_INSTANCE(0);

static void uart_events_handler(app_uart_evt_t * p_event)
{
    switch (p_event->evt_type)
    {
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

/**
 * @brief UART initialization.
 */
static void uart_config(void)
{
    uint32_t                     err_code;
    const app_uart_comm_params_t comm_params =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud38400
    };
    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_events_handler,
                       APP_IRQ_PRIORITY_LOW,
                       err_code);

    APP_ERROR_CHECK(err_code);
}

/**
 * @brief Function for initializing the TWI peripheral.
 */
 
void twi_init (void)
{
    ret_code_t err_code;
    
    const nrf_drv_twi_config_t twi_max30100_config = {
        .scl            = TWI_SCL_PIN,
        .sda            = TWI_SDA_PIN,
        .frequency      = NRF_TWI_FREQ_400K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH
    };
    err_code = nrf_drv_twi_init(&m_twi_max30100, &twi_max30100_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_twi_enable(&m_twi_max30100);
}

/**
 * @brief Function for writing to registers on the MAX30100.
 */

ret_code_t max30100_I2C_register_write(uint8_t reg_addr, uint8_t * p_tx_data, uint8_t bytes)
{
    ret_code_t ret_code;
    uint8_t tx_data[bytes+1];
    tx_data[0] = reg_addr;
    
    for(uint8_t i = 0 ; i<bytes ; i++) 
    {
        tx_data[i+1] = p_tx_data[i];
    }   
    ret_code = nrf_drv_twi_tx(&m_twi_max30100, MAX30100_ADDRESS, tx_data, sizeof(tx_data), false);
    return ret_code;
}

/**
 * @brief Function for reading from registers on the MAX30100.
 */

 ret_code_t max30100_I2C_register_read( uint8_t reg_addr,  uint8_t * p_rx_data, uint32_t bytes)
{   
    ret_code_t ret_code;
    ret_code = nrf_drv_twi_tx(&m_twi_max30100,MAX30100_ADDRESS, &reg_addr, 1, false);
    if(ret_code != NRF_SUCCESS)
    {
        return ret_code;
    }
    ret_code = nrf_drv_twi_rx(&m_twi_max30100, MAX30100_ADDRESS, p_rx_data, bytes,NULL);
    return ret_code;
}

void max30100_read_hr_spo2(int16_t * p_hr_val, int16_t * p_spo2_val)
{
    ret_code_t err_code;
    
    // Raw HR& SPo2 data from FIFO
    uint8_t hr_H[1];
	  uint8_t hr_L[1];
	  uint8_t spo2_H[1];
	  uint8_t spo2_L[1];
    
    // Read the four data registers from MAX30100_FIFO_DATA
		err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_H,sizeof(hr_H));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,hr_L,sizeof(hr_L));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_H,sizeof(spo2_H));
	  err_code = max30100_I2C_register_read(MAX30100_FIFO_DATA,spo2_L,sizeof(spo2_L));
    
    APP_ERROR_CHECK(err_code);
    
    /*  Combine the two 8-bit data registers to a 16-bit value
        for each HR and SPO2 by left shifting MAX30100_FIFO_DATA eight times 
        and OR it with HR& SPO2_L. */
    *p_hr_val = (hr_H[0]<<8)|hr_L[0];
    *p_spo2_val = (spo2_H[0]<<8)|spo2_L[0];
}
/**
 * @brief Function for application main entry.
 */
int main(void)
{  
	  uart_config();
    // Initialize the TWI peripheral
    twi_init();
    
		uint8_t tx_data= 0x0B;  // temp-en 1, Mode 011  (temp en, HR, SPO2 en)
		max30100_I2C_register_write(MAX30100_MODE_CONFIG, &tx_data, 1);
		tx_data = 0x44; // LED Current
		max30100_I2C_register_write(MAX30100_LED_CONFIG, &tx_data, 1);
		tx_data = 0x07; //SPO2 sample rate 100/1s, LED pulse width = 1600 , ADC Resolution = 16bit
		max30100_I2C_register_write(MAX30100_SPO2_CONFIG, &tx_data, 1);
     
    while (true)
    {
				int16_t hr_val;
				int16_t spo2_val;

				max30100_read_hr_spo2(&hr_val,&spo2_val);
				printf("%d, %d \r\n",hr_val, spo2_val);

				nrf_delay_ms(10);
    }
}

Related