Llibrary for the WiGo MPL3115A2, I2C Precision Altimeter sensor. This is a temp fork

Dependents:   sensor AerCloud_MutliTech_Socket_Modem_Example Freescale_Multi-Sensor_Shield 2lemetry_Sensor_Example ... more

Fork of MPL3115A2 by clemente di caprio

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MPL3115A2.cpp Source File

MPL3115A2.cpp

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