cancel
Showing results for 
Search instead for 
Did you mean: 

I2C and FIFO STM32L152 ?

antonius
Senior

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

5 REPLIES 5
antonius
Senior
uint8_t buffer_rx[32*4];

S.Ma
Principal

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.

antonius
Senior

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;

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.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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