Hello Thomas,
Thanks for the reply! Very appreciated!
Yes I do remember your messages and I did re-read them but I think there's still a few things I'm just not grasping. The equation in your response is also what I use to convert raw values to meters in altimeter mode but your overall response still doesn't quite answer all my questioning unfortunately. Sorry, I'm just trying to make sense of what I am reading through different documents and correlate that with what I am seeing as the output from my sensor. Maybe what I am getting is fine and I'm just not interpreting it correctly because the documentation is confusing me.
As for the 0 offset, I will deal with that later. I think the root problem is the understanding on how to interpret and convert the returned values correctly. I seem to be mis-understanding / mis-interpreting different explanations between documents.
I'll go back to basics. Here's my code:
//----- Initialization()
// Altimeter set to ALTITUDE mode (Register 0x26h, bit 7)
Register = Read_I2C( 0xC0, 0x26 );
Register = Register | 0x80; // Force to altitude mode on bit 7
Write_I2C( 0xC0, 0x26, Register );
delay_ms( 10 );
Write_I2C( 0xC0, 0x13, 0x07 );
delay_ms( 10 );
Write_I2C( 0xC0, 0x26, 0xB9 );
delay_ms( 10 );
//----- ReadAltitude()
// Read altimeter 'busy' flag
while(( Read_I2C( 0xC0, 0x00 ) & 0x08 ) != 0x08 );
// Read registers
MSB = Read_I2C( 0xC0, 0x01 );
delay_ms( 10 );
CSB = Read_I2C( 0xC0, 0x02 );
delay_ms( 10 );
LSB = Read_I2C( 0xC0, 0x03 );
delay_ms( 10 );
printf( "\n\rMSB: %02X, CSB: %02X, LSB: %02X (Decimal: %0.3f)", MSB, CSB, LSB, ((float) (LSB >> 4) * 0.0625 ));
Here's the output for 30 seconds at 1 sample per second:
MSB: FF, CSB: 84, LSB: 80 (Decimal: 0.500)
MSB: FF, CSB: 84, LSB: 50 (Decimal: 0.312)
MSB: FF, CSB: 84, LSB: D0 (Decimal: 0.812)
MSB: FF, CSB: 84, LSB: F0 (Decimal: 0.937)
MSB: FF, CSB: 84, LSB: 90 (Decimal: 0.562)
MSB: FF, CSB: 84, LSB: E0 (Decimal: 0.875)
MSB: FF, CSB: 85, LSB: 40 (Decimal: 0.250)
MSB: FF, CSB: 85, LSB: 30 (Decimal: 0.187)
MSB: FF, CSB: 84, LSB: 90 (Decimal: 0.562)
MSB: FF, CSB: 84, LSB: E0 (Decimal: 0.875)
MSB: FF, CSB: 84, LSB: E0 (Decimal: 0.875)
MSB: FF, CSB: 84, LSB: B0 (Decimal: 0.687)
MSB: FF, CSB: 84, LSB: B0 (Decimal: 0.687)
MSB: FF, CSB: 84, LSB: F0 (Decimal: 0.937)
MSB: FF, CSB: 84, LSB: B0 (Decimal: 0.687)
MSB: FF, CSB: 84, LSB: 60 (Decimal: 0.375)
MSB: FF, CSB: 83, LSB: 20 (Decimal: 0.125)
MSB: FF, CSB: 83, LSB: 70 (Decimal: 0.437)
MSB: FF, CSB: 83, LSB: 20 (Decimal: 0.125)
MSB: FF, CSB: 83, LSB: 50 (Decimal: 0.312)
MSB: FF, CSB: 83, LSB: 80 (Decimal: 0.500)
MSB: FF, CSB: 83, LSB: 60 (Decimal: 0.375)
MSB: FF, CSB: 83, LSB: 50 (Decimal: 0.312)
MSB: FF, CSB: 83, LSB: 40 (Decimal: 0.250)
MSB: FF, CSB: 83, LSB: 40 (Decimal: 0.250)
MSB: FF, CSB: 84, LSB: 40 (Decimal: 0.250)
MSB: FF, CSB: 84, LSB: 00 (Decimal: 0.000)
MSB: FF, CSB: 83, LSB: B0 (Decimal: 0.687)
MSB: FF, CSB: 84, LSB: 10 (Decimal: 0.062)
MSB: FF, CSB: 83, LSB: 70 (Decimal: 0.437)
The decimal portion seems to make sense. The problem I am having a hard time figuring-out is the integer part. I looked at a few NXP documents and I am understanding explanations differently between documents and I think this is what is confusing me.
In the main MPL3115 NXP datasheet page 14 section 6.2, it says "altitude is stored as 20-bit 2’s complement value in meters and fractions of a meter". Then on page 21 section 7.1.3 in the same document, it says "The Altitude data is stored as a signed fractional 20-bit value in meters in Q16.4 format. The OUT_P_MSB and OUT_P_CSB registers contain the integer part in meters and the OUT_P_LSB register contains the fractional part. Left shifting the OUT_P_MSB byte by 24 bits into a 32 variable and doing a logical OR with the OUT_P_CSB byte left shifted 16 bits and a logical OR with the OUT_T_LSB byte left shifted 8 bits gives the altitude in meters times 65536."
Then if you read AN4519 from NXP, page 9 section5.1 Converting a 20-bit Altitude reading to a signed decimal number:
The 20-bit measurement in meters is comprised of a signed integer component and a fractional component. The signed 16-bit integer component located in OUT_P_MSB and OUT_P_CSB. The fraction component is located in bits 7-4 of OUT_P_LSB. Bits 3-0 of OUT_P_LSB are not used. The sign of the result is easy to determine by simply checking if the high byte of the value is greater than 0x7F. If so, then the value is a negative number and needs to be transformed by performing a 2’s complement conversion. This involves executing a 1’s complement (i.e., switch all 1’s to 0’s and all 0’s to 1’s) and followed by adding 1 to the result.
In this NXP document, it now says that if the high-byte value is greater than 0x7F, it's because the value is negative but that is not explicitely explained in the main datasheet or it's a misunderstanding on my part.
So now: how/where do I apply the 2's complement? To the high byte only? Or the entire 16-bit integer portion only? Or the full 24-bit value?
Again using MSB: FF, CSB: 83, LSB: 70:
Question 1) To you, do they make any sense at all when interpreted as individual bytes?
Question 2) If you were to use that last sample from my example, what altitude do you get from this sample and how do you do the calculation to get to that value (e.g. please provide exact steps)?
Does it make more sense as to what I am not understanding?
Thanks again, your time and help is very appreciated!
Sorry for the length and sorry for the confusion. Meanwhile I will re-read the documentation I have on-hand.
Ben