Llibrary for the WiGo MPL3115A2, I2C Precision Altimeter sensor.
Dependents: KL25Z_Batt_Test WIGO_MPL3115A2 Multi-Sensor SPACEmk2 ... more
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 }
Generated on Sat Jul 16 2022 22:22:12 by 1.7.2