Llibrary for the WiGo MPL3115A2, I2C Precision Altimeter sensor.

Dependents:   KL25Z_Batt_Test WIGO_MPL3115A2 Multi-Sensor SPACEmk2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MPL3115A2.cpp Source File

MPL3115A2.cpp

00001 /*   MPL3115A2 I2C precision pressure sensor with altimetry Library
00002 *
00003 *    @author: Clemente di Caprio 
00004 *    @date: September 24, 2013
00005 *    @license: Apache License, Version 2.0
00006 *
00007 * Licensed under the Apache License, Version 2.0 (the "License");
00008 * you may not use this file except in compliance with the License.
00009 * You may obtain a copy of the License at
00010 *
00011 *     http://www.apache.org/licenses/LICENSE-2.0
00012 *
00013 * Unless required by applicable law or agreed to in writing, software
00014 * distributed under the License is distributed on an "AS IS" BASIS,
00015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016 * See the License for the specific language governing permissions and
00017 * limitations under the License.
00018 */
00019 
00020 #include "MPL3115A2.h"
00021 
00022 #define REG_WHO_AM_I        0x0C        // return 0xC4 by default
00023 #define REG_STATUS          0x00
00024 #define REG_CTRL_REG_1      0x26
00025 #define REG_CTRL_REG_3      0x28
00026 #define REG_CTRL_REG_4      0x29
00027 #define REG_CTRL_REG_5      0x2A
00028 #define REG_PRESSURE_MSB    0x01        // 3 byte pressure data
00029 #define REG_ALTIMETER_MSB   0x01        // 3 byte altimeter data
00030 #define REG_TEMP_MSB        0x04        // 2 byte temperature data
00031 #define REG_PT_DATA_CFG     0x13
00032 #define REG_P_TGT_MSB       0x16
00033 #define REG_P_WND_MSB       0x19
00034 #define REG_OFF_P           0x2b
00035 #define REG_OFF_T           0x2c
00036 #define REG_OFF_H           0x2d
00037 #define REG_PRES_MIN_MSB    0x1c
00038 #define REG_ALTI_MIN_MSB    0x1c
00039 #define REG_TEMP_MIN_MSB    0x1f
00040 #define REG_PRES_MAX_MSB    0x21
00041 #define REG_ALTI_MAX_MSB    0x21
00042 #define REG_TEMP_MAX_MSB    0x24
00043 #define REG_PRES_DELTA_MSB  0x07
00044 #define REG_ALTI_DELTA_MSB  0x07
00045 #define REG_TEMP_DELTA_MSB  0x0a
00046 
00047 
00048 #define UINT14_MAX        16383
00049 
00050 // Status flag for data ready.
00051 #define PTDR_STATUS       0x03        // Pressure Altitude and Temperature ready
00052 #define PDR_STATUS        0x02        // Pressure and Altitude data ready
00053 #define TDR_STATUS        0x01        // Temperature data ready
00054 
00055 /** Interrupt schema
00056 *
00057 * :: The Altitude Trigger use the IRQ1.
00058 * 
00059 *   Altitude Trigger -- MPL3115A2_Int1.fall --- AltitudeTrg_IRQ --- MPL3115A2_usr1_fptr
00060 *
00061 *
00062 * :: The Data ready use the IRQ2. 
00063 *
00064 *   Data Ready -- MPL3115A2_Int2.fall --- DataReady_IRQ --- MPL3115A2_usr2_fptr
00065 *
00066 */
00067 void (*MPL3115A2_usr2_fptr)(void);               // Pointers to user function called after
00068 void (*MPL3115A2_usr1_fptr)(void);               // IRQ assertion.
00069 
00070 //
00071 InterruptIn MPL3115A2_Int1( PTD4);       // INT1
00072 InterruptIn MPL3115A2_Int2( PTA12);      // INT2
00073 
00074 MPL3115A2::MPL3115A2(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) {
00075     unsigned char data[6];
00076     
00077     MPL3115A2_mode = BAROMETRIC_MODE;
00078     MPL3115A2_oversampling = OVERSAMPLE_RATIO_1;
00079     //
00080     MPL3115A2_usr1_fptr = NULL;
00081     MPL3115A2_usr2_fptr = NULL;
00082     MPL3115A2_Int1.fall( NULL);
00083     MPL3115A2_Int2.fall( NULL);
00084     
00085     Reset();
00086     
00087     data[0]=REG_PRES_MIN_MSB;
00088     data[1]=0;data[2]=0;data[3]=0;data[4]=0;data[5]=0;
00089     writeRegs( &data[0], 6);
00090 }
00091 
00092 void MPL3115A2::Reset( void)
00093 {
00094     unsigned char t;
00095     
00096     // soft reset...
00097     readRegs( REG_CTRL_REG_1, &t, 1);
00098     unsigned char data[2] = { REG_CTRL_REG_1, t|0x04};
00099     writeRegs(data, 2);    
00100     wait( 0.1);
00101 
00102 }
00103 
00104 void MPL3115A2::DataReady( void(*fptr)(void), unsigned char OS)
00105 {
00106     unsigned char dt[5];
00107     unsigned char data[2];
00108     
00109     // Soft Reset
00110     Reset();
00111     
00112     Standby();
00113     
00114     // Clear all interrupts by reading the output registers.
00115     readRegs( REG_ALTIMETER_MSB, &dt[0], 5);
00116     getStatus();
00117     // Configure INT active low and pullup
00118     data[0] = REG_CTRL_REG_3;
00119     data[1] = 0x00;
00120     writeRegs(data, 2);    
00121     // Enable Interrupt fot data ready
00122     data[0] = REG_CTRL_REG_4;
00123     data[1] = 0x80;
00124     writeRegs(data, 2);    
00125     // Configure Interrupt to route to INT2
00126     data[0] = REG_CTRL_REG_5;
00127     data[1] = 0x00;
00128     writeRegs(data, 2);    
00129     data[0] = REG_PT_DATA_CFG;
00130     data[1] = 0x07;
00131     writeRegs(data, 2);    
00132 
00133     // Configure the OverSampling rate, Altimeter/Barometer mode and set the sensor Active
00134     data[0] = REG_CTRL_REG_1;
00135     data[1] = (OS<<3);
00136     //
00137     if (MPL3115A2_mode == BAROMETRIC_MODE)
00138         data[1] &= 0x7F;
00139     else
00140         data[1] |= 0x80;
00141     //
00142     data[1] |= 0x01; 
00143     writeRegs(data, 2);    
00144 
00145     MPL3115A2_usr2_fptr = fptr;
00146     MPL3115A2_Int2.fall( this, &MPL3115A2::DataReady_IRQ);
00147 
00148 }
00149 
00150 void MPL3115A2::DataReady_IRQ( void)
00151 {
00152     // Clear the IRQ flag
00153     getStatus();
00154     // Run the user supplied function
00155     MPL3115A2_usr2_fptr();   
00156 }
00157 
00158 void MPL3115A2::AltitudeTrigger( void(*fptr)(void), unsigned short level)
00159 {
00160     unsigned char dt[5];
00161     unsigned char data[2];
00162 
00163     // Soft Reset
00164     Reset();
00165     
00166     // The device is on standby
00167     Standby();
00168     
00169     // Clear all interrupts by reading the output registers.
00170     readRegs( REG_ALTIMETER_MSB, &dt[0], 5);
00171     getStatus();
00172 
00173     // Write Target and Window Values
00174     dt[0] = REG_P_TGT_MSB;
00175     dt[1] = (level>>8);
00176     dt[2] = (level&0xFF);
00177     writeRegs( dt, 3);
00178     
00179     // Window values are zero
00180     dt[0] = REG_P_WND_MSB;
00181     dt[1] = 0;
00182     dt[2] = 0;
00183     writeRegs( dt, 3);
00184 
00185     // Enable Pressure Threshold interrupt
00186     data[0] = REG_CTRL_REG_4;
00187     data[1] = 0x08;
00188     writeRegs( data, 2);
00189     // Interrupt is routed to INT1
00190     data[0] = REG_CTRL_REG_5;
00191     data[1] = 0x08;
00192     writeRegs( data, 2);
00193     data[0] = REG_PT_DATA_CFG;
00194     data[1] = 0x07;
00195     writeRegs(data, 2);    
00196     // Configure the OverSampling rate, Altimeter mode and set the sensor Active
00197     data[0] = REG_CTRL_REG_1;
00198     data[1] = 0x81 | (MPL3115A2_oversampling<<3);    
00199     writeRegs(data, 2);    
00200 
00201     MPL3115A2_usr1_fptr = fptr;
00202     MPL3115A2_Int1.fall( this, &MPL3115A2::AltitudeTrg_IRQ);
00203 
00204 }
00205 
00206 void MPL3115A2::AltitudeTrg_IRQ( void)
00207 {
00208     // Clear the IRQ flag
00209     getStatus();
00210     // Run the user supplied function
00211     MPL3115A2_usr1_fptr();   
00212 
00213 }
00214 
00215 void MPL3115A2::Barometric_Mode( void)
00216 {
00217     unsigned char t;
00218     unsigned char data[2];
00219     
00220     Standby();
00221 
00222     // soft reset...
00223     Reset();
00224         
00225     Standby();
00226     readRegs( REG_CTRL_REG_1, &t, 1);
00227     
00228     // Set the Barometric mode
00229     data[0] = REG_CTRL_REG_1;
00230     data[1] = t&0x7F;
00231     writeRegs(data, 2);    
00232 
00233     data[0] = REG_PT_DATA_CFG;
00234     data[1] = 0x07;
00235     writeRegs(data, 2);    
00236 
00237     Oversample_Ratio( MPL3115A2_oversampling);
00238     
00239     Active();
00240     
00241     MPL3115A2_mode = BAROMETRIC_MODE;
00242 }
00243 
00244 void MPL3115A2::Altimeter_Mode( void)
00245 {
00246     unsigned char t;
00247     unsigned char data[2];
00248     
00249     Standby();
00250 
00251     // soft reset...
00252     Reset();    
00253     
00254     Standby();
00255     readRegs( REG_CTRL_REG_1, &t, 1);
00256 
00257     data[0] = REG_CTRL_REG_1;
00258     data[1] = t|0x80;
00259     writeRegs(data, 2);    
00260 
00261     data[0] = REG_PT_DATA_CFG;
00262     data[1] = 0x07;
00263     writeRegs(data, 2);    
00264 
00265     Oversample_Ratio( MPL3115A2_oversampling);
00266     
00267     Active();
00268     
00269     MPL3115A2_mode = ALTIMETER_MODE;
00270 }
00271 
00272 void MPL3115A2::Oversample_Ratio( unsigned int ratio)
00273 {
00274     unsigned char t;
00275     
00276     Standby();
00277     readRegs( REG_CTRL_REG_1, &t, 1);
00278 
00279     t = t & 0xE7;
00280     t = t | ( ratio<<3);
00281 
00282     unsigned char data[2] = { REG_CTRL_REG_1, t};
00283     writeRegs(data, 2);    
00284 
00285     Active();
00286     
00287     MPL3115A2_oversampling = ratio;
00288 }
00289 
00290 
00291 void MPL3115A2::Active( void)
00292 {
00293     unsigned char t;
00294     
00295     // Activate the peripheral
00296     readRegs(REG_CTRL_REG_1, &t, 1);
00297     unsigned char data[2] = {REG_CTRL_REG_1, t|0x01};
00298     writeRegs(data, 2);
00299 }
00300 
00301 void MPL3115A2::Standby( void)
00302 {
00303     unsigned char t;
00304     
00305     // Standby
00306     readRegs(REG_CTRL_REG_1, &t, 1);
00307     unsigned char data[2] = {REG_CTRL_REG_1, t&0xFE};
00308     writeRegs(data, 2);
00309 }
00310 
00311 unsigned char MPL3115A2::getDeviceID() {
00312     unsigned char device_id = 0;
00313     readRegs(REG_WHO_AM_I, &device_id, 1);
00314     return device_id;
00315 }
00316 
00317 unsigned int MPL3115A2::isDataAvailable( void)
00318 {
00319     unsigned char status;
00320     
00321     readRegs( REG_STATUS, &status, 1);
00322 
00323     return ((status>>1));
00324     
00325 }
00326 
00327 unsigned char MPL3115A2::getStatus( void)
00328 {
00329     unsigned char status;
00330     
00331     readRegs( REG_STATUS, &status, 1);
00332     return status;
00333 }
00334 
00335 unsigned int MPL3115A2::getAllData( float *f)
00336 {
00337     if ( isDataAvailable() & PTDR_STATUS) {
00338         if ( MPL3115A2_mode == ALTIMETER_MODE) {
00339             f[0] = getAltimeter( REG_ALTIMETER_MSB);
00340         } else {
00341             f[0] = getPressure( REG_PRESSURE_MSB);
00342         }
00343         
00344         f[1] = getTemperature( REG_TEMP_MSB);
00345         //
00346         return 1;
00347     } else
00348         return 0;
00349 }
00350 
00351 unsigned int MPL3115A2::getAllData( float *f, float *d)
00352 {
00353     if ( isDataAvailable() & PTDR_STATUS) {
00354         if ( MPL3115A2_mode == ALTIMETER_MODE) {
00355             f[0] = getAltimeter();
00356             d[0] = getAltimeter( REG_ALTI_DELTA_MSB);
00357         } else {
00358             f[0] = getPressure();
00359             d[0] = getPressure( REG_PRES_DELTA_MSB);
00360         }
00361         
00362         f[1] = getTemperature();
00363         d[1] = getTemperature( REG_TEMP_DELTA_MSB);
00364         //
00365         return 1;
00366     } else
00367         return 0;
00368 }
00369 
00370 void MPL3115A2::getAllMaximumData( float *f)
00371 {
00372     if ( MPL3115A2_mode == ALTIMETER_MODE) {
00373         f[0] = getAltimeter( REG_ALTI_MAX_MSB);
00374     } else {
00375         f[0] = getPressure( REG_PRES_MAX_MSB);
00376     }
00377     
00378     f[1] = getTemperature( REG_TEMP_MAX_MSB);
00379 }
00380 
00381 void MPL3115A2::getAllMinimumData( float *f)
00382 {
00383     if ( MPL3115A2_mode == ALTIMETER_MODE) {
00384         f[0] = getAltimeter( REG_ALTI_MIN_MSB);
00385     } else {
00386         f[0] = getPressure( REG_PRES_MIN_MSB);
00387     }
00388     
00389     f[1] = getTemperature( REG_TEMP_MIN_MSB);
00390 }
00391 
00392 float MPL3115A2::getAltimeter( void)
00393 {
00394     float a;
00395     
00396     a = getAltimeter( REG_ALTIMETER_MSB);
00397     return a;
00398 }
00399 
00400 float MPL3115A2::getAltimeter( unsigned char reg)
00401 {
00402     unsigned char dt[3];
00403     unsigned short altm;
00404     short tmp;
00405     float faltm;
00406     
00407     /*
00408     * dt[0] = Bits 12-19 of 20-bit real-time Altitude sample. (b7-b0)
00409     * dt[1] = Bits 4-11 of 20-bit real-time Altitude sample. (b7-b0)
00410     * dt[2] = Bits 0-3 of 20-bit real-time Altitude sample (b7-b4)
00411     */
00412     readRegs( reg, &dt[0], 3);
00413     altm = (dt[0]<<8) | dt[1];
00414     //
00415     if ( dt[0] > 0x7F) {
00416         // negative number
00417         tmp = ~altm + 1;
00418         faltm = (float)tmp * -1.0f;
00419     } else {
00420         faltm = (float)altm * 1.0f;
00421     }
00422     //
00423     faltm = faltm+((float)(dt[2]>>4) * 0.0625f);
00424     return faltm;
00425 }
00426 
00427 float MPL3115A2::getPressure( void)
00428 {
00429     float a;
00430     
00431     a = getPressure( REG_PRESSURE_MSB);
00432     return a;
00433 }
00434 
00435 float MPL3115A2::getPressure( unsigned char reg)
00436 {
00437     unsigned char dt[3];
00438     unsigned int prs;
00439     int tmp;
00440     float fprs;
00441     
00442     /*
00443     * dt[0] = Bits 12-19 of 20-bit real-time Pressure sample. (b7-b0)
00444     * dt[1] = Bits 4-11 of 20-bit real-time Pressure sample. (b7-b0)
00445     * dt[2] = Bits 0-3 of 20-bit real-time Pressure sample (b7-b4)
00446     */
00447     readRegs( reg, &dt[0], 3);
00448     prs = ((dt[0]<<10) | (dt[1]<<2) | (dt[2]>>6));
00449     //
00450     if ( dt[0] > 0x7f) {
00451         // negative number
00452         if ( dt[0] & 0x80)
00453             prs |= 0xFFFC0000;      // set at 1 the bits to complete the word len
00454         else
00455             prs |= 0xFFFE0000;
00456         tmp = ~prs + 1;             // make the complemets. At this point all the bits are inverted.
00457         fprs = (float)tmp * -1.0f;  // set the signe..
00458     } else {
00459         fprs = (float)prs * 1.0f;
00460     }
00461 
00462     if ( dt[2] & 0x10)              // I did some experiment to set the fractional parte.
00463         fprs += 0.25f;              // ** Warning: the DS is wrong! **
00464     if ( dt[2] & 0x20)
00465         fprs += 0.5f;
00466         
00467     return fprs;
00468 }
00469 
00470 float MPL3115A2::getTemperature( void)
00471 {
00472     float a;
00473     
00474     a = getTemperature( REG_TEMP_MSB);
00475     return a;
00476 }
00477 
00478 float MPL3115A2::getTemperature( unsigned char reg)
00479 {
00480     unsigned char dt[2];
00481     unsigned short temp;
00482     float ftemp;
00483     
00484     /*
00485     * dt[0] = Bits 4-11 of 16-bit real-time temperature sample. (b7-b0)
00486     * dt[1] = Bits 0-3 of 16-bit real-time temperature sample. (b7-b4)
00487     */
00488     readRegs( reg, &dt[0], 2);
00489     temp = dt[0];
00490     //
00491     if ( dt[0] > 0x7F) {
00492         temp = ~temp + 1;
00493         ftemp = (float)temp * -1.0f;
00494     } else {
00495         ftemp = (float)temp * 1.0f;
00496     }
00497     //
00498     ftemp = ftemp+((float)(dt[1]>>4) * 0.0625f);
00499     return ftemp;
00500 
00501 }
00502 
00503 
00504 unsigned int MPL3115A2::getAllDataRaw( unsigned char *dt)
00505 {
00506     // Check for Press/Alti and Temp value ready
00507     if ( isDataAvailable() & PTDR_STATUS) {
00508         if ( MPL3115A2_mode == ALTIMETER_MODE) {
00509             getAltimeterRaw( &dt[0]);               // 3 bytes
00510         } else {
00511             getPressureRaw( &dt[0]);                   // 3 bytes
00512         }
00513         
00514         getTemperatureRaw( &dt[3]);                    // 2 bytes
00515         
00516         return 1;
00517     } else {
00518         return 0;
00519     }
00520 }
00521 
00522 unsigned int MPL3115A2::getAltimeterRaw( unsigned char *dt)
00523 {
00524     
00525     /*
00526     * dt[0] = Bits 12-19 of 20-bit real-time Pressure sample. (b7-b0)
00527     * dt[1] = Bits 4-11 of 20-bit real-time Pressure sample. (b7-b0)
00528     * dt[2] = Bits 0-3 of 20-bit real-time Pressure sample (b7-b4)
00529     */
00530     
00531     // Check for Press/Alti value ready
00532     if ( isDataAvailable() & PDR_STATUS) {
00533         readRegs( REG_ALTIMETER_MSB, &dt[0], 3);    
00534         return 1;
00535     } else
00536         return 0;
00537 }
00538 
00539 unsigned int  MPL3115A2::getPressureRaw( unsigned char *dt)
00540 {
00541     
00542     /*
00543     * dt[0] = Bits 12-19 of 20-bit real-time Pressure sample. (b7-b0)
00544     * dt[1] = Bits 4-11 of 20-bit real-time Pressure sample. (b7-b0)
00545     * dt[2] = Bits 0-3 of 20-bit real-time Pressure sample (b7-b4)
00546     */
00547     
00548     // Check for Press/Alti value ready
00549     if ( isDataAvailable() & PDR_STATUS) {
00550         readRegs( REG_PRESSURE_MSB, &dt[0], 3);
00551         return 1;
00552     } else 
00553         return 0;
00554         
00555 }
00556 
00557 unsigned int MPL3115A2::getTemperatureRaw( unsigned char *dt)
00558 {
00559     
00560     /*
00561     * dt[0] = Bits 4-11 of 16-bit real-time temperature sample. (b7-b0)
00562     * dt[1] = Bits 0-3 of 16-bit real-time temperature sample. (b7-b4)
00563     */
00564     
00565     // Check for Temp value ready
00566     if ( isDataAvailable() & TDR_STATUS) {
00567         readRegs( REG_TEMP_MSB, &dt[0], 2);
00568         return 1;
00569     } else
00570         return 0;        
00571 }
00572 
00573 void MPL3115A2::SetPressureOffset( char offset)
00574 {
00575     unsigned char data [2] = {REG_OFF_P, offset};
00576 
00577     Standby();
00578     writeRegs(data,2);
00579 
00580     Active(); 
00581 }
00582 
00583 void MPL3115A2::SetTemperatureOffset( char offset)
00584 {
00585     unsigned char data [2] = {REG_OFF_T, offset};
00586 
00587     Standby();
00588     writeRegs(data,2);
00589 
00590     Active(); 
00591 }
00592 
00593 void MPL3115A2::SetAltitudeOffset( char offset)
00594 {
00595     unsigned char data [2] = {REG_OFF_H, offset};
00596 
00597     Standby();
00598     writeRegs(data,2);
00599 
00600     Active(); 
00601 }
00602 
00603 void MPL3115A2::readRegs(int addr, uint8_t * data, int len) {
00604     char t[1] = {addr};
00605     m_i2c.write(m_addr, t, 1, true);
00606     m_i2c.read(m_addr, (char *)data, len);
00607 }
00608 
00609 void MPL3115A2::writeRegs(uint8_t * data, int len) {
00610     m_i2c.write(m_addr, (char *)data, len);
00611 }