Hi all,
I am working with the nRF52 dev kit and the ecg sensor MAX30003. Using MBED to develop firmware.
I am using this library and the example code from maxim (https://os.mbed.com/teams/MaximIntegrated/code/MAX30003/ 1)
My problem is:
No interrupt calls are triggered from the ecg sensor despite the ecg FIFO being full. No ECG readings are coming in. But I am able to accurately read and write registers from the MAX30003.
Thanks for any help!
my code is below:
#include "mbed.h"
#include "MAX30003.h"
//LED pins
#define LED1 p17
//#define LED2 p20 //-->check pins after
//SPI PINS (MAX 30003)
#define SPI_MOSI p26 //SPI MOSI Pin
#define SPI_MISO p23 //SPI MISO Pin
#define SPI_SCK p24 //SPI SCK Pin
#define ECG_SPI_CS p22 //ECG SPI Chip Select Pin
#define ECG_INT_PIN p19 //ECG Interrupt Pin (FIFO almost full)
void ecg_config(MAX30003 &ecgAFE);
/* ECG FIFO nearly full callback */
volatile bool ecgFIFOIntFlag = 0;
void ecgFIFO_callback() {
ecgFIFOIntFlag = 1;
}
int main()
{
// Constants
const int EINT_STATUS_MASK = 1 << 23;
const int FIFO_OVF_MASK = 0x7;
const int FIFO_VALID_SAMPLE_MASK = 0x0;
const int FIFO_FAST_SAMPLE_MASK = 0x1;
const int ETAG_BITS_MASK = 0x7;
// Ports and serial connections
Serial pc(USBTX, USBRX); // Use USB debug probe for serial link
pc.baud(115200); // Baud rate = 115200
DigitalOut rLed(LED1, 0); // Debug LED
//DigitalOut gLed(LED2, 0); // Debug LED
InterruptIn ecgFIFO_int(ECG_INT_PIN);
ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
SPI spiBus(SPI_MOSI, SPI_MISO, SPI_SCK); // SPI bus
MAX30003 ecgAFE(spiBus, ECG_SPI_CS); // New MAX30003 on spiBus, CS
ecg_config(ecgAFE); // Config ECG
ecgAFE.writeRegister( MAX30003::SYNCH , 0);
//ecgAFE.writeRegister( MAX30003::FIFO_RST , 0);
uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
int16_t ecgSample[32];
pc.printf("MAX30003 configured \n\n\n");
pc.printf("INFO %d \n\n", ecgAFE.readRegister( MAX30003::INFO ));
pc.printf("STATUS %d \n\n", ecgAFE.readRegister( MAX30003::STATUS ));
ecgAFE.writeRegister( MAX30003::FIFO_RST , 0);
while(1) {
pc.printf("STATUS %d \n\n", ecgAFE.readRegister( MAX30003::STATUS ));
pc.printf("ecgFIFOIntFlag %d \n\n", ecgFIFOIntFlag);
// Read back ECG samples from the FIFO
if( ecgFIFOIntFlag ) {
ecgFIFOIntFlag = 0;
status = ecgAFE.readRegister( MAX30003::STATUS ); // Read the STATUS register
// Check if EINT interrupt asserted
if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
readECGSamples = 0; // Reset sample counter
do {
ecgFIFO = ecgAFE.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK; // Isolate ETAG
readECGSamples++; // Increment sample counter
// Check that sample is not last sample in FIFO
} while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
// Check if FIFO has overflowed
if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
ecgAFE.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
rLed = 1;//notifies the user that an over flow occured
}
// Print results
for( idx = 0; idx < readECGSamples; idx++ ) {
pc.printf("%6d\r\n", ecgSample[idx]);
}
}
}
}
}
void ecg_config(MAX30003& ecgAFE) {
// Reset ECG to clear registers
ecgAFE.writeRegister( MAX30003::SW_RST , 0);
// General config register setting
MAX30003::GeneralConfiguration_u CNFG_GEN_r;
CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
// ECG Config register setting
MAX30003::ECGConfiguration_u CNFG_ECG_r;
CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
//R-to-R configuration
MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
CNFG_RTOR_r.bits.wndw = 0b0011; // WNDW = 96ms
CNFG_RTOR_r.bits.rgain = 0b1111; // Auto-scale gain
CNFG_RTOR_r.bits.pavg = 0b11; // 16-average
CNFG_RTOR_r.bits.ptsf = 0b0011; // PTSF = 4/16
CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
//Manage interrupts register setting
MAX30003::ManageInterrupts_u MNG_INT_r;
MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
//Enable interrupts register setting
MAX30003::EnableInterrupts_u EN_INT_r;
EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
EN_INT_r.bits.en_rrint = 1; // Enable R-to-R interrupt
EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
//Dyanmic modes config
MAX30003::ManageDynamicModes_u MNG_DYN_r;
MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
// MUX Config
MAX30003::MuxConfiguration_u CNFG_MUX_r;
CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
return;
}