cancel
Showing results for 
Search instead for 
Did you mean: 

I2C communication: getting the wrong values!

esovo1
Associate II
Posted on January 31, 2015 at 22:43

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:

http://www.meas-spec.com/downloads/MS5611-01BApdf

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;
}

#i2c-stm32
2 REPLIES 2
Posted on January 31, 2015 at 22:50

Having data stored in a ''char'' and promoting it to an ''int'' seems like a VERY bad plan.

''unsigned char'' and ''unsigned int'', and use them CONSISTENTLY

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
esovo1
Associate II
Posted on February 01, 2015 at 13:00

Tnx clive, but the core problem is stil there. So, maybe the problem isn't in the code....or?