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

Cannot Read MAX30003WING Board using SPI communication

Hello,

I tried to check SPI communication with a test board.

However, I couldn't read the device info from the max30003wing board.

Board: NRF52840DK --> MAX30003WING Using SPI.

SDK: nRF5_SDK_17.1.0_ddde560

this is my code 

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define HIGH  1
#define LOW   0

#define WREG 0x00
#define RREG 0x01

#define SPI_TIMEOUT       50000

#define   NO_OP           0x00
#define   STATUS          0x01
#define   EN_INT          0x02
#define   EN_INT2         0x03
#define   MNGR_INT        0x04
#define   MNGR_DYN        0x05
#define   SW_RST          0x08
#define   SYNCH           0x09
#define   FIFO_RST        0x0A
#define   INFO            0x0F
#define   CNFG_GEN        0x10
#define   CNFG_CAL        0x12
#define   CNFG_EMUX       0x14
#define   CNFG_ECG        0x15
#define   CNFG_RTOR1      0x1D
#define   CNFG_RTOR2      0x1E
#define   ECG_FIFO_BURST  0x20
#define   ECG_FIFO        0x21
#define   RTOR            0x25
#define   NO_OP           0x7F

#define MAX30003_CLK_PIN  3
#define MAX30003_MOSI_PIN 4
#define MAX30003_MISO_PIN 28
#define MAX30003_CS_PIN   29

#define RTOR_INTR_MASK     0x04

#define AFE_SPI_INSTANCE  0
const nrf_drv_spi_t afe_spi = NRF_DRV_SPI_INSTANCE(AFE_SPI_INSTANCE);  /**< SPI instance. */

volatile bool afe_spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

unsigned int heartRate;
unsigned int RRinterval;
signed long ecgdata;

typedef enum
{
  SAMPLINGRATE_128 = 128, SAMPLINGRATE_256 = 256, SAMPLINGRATE_512 = 512
}sampRate;

void max30003RegWrite (unsigned char WRITE_ADDRESS, unsigned long data)
{
	uint32_t err_code;
	uint32_t timeout = SPI_TIMEOUT;
	uint8_t dataToSend[4] = {0x00,} ;

	afe_spi_xfer_done = false;

    // now combine the register address and the command into one byte:
    dataToSend[0] = (WRITE_ADDRESS<<1) | WREG;
	dataToSend[1] = (data>>16);
	dataToSend[2] = (data>>8);
	dataToSend[3] = (data);

     // take the chip select low to select the device:
    nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);    

    nrf_delay_ms(2);
	err_code = nrf_drv_spi_transfer(&afe_spi, &dataToSend, 4, NULL, 0);
    nrf_delay_ms(2);
    // take the chip select high to de-select:
    nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);    	
    while((!afe_spi_xfer_done) && --timeout);
    if(!timeout) return NRF_ERROR_TIMEOUT;   

}



void max30003SwReset(void)
{
    max30003RegWrite(SW_RST,0x000000);
    nrf_delay_ms(100);
}

void max30003Synch(void)
{
    max30003RegWrite(SYNCH,0x000000);
}

void max30003RegRead(uint8_t Reg_address, uint8_t * buff)
{
	uint32_t err_code;
	uint32_t timeout = SPI_TIMEOUT;	
    uint8_t spiTxBuff;	

	afe_spi_xfer_done = false;
	nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
	nrf_delay_ms(2);
    spiTxBuff = (Reg_address<<1 ) | RREG;
	err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, buff, 4);
	nrf_delay_ms(2);
    nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
	if(err_code != NRF_SUCCESS) return err_code;
	while((!afe_spi_xfer_done) && --timeout);
	if(!timeout) return NRF_ERROR_TIMEOUT;
}

ret_code_t max30003ReadStatus(void)
{
	uint32_t err_code;
	uint32_t timeout = SPI_TIMEOUT;
    uint8_t spiTxBuff;
    uint8_t readBuff[4] ;

	afe_spi_xfer_done = false;
	spiTxBuff = (STATUS << 1 ) | RREG;

    nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);    
   	nrf_delay_ms(2);
	err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
	nrf_delay_ms(2);	
	nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
	if(err_code != NRF_SUCCESS) return err_code;
	while((!afe_spi_xfer_done) && --timeout);
	if(!timeout) return NRF_ERROR_TIMEOUT;

    return NRF_SUCCESS;
}

ret_code_t max30003ReadInfo(void)
{
	uint32_t err_code;
	uint32_t timeout = SPI_TIMEOUT;
    uint8_t spiTxBuff;
    uint8_t readBuff[4] = {0x00,} ;
	afe_spi_xfer_done = false;
	spiTxBuff = (INFO << 1 ) | RREG;

    nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);    
	nrf_delay_ms(2);    
	err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
	nrf_delay_ms(2);	
	nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
	if(err_code != NRF_SUCCESS) return err_code;
	while((!afe_spi_xfer_done) && --timeout);
	if(!timeout) return NRF_ERROR_TIMEOUT;
	//afe_spi_xfer_done = false;


    if((readBuff[0]&0xf0) == 0x50 ){

      NRF_LOG_INFO("max30003 is ready");
      NRF_LOG_INFO("Rev ID:  0x%02x", (readBuff[0]&0xf0));      
    }else{
      NRF_LOG_INFO("max30003 read info error\n");
      NRF_LOG_INFO("Rev ID:  0x%02x", (readBuff[0]&0xf0));      
	  return NRF_ERROR_NOT_FOUND;
    }

    return NRF_SUCCESS;
}

void max30003ReadData(int num_samples, uint8_t * readBuffer)
{
	uint32_t err_code;
	uint32_t timeout = SPI_TIMEOUT;
    uint8_t spiTxBuff;
    uint8_t readBuff[4] ;

    nrf_gpio_pin_write(MAX30003_CS_PIN, LOW);
	nrf_delay_ms(2);

    spiTxBuff = (ECG_FIFO_BURST<<1 ) | RREG;
	err_code = nrf_drv_spi_transfer(&afe_spi, &spiTxBuff, 1, readBuff, 4);
	nrf_delay_ms(2);	
	nrf_gpio_pin_write(MAX30003_CS_PIN, HIGH);
	if(err_code != NRF_SUCCESS) return err_code;

	while((!afe_spi_xfer_done) && --timeout);
	if(!timeout) return NRF_ERROR_TIMEOUT;
}

void max30003Begin()
{
    max30003SwReset();
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_GEN, 0x081007);
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_CAL, 0x720000);  // 0x700000
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_EMUX,0x0B0000);
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_ECG, 0x805000);  // d23 - d22 : 10 for 250sps , 00:500 sps
    nrf_delay_ms(100);

    max30003RegWrite(CNFG_RTOR1,0x3fc600);
    max30003Synch();
    nrf_delay_ms(100);
}

void max30003BeginRtorMode()
{
    max30003SwReset();
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_GEN, 0x080004);
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_CAL, 0x720000);  // 0x700000
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_EMUX,0x0B0000);
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_ECG, 0x805000);  // d23 - d22 : 10 for 250sps , 00:500 sps
    nrf_delay_ms(100);
    max30003RegWrite(CNFG_RTOR1,0x3fc600);
    nrf_delay_ms(100);
    max30003RegWrite(EN_INT, 0x000401);
    nrf_delay_ms(100);
    max30003Synch();
    nrf_delay_ms(100);
}

//not tested
void max30003SetsamplingRate(uint16_t samplingRate)
{
    uint8_t regBuff[4] = {0};
    max30003RegRead(CNFG_ECG, regBuff);

    switch(samplingRate){
        case SAMPLINGRATE_128:
                regBuff[0] = (regBuff[0] | 0x80 );
            break;

        case SAMPLINGRATE_256:
                regBuff[0] = (regBuff[0] | 0x40 );
            break;

        case SAMPLINGRATE_512:
                regBuff[0] = (regBuff[0] | 0x00 );
            break;

        default :            
            break;
    }

    unsigned long cnfgEcg;
    memcpy(&cnfgEcg, regBuff, 4);

    max30003RegWrite(CNFG_ECG, (cnfgEcg >> 8));
}

void getEcgSamples(void)
{
    uint8_t regReadBuff[4];
    max30003RegRead(ECG_FIFO, regReadBuff);

    unsigned long data0 = (unsigned long) (regReadBuff[0]);
    data0 = data0 <<24;
    unsigned long data1 = (unsigned long) (regReadBuff[1]);
    data1 = data1 <<16;
    unsigned long data2 = (unsigned long) (regReadBuff[2]);
    data2 = data2 >>6;
    data2 = data2 & 0x03;

    unsigned long data = (unsigned long) (data0 | data1 | data2);
    ecgdata = (signed long) (data);
	printf("ecgdata(%d) \r\n", ecgdata);
}


void getHRandRR(void)
{
    uint8_t regReadBuff[4];
    max30003RegRead(RTOR, regReadBuff);

    unsigned long RTOR_msb = (unsigned long) (regReadBuff[0]);
    unsigned char RTOR_lsb = (unsigned char) (regReadBuff[1]);
    unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
    rtor = ((rtor >>2) & 0x3fff) ;

    float hr =  60 /((float)rtor*0.0078125);
    heartRate = (unsigned int)hr;

    unsigned int RR = (unsigned int)rtor* (7.8125) ;  //8ms
    RRinterval = RR;
}

void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    afe_spi_xfer_done = true;
}


int main(void)
{
	uint32_t err_code;

    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    nrf_gpio_cfg_output(MAX30003_CS_PIN);
    nrf_gpio_pin_write(MAX30003_CS_PIN, 1);

    nrfx_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPI_FREQ_1M;
    spi_config.ss_pin         = MAX30003_CS_PIN;
    spi_config.miso_pin       = MAX30003_MISO_PIN;
    spi_config.mosi_pin       = MAX30003_MOSI_PIN;
    spi_config.sck_pin        = MAX30003_CLK_PIN;
	//spi_config.mode			    = NRF_SPI_MODE_0;

    APP_ERROR_CHECK(nrf_drv_spi_init(&afe_spi, &spi_config, spi_event_handler, NULL));
    //APP_ERROR_CHECK(nrf_drv_spi_init(&afe_spi, &spi_config, NULL, NULL));

    NRF_LOG_INFO("NRFX SPI example started.");
	 nrf_delay_ms(2);
	 err_code = max30003ReadInfo();
	 nrf_delay_ms(2);
	 
    while (1)
    {
        // Reset rx buffer and transfer done flag
        //memset(m_rx_buf, 0, m_length);
        //spi_xfer_done = false;

        //APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));
		
        while (!afe_spi_xfer_done)
        {
            __WFE();
        }

        NRF_LOG_FLUSH();

        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(200);
        #endif
    }
}

I don't know what is wrong. Is the problems with the SPI read function?

Please any help is appreciated.

Regards,

ray

Parents
  • Looking at your implementation of max30003ReadStatus() and trace, then it looks like the SPI is doing exactly as programmed. So, you need to look at whether the MAX30003WING is powered, configured for SPI, and that all SPI pins (including GND) are connected correctly between the boards.

    Kenneth

Reply
  • Looking at your implementation of max30003ReadStatus() and trace, then it looks like the SPI is doing exactly as programmed. So, you need to look at whether the MAX30003WING is powered, configured for SPI, and that all SPI pins (including GND) are connected correctly between the boards.

    Kenneth

Children
Related