|
|
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
MPL3115 code for PIC24? [WORKS - CLOSED] |
Posted: Thu Oct 29, 2020 9:47 pm |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
Hi guys,
Anyone has simple working code for the MPL3115A2 pressure sensor from NXP in polling altimeter mode? I wrote some code that somewhat works but I'd like to compare with other known working code. I find that the values returned, even when polling every second, swing a lot, perhaps a bit too much for my taste. I was expecting to see something much more stable but it seems that the altitude, just sitting there, swings by 1-2 feet, sometimes even more. I'm curious to test other code.
I may have to contact NXP for support, I'll also check on their support page.
Code: |
typedef struct
{
unsigned int8 AltitudeIntegerMSB;
unsigned int8 AltitudeIntegerCSB;
unsigned int8 AltitudeIntegerLSB;
float fAltitude;
unsigned int8 ID;
} SALTIMETER;
SALTIMETER ALT;
//-------------------------------------
unsigned int8 ALT_Initialize( unsigned int8 MsgID )
{
ALT.ID = PROTOCOL_Read_I2C( 0xC0, 0x0C );
delay_ms( 10 );
if( ALT.ID == ALT_MANUFACTURER_ID )
{
ALT.IsInitialized = TRUE;
return( TRUE );
}
ALT.ID = 0;
return( FALSE );
ALT.Register = PROTOCOL_Read_I2C( 0xC0, ALT_CTRL_REG1 );
ALT.Register = ALT.Register | 0x80;
PROTOCOL_Write_I2C( 0xC0, ALT_CTRL_REG1, ALT.Register );
delay_ms( 10 );
// Set oversample rate
ALT.Register = PROTOCOL_Read_I2C( 0xC0, ALT_CTRL_REG1 );
ALT.Register = ALT.Register | 0x38; // xx111xxx -> 128
PROTOCOL_Write_I2C( 0xC0, ALT_CTRL_REG1, ALT.Register );
// Enable event flags
PROTOCOL_Write_I2C( 0xC0, ALT_PT_DATA_CFG, 0x07 );
delay_ms( 10 );
return( ALT.ID );
}
//-------------------------------------
void ALT_ToggleOneShot( void )
{
// Clear OST bit
ALT.Register = PROTOCOL_Read_I2C( 0xC0, ALT_CTRL_REG1 );
ALT.Register = ALT.Register & 0xFD; // Force OSD bit to 0
PROTOCOL_Write_I2C( 0xC0, ALT_CTRL_REG1, ALT.Register );
// Set OST bit
ALT.Register = PROTOCOL_Read_I2C( 0xC0, ALT_CTRL_REG1 );
ALT.Register = ALT.Register | 0x02; // Force OSD bit to 1
PROTOCOL_Write_I2C( 0xC0, ALT_CTRL_REG1, ALT.Register );
}
//-------------------------------------
void ALT_ReadAltitude( void )
{
ALT_ToggleOneShot();
// Read altimeter PDR flag
while(( PROTOCOL_Read_I2C( 0xC0, ALT_STATUS ) & 0x04 ) == 0x00 )
{
// Here, have a counter that will exit if so many milliseconds have elapsed
}
//-----------------------------------------
// Altitude
//-----------------------------------------
// OUT_P_MSB: Contains integer MSB part in meters
// OUT_P_CSB: Contains integer LSB part in meters
// OUT_P_LSB: Contains fractional part
ALT.AltitudeIntegerMSB = PROTOCOL_Read_I2C( 0xC0, ALT_OUT_P_MSB );
delay_ms( 10 );
ALT.AltitudeIntegerCSB = PROTOCOL_Read_I2C( 0xC0, ALT_OUT_P_CSB );
delay_ms( 10 );
ALT.AltitudeIntegerLSB = PROTOCOL_Read_I2C( 0xC0, ALT_OUT_P_LSB );
delay_ms( 10 );
ALT.fAltitude = ((float) (( ALT.AltitudeIntegerMSB << 8 ) | ALT.AltitudeIntegerCSB )) + ((float) (ALT.AltitudeIntegerLSB >> 4) * 0.0625 );
//-----------------------------------------
// Temperature
//-----------------------------------------
// Read temperature integer
ALT.TemperatureMSB = PROTOCOL_Read_I2C( 0xC0, ALT_OUT_T_MSB );
// Read temperature decimals
ALT.TemperatureLSB = PROTOCOL_Read_I2C( 0xC0, ALT_OUT_T_LSB );
// OUT_T_MSB: Contains the integer part in °C
// OUT_T_LSB: Contains the fractional part
// Left shift OUT_T_MSB byte by 8 bits into a 16-bit variable and
// bitwise-OR OUT_T_LSB byte to give the temperature in °C, times 256.
// Adjust 4-bit temperature decimals to reflect 1/16th steps
ALT.Temperature = ALT.TemperatureMSB << 8;
ALT.fTemperature = ( ALT.Temperature | ALT.TemperatureLSB ) / 256;
ALT_ToggleOneShot();
}
|
With the code above, I have a 1 second timer getting the data and displaying it and this is the output which makes no sense (no, I am not in outer space):
Current altitude: 214405.3ft (65359.50m) -- Temperature: 32.0C
Current altitude: 214404.8ft (65359.37m) -- Temperature: 32.0C
Current altitude: 214404.4ft (65359.25m) -- Temperature: 32.0C
Current altitude: 214404.0ft (65359.12m) -- Temperature: 32.0C
Changing the types for AltitudeIntegerMSB/CSB/LSB from unsigned int8 to signed int8 returns the following which makes a bit more sense but I guess there's some error in there:
Current altitude: -579.8ft (-176.75m) -- Temperature: 31.0C
Current altitude: -578.7ft (-176.43m) -- Temperature: 31.0C
Current altitude: -581.6ft (-177.31m) -- Temperature: 31.0C
Current altitude: -581.4ft (-177.25m) -- Temperature: 31.0C
Current altitude: -579.6ft (-176.68m) -- Temperature: 31.0C
So it makes more sense but the swing is quite wide. First time I play around with an altimeter so I may have overlooked some configuration details.... Given that these things are calibrated at sea level, I'm not high, perhaps 200m or less above sea level in Ottawa, Canada. So I would have expected an approximate value of my altitude from sea level....
Good night. Bed time and thanks for any pointers. When I get something working I'll post it in the working code folder on the forum.
Thanks.
Ben
Ottawa, Canada
Last edited by benoitstjean on Sun Nov 29, 2020 8:36 am; edited 2 times in total |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Sun Nov 29, 2020 8:31 am |
|
|
Had forgotten about this post. Here's what I have that works in case anyone is interested... This sensor can do lots but this is good for me. I guess I had overlooked the 2's complement part.
in .h file:
Code: |
unsigned int8 AltitudeIntegerMSB; // Integer MSB
unsigned int8 AltitudeIntegerCSB; // Integer CSB
unsigned int8 AltitudeIntegerLSB; // Integer LSB
float fAltitude; // Altitude samples
//----- Temperature parameters -----
unsigned int8 TemperatureMSB; // Temperature integer
unsigned int8 TemperatureLSB; // Temperature decimals 4-bit (1/16th steps)
float fTemperature;
|
In .c file:
Code: |
void Initialize_altimeter( void )
{
// Set in altimeter mode with OSR = 128
Write_I2C( 0xC0, 0x26, 0xB8 );
delay_ms( 10 );
// Enable event flags
Write_I2C( 0xC0, 0x13, 0x07 );
delay_ms( 10 );
// Set active
Write_I2C( 0xC0, 0x26, 0xB9 );
delay_ms( 10 );
}
void Read_altitude( void )
{
int32 Integer = 0;
// Read altimeter 'busy' flag
while(( Read_I2C( 0xC0, 0x00 ) & 0x08 ) != 0x08 )
{
// Add some means (e.g. timer) of exiting to prevent while loop from getting stuck here.
}
//--------- Altitude ---------
// Read MSB of altitude integer
AltitudeIntegerMSB = Read_I2C( 0xC0, 0x01 );
delay_ms( 10 );
// Read CSB of altitude integer
AltitudeIntegerCSB = Read_I2C( 0xC0, 0x02 );
delay_ms( 10 );
// Read LSB of altitude integer
AltitudeIntegerLSB = Read_I2C( 0xC0, 0x03 );
delay_ms( 10 );
// Encompass bytes in single value
Integer = (( int32 ) AltitudeIntegerMSB << 24 ) | (( int32 ) AltitudeIntegerCSB << 16 ) | (( int32 ) AltitudeIntegerLSB << 8 );
// Check if value is negative
if( AltitudeIntegerMSB > 0x7F )
{
// Perform 2's complement: invert all bits then add 1
Integer != Integer + 1;
}
// Divide by 65536 to get altitude
fAltitude = (float)Integer / 65536;
//-------- Temperature --------
// Read temperature integer
TemperatureMSB = Read_I2C( 0xC0, 0x04 );
delay_ms( 10 );
// Read temperature decimals
TemperatureLSB = Read_I2C( 0xC0, 0x05 );
delay_ms( 10 );
// Encompass bytes in single value
Integer = ((int32) TemperatureMSB << 8 ) | ((int32) TemperatureLSB );
// Check if value is negative
if( TemperatureMSB > 0x7F )
{
// Perform 2's complement.
Integer != Integer + 1;
}
// Divide by 256 to get temperature
fTemperature = (float) Integer / 256;
}
|
Enjoy.
Ben |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|