AnsweredAssumed Answered

I2C communication: getting the wrong values!

Question asked by t.a on Jan 31, 2015
Latest reply on Feb 1, 2015 by t.a
Hei everybody,

I am using a barometric sensor MS5611-BA03 for measuring the height. The sensor pressure values should be around 1000 mb, but instead of that  I get -4895 mb. It's obvious, this can't be true. First, let me explain how it works. Through the I2C communication I get 8 variables: 6 coefficients that are needed for the calibration (offset, sensitivity and etc.), temperature and pressure value. Then I use some math, equations with the 8 variables to get the right format for the pressure value.

Here is the datasheet:ms5611

I assumed that the reason for getting the wrong number can only lay in the equations or I2C communication handling. What else, right? In the datasheet of the pressure sensor ms5611 is also an example on which values should the variables have. So, instead od the values that I get form the sensor, I inserted the example values and see if all goes in the right direction. Did this and the pressure was correct. So, the math algorithm is good.
Therefore the fault should be in the I2C communication. Luckily, I have got a logic analyzer and checked it. Data matched up, the bits from the analyzer and the debug watch window were the same. Okaaaaay...WHAT AM I MISSING? I still believe that the bug is in my code.

This is a project for the school and dealine is pretty near -_- Any help would be appreciated!
___________________________________________________________________________________________________________________________________________
The code for handling the I2C communication:

The size of the calibration coefficients are 16 bits long and just need to wait for 2 bytes. However, getting the pressure and temperature values is a little bit tricky. The data size is 24 bits long and in order to get the Temp and Press values, it is necessary  to send the command for converting the signal from analog to digital ( AD converter), wait converter to finish sampling and then send another command (ADC read) to shift out the data.

The code for calibration coefficients:
int cmd_prom(char coef_num)
{
 char Nbytes = 2;        // number of bytes
 char cobuf[2] = {0,0}; // buffer for the 2 bytes
 unsigned int temp;  //variable for storing the information
 
 /*Write the command to address coeficients-------------------------------------------------------------------------------*/
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_BUSY) != RESET); // wait if the bus is busy?
  
 I2C_TransferHandling(I2C_MS5611, ADDR, 1, I2C_AutoEnd_Mode, I2C_CR2_START); // Configure slave address, nbytes, reload, end mode and start or stop generation
   
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_TXIS) == RESET){};  // Wait until TXIS flag is set, waiting ACK
   
 I2C_SendData(I2C_MS5611, (uint8_t) CMD_PROM_C+ coef_num*2);// Send Register address
  
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_STOPF) == RESET){}; // Wait until STOPF flag is set
   
 I2C_ClearFlag(I2C_MS5611, I2C_ICR_STOPCF); // Clear STOPF flag
 
 Delay_ms(1);  
      
/*Read the values-----------------------------------------------------------------------------------------------------------*/
   
  I2C_TransferHandling(I2C_MS5611, ADDR_R, Nbytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Read); // Configure I2C handling
  
            while(Nbytes)
            {  
            while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_RXNE) == RESET); // Wait for the ACK bit
            cobuf [Nbytes-1]= I2C_ReceiveData(I2C_MS5611); // save data to cobuf
            Nbytes--;
            }
  
  while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_STOPF) == RESET){};// Wait until STOPF flag is set
   
  I2C_ClearFlag(I2C_MS5611, I2C_ICR_STOPCF); // Clear STOPF flag
     
 // this is right, because I give MSByt in the location cobuf[1] and the LSByte in cobuf[0]
 temp = (((int)cobuf[1])<<8) | cobuf[0];
 return temp;
 }

The code for Temp and Press values:

int32_t cmd_adc(uint8_t ComandAddr)
{
 char Nbytes = 3;
 char cobuf[3] = {0,0,0}; //buffer for saving the values that I get from RXDR
 int32_t temp;                    //temporary buffer
  
 /*Write the command to address the Dx constans-------------------------------------------------------------------------------*/
  
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_BUSY) != RESET);   //look if the bus is busy?
  
 I2C_TransferHandling(I2C_MS5611, ADDR, 1, I2C_AutoEnd_Mode, I2C_CR2_START); //Configure slave address, nbytes, reload, end mode and start or stop generation
  
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_TXIS) == RESET){};   //Wait until TXIS flag is set
   
 I2C_SendData(I2C_MS5611, (uint8_t) ComandAddr); //Send Register address
  
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_STOPF) == RESET){};  //Wait until STOPF flag is set
   
 I2C_ClearFlag(I2C_MS5611, I2C_ICR_STOPCF);  //Clear STOPF flag
  
 Delay_ms(10); //wait 9ms because the ADC in OSR= 4096 and it needs so long
      
 /*Write the command to read ADC result-----------------------------------------------------------------------------------*/
      
 I2C_TransferHandling(I2C_MS5611, ADDR, 1, I2C_AutoEnd_Mode, I2C_CR2_START);//Configure slave address, nbytes, reload, end mode and start or stop generation
  
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_TXIS) == RESET){}; // Wait until TXIS flag is set
   
 I2C_SendData(I2C_MS5611, (uint8_t) 0x00); // Send Register address
      
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_STOPF) == RESET){}; // Wait until STOPF flag is set
   
 I2C_ClearFlag(I2C_MS5611, I2C_ICR_STOPCF);  // Clear STOPF flag
      
 /*Read the values-----------------------------------------------------------------------------------*/
      
 I2C_TransferHandling(I2C_MS5611, ADDR, Nbytes, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);//Configure slave address, nbytes (to read), reload, end mode and start or stop generation
 
        while(Nbytes)
        {
        while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_RXNE) == RESET);// Wait until RXNE flag is set
        cobuf [Nbytes-1]= I2C_ReceiveData(I2C_MS5611); // Read data from RXDR  
        Nbytes--;
        }
         
 while(I2C_GetFlagStatus(I2C_MS5611, I2C_ISR_STOPF) == RESET){};// Wait until STOPF flag is set
   
 I2C_ClearFlag(I2C_MS5611, I2C_ICR_STOPCF);// Clear STOPF flag
             
 temp = (cobuf[2]<<16) | (cobuf[1]<<8) | cobuf[0];//this is right, because I give MSByt in the location cobuf[2] and the LSByte in cobuf[0]
 return temp;
}

Outcomes