2019-06-23 02:55 AM
Dear Members,
I try to translate this paragraph in datasheet :
FIFO Data
The circular FIFO depth is 16 and can hold up to 16 samples of SpO2 channel data (Red and IR). The FIFO_DATA register in the I2C register map points to the next sample to be read from the FIFO. FIFO_RD_PTR points to this sample. Reading FIFO_DATA register does not automatically increment the register address; burst reading this register reads the same address over and over. Each sample is 4 bytes of data, so this register has to be read 4 times to get one sample.
The above registers can all be written and read, but in practice, only the FIFO_RD_PTR register should be written to in operation. The others are automatically incremented or filled with data by the MAX30100. When starting a new SpO2
or heart-rate conversion, it is recommended to first clear the FIFO_WR_PTR, OVF_COUNTER, and FIFO_RD_PTR registers to all zeros (0x00) to ensure the FIFO is empty and in a known state. When reading the MAX30100 registers in one burst-read I2C transaction, the register address pointer typically increments so that the next byte of data sent is from the next register, etc. The exception to this is the FIFO data register, register 0x05. When reading this register, the address pointer does not increment, but the FIFO_RD_PTR does. So the next byte of data sent will represent the next byte of data available in the FIFO.
Reading from the FIFO
Normally, reading registers from the I2C interface autoincrements the register address pointer, so that all the registers can be read in a burst read without an I2C restart event. In the MAX30100, this holds true for all registers except for the FIFO_DATA register (0x05).
Reading the FIFO_DATA register does not automatically increment the register address; burst reading this register reads the same address over and over. Each sample is 4 bytes of data, so this register has to be read 4 times to get one sample.
The other exception is 0xFF, reading more bytes after the 0xFF register does not advance the address pointer back to 0x00, and the data read is not meaningful.
FIFO Data Structure
The data FIFO consists of a 16-sample memory bank that stores both IR and RED ADC data. Since each sample consists of one IR word and one RED word, there are 4 bytes of data for each sample, and therefore, 64 total bytes of data can be stored in the FIFO. Figure 2 shows the structure of the FIFO graphically.
The FIFO data is left-justified as shown in Table 1; i.e. the MSB bit is always in the bit 15 position regardless of ADC resolution.
Each data sample consists of an IR and a red data word (2 registers), so to read one sample requires 4 I2C byte reads in a row. The FIFO read pointer is automatically incremented after each 4-byte sample is read.
In heart-rate only mode, the 3rd and 4th bytes of each sample return zeros, but the basic structure of the FIFO remains the same.
Could you please correct me ?
I got the value of SPO2 and HeartRate, but Heart Rate is always over the normal calculation,
over 200 always...??
The code :
un_min=0x3FFFF;
un_max=0;
n_ir_buffer_length = 500;
for(i=0;i<n_ir_buffer_length;i++)
{
HAL_I2C_Master_Receive(&hi2c2, 0xAF, buffer_rx ,4,25); //receive 4 bytes from MAX30100
aun_ir_buffer[i] = ((long)(long)(buffer_rx[0] << 8)) | (long)buffer_rx[1];
aun_red_buffer[i] = ((long)(long)(buffer_rx[2] << 8)) | (long)buffer_rx[3];
if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i]; //update signal min
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i]; //update signal max
} //end loop
un_prev_data=aun_red_buffer[i];
maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
printf("SPO2 = %i ",n_sp02);
printf("SPO2Valid=%i \r\n", ch_spo2_valid);
printf("Heart Rate = %i ",n_heart_rate);
printf("HRvalid=%i \r\n ", ch_hr_valid);
Thanks for reading
2019-06-23 03:05 AM
uint8_t buffer_rx[32*4];
2019-06-23 03:47 AM
Put this post in Maxim forum, seems to be that the device handling has specifics regardless of which MCU is accessing it.
Do they provide pseudo code, C source files, something? Sensirion, ST, Bosch do this, Check on mbed, github.
2019-06-23 06:31 AM
Pseudo code :
START;
Send device address + write mode
Send address of FIFO_DATA;
REPEATED_START;
Send device address + read mode
for (i = 0; i < NUM_SAMPLES_TO_READ; i++) {
Read FIFO_DATA;
Save IR[15:8];
Read FIFO_DATA;
Save IR[7:0];
Read FIFO_DATA;
Save R[15:8];
Read FIFO_DATA;
Save R[7:0];
}
STOP;
2019-06-23 08:33 AM
Says the FIFO contains 16 words, you read 500.
Perhaps you should inspect whole I2C transaction, and review on a scope or logic analyser.
I'd probably approach as a 64 byte read, and then translate big endian data from there.
Use of (long)(long) seems unnecessary.
2019-06-23 07:36 PM
Clive, I got a good result from I2C :
The output from MAX30100, from 0xFE register (Revision ID) First byte : 5
The output from MAX30100, from 0xFF register (PART ID) First byte : 11
The output from MAX30100, from 0x16 register (Temp Int) First byte : 20 hex
The output from MAX30100, from 0x17 register (Temp Fraction) First byte : 4 he
x
TEMP FRACT : 0.250000
TEMP INT : 32.000000
Measured temperature output from MAX30100, from 0x16 and 0x17 register (Temp) Fi
rst byte : 32.250000
The output from MAX30100, from 0x07 register (SP O2 Config) : 4 hex
The output from MAX30100, from 0x09 register (LED Config) : CC hex
The output from MAX30100, from 0x06 register (MODE Config) : 3 hex
The output from MAX30100, from 0x02 register (WR_PTR) : 9 hex
The output from MAX30100, from 0x03 register (OVR_COUNTER) : F hex
The output from MAX30100, from 0x04 register (RD_PTR) : 0 hex
SPO2 = 88 SPO2Valid=1
Heart Rate = 260 HRvalid=1
But the calculation is a bit odd for heart rate on 260, proably only 80, should I change the formula ??
// flip wave form so that we can detect valley with peak detector
for ( i=0 ; i<BUFFER_SIZE-HAMMING_SIZE-MA4_SIZE-2 ;i++){
s= 0;
for( k=i; k<i+ HAMMING_SIZE ;k++){
s -= an_dx[k] *auw_hamm[k-i] ;
}
an_dx[i]= s/ (int32_t)1146; // divide by sum of auw_hamm
}
n_th1=0; // threshold calculation
for ( k=0 ; k<BUFFER_SIZE-HAMMING_SIZE ;k++){
n_th1 += ((an_dx[k]>0)? an_dx[k] : ((int32_t)0-an_dx[k])) ;
}
n_th1= n_th1/ ( BUFFER_SIZE-HAMMING_SIZE);
// peak location is acutally index for sharpest location of raw signal since we flipped the signal
maxim_find_peaks( an_dx_peak_locs, &n_npks, an_dx, BUFFER_SIZE-HAMMING_SIZE, n_th1, 8, 5 );//peak_height, peak_distance, max_num_peaks
n_peak_interval_sum =0;
if (n_npks>=2){
for (k=1; k<n_npks; k++)
n_peak_interval_sum += (an_dx_peak_locs[k]-an_dx_peak_locs[k -1]);
n_peak_interval_sum=n_peak_interval_sum/(n_npks-1);
*pn_heart_rate=(int32_t)(6000/n_peak_interval_sum);// beats per minutes
*pch_hr_valid = 1;
}
Is it because of a wrong coefficient on hamming window filter ?
Thanks