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

SPI Communication With MAX30003 ECG "Reg_READ_WRITE"

Hello Nordic,

I am trying to make NRF52840-DK Communication with MAX30003 ECG Board via SPI. I am using the SPI example and it works fine. Now I have made three SPI functions that I can use in my project:

- _Read_Data(int num_samples)  

- _Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data)

-_Reg_Read(uint8_t Reg_address)

I have made the following so far and the event handler works fine if I keep the original example code for the SPI transfer. It is just the _Reg_Read(uint8_t Reg_address) and _Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data) function which doesn't work. I am sure it has something to do with my function arguments. I am not too familiar with using pointers. The code below compiles without errors, but the LED does not flash as it is the case with the original sample code. I have referred MAX30003 ECG working Arduino code. See my both code below.

Any help is appreciated.

Regards,

rohit

#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"
#include "MAX30003.h"
#include <math.h>
#include <string.h>

#define SPI_INSTANCE  0 /**< SPI instance index. */
#define   ECG_FIFO        ((uint8_t)0x21)
#define   RTOR            ((uint8_t)0x25)

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

//FOr ECG Tx Buffer
 uint8_t SPI_RX_Buff[6];    /**< RX buffer. */
 uint8_t SPI_TX_Buff[6]={6,5,4,3,2,25};
 uint8_t ECG_length = sizeof(SPI_TX_Buff);
 uint8_t dataToSend[1];
 	uint8_t A[1]=0xFF;
  uint8_t A1[1]=0x00;
  uint8_t ECG_FIFO_BURST1;
volatile char *SPI_RX_Buff_Ptr;
int i=0;
unsigned long uintECGraw = 0;
signed long intECGraw=0;
uint8_t DataPacketHeader[20];
uint8_t data_len = 8;
signed long ecgdata;
unsigned long data;
 char SPI_temp_32b[4];
char SPI_temp_Burst[100];
static const uint8_t m_board_led_list[LEDS_NUMBER] = SPI_LIST;

/* As Reference from Aurdino Code */
//void bsp_board_toggle_pin(uint32_t pin_idx);
void timerIsr();
void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data);
void max30003_sw_reset(void);
void max30003_synch(void);
void MAX30003_Reg_Read(uint8_t Reg_address);
void MAX30003_Read_Data(int num_samples);
void MAX30003_begin();

	void max30003_sw_reset(void)        
	{
	 nrf_gpio_pin_set(SPI_SS_PIN);      //Slave select Set
	 nrf_gpio_pin_clear(SPI_SS_PIN);    //Slave select High
	 MAX30003_Reg_Write(SW_RST,0x00);  //As per Arduino Code
	} 
	
	void max30003_synch(void){
	MAX30003_Reg_Write(SYNCH,0x000000);  //As per Arduino Code
	}
	void timerIsr(){
			nrf_gpio_pin_toggle(NRF_FCLK_PIN); //As per Arduino Code
	}
	
	void MAX30003_begin(){
	max30003_sw_reset();
	nrf_delay_ms(100);
	MAX30003_Reg_Write(CNFG_GEN, 0x081007);
	nrf_delay_ms(100);
	MAX30003_Reg_Write(CNFG_CAL, 0x720000);  // 0x700000  
	nrf_delay_ms(100);
	MAX30003_Reg_Write(CNFG_EMUX,0x0B0000);
	nrf_delay_ms(100);
	MAX30003_Reg_Write(CNFG_ECG, 0x005000);  // d23 - d22 : 10 for 250sps , 00:500 sps
	nrf_delay_ms(100);
	MAX30003_Reg_Write(CNFG_RTOR1,0x3fc600);
	max30003_synch();
	nrf_delay_ms(100);
	}
void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data)  //Its Completed //for main.oerror 
	{ 		  
	  nrf_gpio_pin_clear(SPI_SS_PIN); 
		nrf_delay_ms(200);	
		WRITE_ADDRESS= WRITE_ADDRESS | WREG;
		dataToSend[1]=WRITE_ADDRESS;
		memset(SPI_RX_Buff, 0, ECG_length);
 	  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)dataToSend[1], ECG_length, SPI_RX_Buff, ECG_length));
	  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data>>16), ECG_length, SPI_RX_Buff, ECG_length));
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data>>8), ECG_length, SPI_RX_Buff, ECG_length));
	  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)(data), ECG_length, SPI_RX_Buff, ECG_length));
	  nrf_delay_ms(200);
 	  nrf_gpio_pin_set(SPI_SS_PIN); 
	}
	void MAX30003_Read_Data(int num_samples)     //Its Completed
	{
	 
	 nrf_gpio_pin_clear(SPI_SS_PIN);    // as per arduino code
	 ECG_FIFO_BURST1 = (ECG_FIFO_BURST<<1 ) | RREG;
   APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)ECG_FIFO_BURST1, ECG_length, SPI_RX_Buff, ECG_length));
	for ( i = 0; i < num_samples*3; ++i)
	{
		SPI_temp_Burst[i] = (nrf_drv_spi_transfer(&spi, (const uint8_t *)A1[1], ECG_length, SPI_RX_Buff, ECG_length));
	 
	}
	 nrf_gpio_pin_set(SPI_SS_PIN);  //it make High
	}
void MAX30003_Reg_Read(uint8_t Reg_address)  //Its Completed
{
	nrf_gpio_pin_clear(SPI_SS_PIN);    // as per arduino code
	Reg_address= (Reg_address<<1 ) | RREG;
	
	APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)Reg_address, ECG_length, SPI_RX_Buff, ECG_length));
	for ( i = 0; i < 3; i++)
	 {
	SPI_temp_32b[i]=(nrf_drv_spi_transfer(&spi, (const uint8_t *)A[1], ECG_length, SPI_RX_Buff, ECG_length)); 	 
	 }
	 nrf_gpio_pin_set(SPI_SS_PIN);  //it make High
}
	


void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
	  nrf_gpio_pin_set(SPI_SS_PIN);
    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
    if (SPI_RX_Buff[0] != 0)
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(SPI_RX_Buff, strlen((const char *)SPI_RX_Buff));
    }
}
int main(void)
{
	    char ECG_CHAR[30];
	   /*From Procentral upto line 222 */
	    MAX30003_Reg_Read(ECG_FIFO);           //Its stuck
      unsigned long data0 = (unsigned long) (SPI_temp_32b[0]);
      data0 = data0 <<24;
      unsigned long data1 = (unsigned long) (SPI_temp_32b[1]);
      data1 = data1 <<16;
      unsigned long data2 = (unsigned long) (SPI_temp_32b[2]);
      data2 = data2 >>6;
      data2 = data2 & 0x03;
      data = (unsigned long) (data0 | data1 | data2);
      ecgdata = (signed long) (data);
      MAX30003_Reg_Read(RTOR);                   //Its stuck
      unsigned long RTOR_msb = (unsigned long) (SPI_temp_32b[0]);
      unsigned char RTOR_lsb = (unsigned char) (SPI_temp_32b[1]);
      unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
      rtor = ((rtor >>2) & 0x3fff);
      float hr =  60 /((float)rtor*0.008); 
      unsigned int HR = (unsigned int)hr;  // type cast to int
      unsigned int RR = (unsigned int)rtor*8 ;  //8ms
      DataPacketHeader[0] = 0x0A;
      DataPacketHeader[1] = 0xFA;
      DataPacketHeader[2] = 0x0C;
      DataPacketHeader[3] = 0;
      DataPacketHeader[4] = 0x02;
   
      DataPacketHeader[5] = ecgdata;
      DataPacketHeader[6] = ecgdata>>8;
      DataPacketHeader[7] = ecgdata>>16;
      DataPacketHeader[8] = ecgdata>>24; 
   
      DataPacketHeader[9] =  RR ;
      DataPacketHeader[10] = RR >>8;
      DataPacketHeader[11] = 0x00;
      DataPacketHeader[12] = 0x00; 

      DataPacketHeader[13] = HR ;
      DataPacketHeader[14] = HR >>8;
      DataPacketHeader[15] = 0x00;
      DataPacketHeader[16] = 0x00; 
        
      DataPacketHeader[17] = 0x00;
      DataPacketHeader[18] = 0x0b;			
     bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin   = SPI_SS_PIN;    //29
    spi_config.miso_pin = SPI_MISO_PIN;  //28
    spi_config.mosi_pin = SPI_MOSI_PIN;  //4
    spi_config.sck_pin  = SPI_SCK_PIN;   //3
    nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);

    NRF_LOG_INFO("SPI example started.");
	 while (1)
    {
        // Reset rx buffer and transfer done flag
        memset(SPI_RX_Buff, 0, ECG_length);
        spi_xfer_done = false;    
        for(i=0; i<19; i++) // transmit the data
      {
				
         APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)SPI_TX_Buff, ECG_length, SPI_RX_Buff, ECG_length));
       }   
        while (!spi_xfer_done)
        {
            __WFE();
        }

        NRF_LOG_FLUSH();

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

#include<SPI.h>
#include <TimerOne.h>
#include "MAX30003.h"

#define MAX30003_CS_PIN   7
#define CLK_PIN          6

volatile char SPI_RX_Buff[5] ;
volatile char *SPI_RX_Buff_Ptr;
int i=0;
unsigned long uintECGraw = 0;
signed long intECGraw=0;
uint8_t DataPacketHeader[20];
uint8_t data_len = 8;
 signed long ecgdata;
 unsigned long data;

char SPI_temp_32b[4];
char SPI_temp_Burst[100];

// 32KHz clock using timer1
void timerIsr()
{
    digitalWrite( CLK_PIN, digitalRead(CLK_PIN ) ^ 1 ); // toggle Digital6 attached to FCLK  of MAX30003
}

void setup() 
{
    Serial.begin(115200); //Serial begin
    
    pinMode(MAX30003_CS_PIN,OUTPUT);
    digitalWrite(MAX30003_CS_PIN,HIGH); //disable device

    SPI.begin();
    SPI.setBitOrder(MSBFIRST); 
    SPI.setDataMode(SPI_MODE0);
    SPI.setClockDivider(SPI_CLOCK_DIV4);
    
    pinMode(CLK_PIN,OUTPUT);

    MAX30003_begin();   // initialize MAX30003
    
}

void loop() 
{
    MAX30003_Reg_Read(ECG_FIFO);

    unsigned long data0 = (unsigned long) (SPI_temp_32b[0]);
    data0 = data0 <<24;
    unsigned long data1 = (unsigned long) (SPI_temp_32b[1]);
    data1 = data1 <<16;
    unsigned long data2 = (unsigned long) (SPI_temp_32b[2]);
    data2 = data2 >>6;
    data2 = data2 & 0x03;
    
    data = (unsigned long) (data0 | data1 | data2);
    ecgdata = (signed long) (data);

    MAX30003_Reg_Read(RTOR);
    unsigned long RTOR_msb = (unsigned long) (SPI_temp_32b[0]);
   // RTOR_msb = RTOR_msb <<8;
    unsigned char RTOR_lsb = (unsigned char) (SPI_temp_32b[1]);

    unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
    rtor = ((rtor >>2) & 0x3fff) ;
  
    float hr =  60 /((float)rtor*0.008); 
   unsigned int HR = (unsigned int)hr;  // type cast to int

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

     /*Serial.print(RTOR_msb);
     Serial.print(",");
     Serial.print(RTOR_lsb);
     Serial.print(",");
     Serial.print(rtor); 
     Serial.print(",");
     Serial.print(rr);
     Serial.print(",");
     Serial.println(hr);      */

      DataPacketHeader[0] = 0x0A;
      DataPacketHeader[1] = 0xFA;
      DataPacketHeader[2] = 0x0C;
      DataPacketHeader[3] = 0;
      DataPacketHeader[4] = 0x02;
   
      DataPacketHeader[5] = ecgdata;
      DataPacketHeader[6] = ecgdata>>8;
      DataPacketHeader[7] = ecgdata>>16;
      DataPacketHeader[8] = ecgdata>>24; 
   
      DataPacketHeader[9] =  RR ;
      DataPacketHeader[10] = RR >>8;
      DataPacketHeader[11] = 0x00;
      DataPacketHeader[12] = 0x00; 

      DataPacketHeader[13] = HR ;
      DataPacketHeader[14] = HR >>8;
      DataPacketHeader[15] = 0x00;
      DataPacketHeader[16] = 0x00; 
        
      DataPacketHeader[17] = 0x00;
      DataPacketHeader[18] = 0x0b;
  
      for(i=0; i<19; i++) // transmit the data
      {
        Serial.write(DataPacketHeader[i]);
  
       }    

    delay(1);      
}

void MAX30003_Reg_Write (unsigned char WRITE_ADDRESS, unsigned long data)
{
 
  // now combine the register address and the command into one byte:
   byte dataToSend = (WRITE_ADDRESS<<1) | WREG;

   // take the chip select low to select the device:
   digitalWrite(MAX30003_CS_PIN, LOW);
   
   delay(2);
   SPI.transfer(dataToSend);   //Send register location
   SPI.transfer(data>>16);     //number of register to wr
   SPI.transfer(data>>8);      //number of register to wr
   SPI.transfer(data);      //Send value to record into register
   delay(2);
   
   // take the chip select high to de-select:
   digitalWrite(MAX30003_CS_PIN, HIGH);
}

void max30003_sw_reset(void)
{
  MAX30003_Reg_Write(SW_RST,0x000000);     
  delay(100);
}

void max30003_synch(void)
{
  MAX30003_Reg_Write(SYNCH,0x000000);
}

void MAX30003_Reg_Read(uint8_t Reg_address)
{
   uint8_t SPI_TX_Buff;
 
   digitalWrite(MAX30003_CS_PIN, LOW);
  
   SPI_TX_Buff = (Reg_address<<1 ) | RREG;
   SPI.transfer(SPI_TX_Buff); //Send register location
   
   for ( i = 0; i < 3; i++)
   {
      SPI_temp_32b[i] = SPI.transfer(0xff);
   }

   digitalWrite(MAX30003_CS_PIN, HIGH);
}

void MAX30003_Read_Data(int num_samples)
{
  uint8_t SPI_TX_Buff;

  digitalWrite(MAX30003_CS_PIN, LOW);   

  SPI_TX_Buff = (ECG_FIFO_BURST<<1 ) | RREG;
  SPI.transfer(SPI_TX_Buff); //Send register location

  for ( i = 0; i < num_samples*3; ++i)
  {
    SPI_temp_Burst[i] = SPI.transfer(0x00);
  }
  
  digitalWrite(MAX30003_CS_PIN, HIGH);  
}

void MAX30003_begin()
{
    //Start CLK timer
    Timer1.initialize(16);              // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second)
    Timer1.attachInterrupt( timerIsr ); // attach the service routine here
    
    max30003_sw_reset();
    delay(100);
    MAX30003_Reg_Write(CNFG_GEN, 0x081007);
    delay(100);
    MAX30003_Reg_Write(CNFG_CAL, 0x720000);  // 0x700000  
    delay(100);
    MAX30003_Reg_Write(CNFG_EMUX,0x0B0000);
    delay(100);
    MAX30003_Reg_Write(CNFG_ECG, 0x005000);  // d23 - d22 : 10 for 250sps , 00:500 sps
    delay(100);

    
    MAX30003_Reg_Write(CNFG_RTOR1,0x3fc600);
    max30003_synch();
    delay(100);
}

  • Hello sir,

    Thanks for the reply,

    I have made two functions for Reg read and reg write. may I Know its correct or not?

    if it is correct then I am facing some stuck on below function for store SPI Transmit data in char Array and when I call  MAX30003_Reg_Read() function to the main.

    void MAX30003_Reg_Read(uint8_t Reg_address) 
    {
    nrf_gpio_pin_clear(SPI_SS_PIN); // as per Arduino code
    Reg_address= (Reg_address<<1 ) | RREG;

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)Reg_address, ECG_length, SPI_RX_Buff, ECG_length));


    for ( i = 0; i < 3; i++)
    {
    SPI_temp_32b[i]=(nrf_drv_spi_transfer(&spi, (const uint8_t *)A[1], ECG_length, SPI_RX_Buff, ECG_length)); 
    }


    nrf_gpio_pin_set(SPI_SS_PIN); //it make High
    }

    int main(void)
    {
    char ECG_CHAR[30];
    /*From Procentral upto line 222 */
    MAX30003_Reg_Read(ECG_FIFO); //Its stuck
    unsigned long data0 = (unsigned long) (SPI_temp_32b[0]);
    data0 = data0 <<24;
    unsigned long data1 = (unsigned long) (SPI_temp_32b[1]);
    data1 = data1 <<16;
    unsigned long data2 = (unsigned long) (SPI_temp_32b[2]);
    data2 = data2 >>6;
    data2 = data2 & 0x03;
    data = (unsigned long) (data0 | data1 | data2);
    ecgdata = (signed long) (data);
    MAX30003_Reg_Read(RTOR); //Its stuck
    unsigned long RTOR_msb = (unsigned long) (SPI_temp_32b[0]);
    unsigned char RTOR_lsb = (unsigned char) (SPI_temp_32b[1]);
    unsigned long rtor = (RTOR_msb<<8 | RTOR_lsb);
    rtor = ((rtor >>2) & 0x3fff);
    float hr = 60 /((float)rtor*0.008); 
    unsigned int HR = (unsigned int)hr; // type cast to int
    unsigned int RR = (unsigned int)rtor*8 ; //8ms
    DataPacketHeader[0] = 0x0A;
    DataPacketHeader[1] = 0xFA;
    DataPacketHeader[2] = 0x0C;
    DataPacketHeader[3] = 0;
    DataPacketHeader[4] = 0x02;

    DataPacketHeader[5] = ecgdata;
    DataPacketHeader[6] = ecgdata>>8;
    DataPacketHeader[7] = ecgdata>>16;
    DataPacketHeader[8] = ecgdata>>24; 

    DataPacketHeader[9] = RR ;
    DataPacketHeader[10] = RR >>8;
    DataPacketHeader[11] = 0x00;
    DataPacketHeader[12] = 0x00;

    DataPacketHeader[13] = HR ;
    DataPacketHeader[14] = HR >>8;
    DataPacketHeader[15] = 0x00;
    DataPacketHeader[16] = 0x00; 

    DataPacketHeader[17] = 0x00;
    DataPacketHeader[18] = 0x0b; 
    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin = SPI_SS_PIN; //29
    spi_config.miso_pin = SPI_MISO_PIN; //28
    spi_config.mosi_pin = SPI_MOSI_PIN; //4
    spi_config.sck_pin = SPI_SCK_PIN; //3
    nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);

    NRF_LOG_INFO("SPI example started.");
    while (1)
    {
    // Reset rx buffer and transfer done flag
    memset(SPI_RX_Buff, 0, ECG_length);
    spi_xfer_done = false; 
    for(i=0; i<19; i++) // transmit the data
    {

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, (const uint8_t *)SPI_TX_Buff, ECG_length, SPI_RX_Buff, ECG_length));
    } 
    while (!spi_xfer_done)
    {
    __WFE();
    }

    NRF_LOG_FLUSH();

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

Related