CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

MPL3115 code for PIC24? [WORKS - CLOSED]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

MPL3115 code for PIC24? [WORKS - CLOSED]
PostPosted: Thu Oct 29, 2020 9:47 pm     Reply with quote

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: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Sun Nov 29, 2020 8:31 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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