High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of ms5611 by Kevin Braun

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MS561101BA.cpp Source File

MS561101BA.cpp

00001 /*
00002 MS5611-01BA.cpp - Interfaces a Measurement Specialities MS5611-01BA with Arduino
00003 See http://www.meas-spec.com/downloads/MS5611-01BA01.pdf for the device datasheet
00004 
00005 Copyright (C) 2011 Fabio Varesano <fvaresano@yahoo.it>
00006 
00007 Development of this code has been supported by the Department of Computer Science,
00008 Universita' degli Studi di Torino, Italy within the Piemonte Project
00009 http://www.piemonte.di.unito.it/
00010 
00011 
00012 This program is free software: you can redistribute it and/or modify
00013 it under the terms of the version 3 GNU General Public License as
00014 published by the Free Software Foundation.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 */
00025 
00026 #include "mbed.h"
00027 #include "rtos.h"
00028 #include "MODI2C.h"
00029 #include "MS561101BA.h"
00030 
00031 #ifndef I2C_SDA
00032     #define I2C_SDA p9
00033     #define I2C_SCL p10
00034 #endif
00035 
00036 MS561101BA::MS561101BA() : i2c(I2C_SDA,I2C_SCL), _thread(), sem(0){
00037     zero = 0;
00038     MS561101BA_RESET = 0x1E;
00039     _OSR = NULL;
00040     _thread.start(callback(&MS561101BA::samplingthread_stub, (void *) this));
00041 }
00042 
00043 void MS561101BA::init(uint8_t address) {  
00044     lastPresConv=0;
00045     lastTempConv=0;
00046     t.start();
00047     _addr =  address << 1;
00048  
00049     reset(); // reset the device to populate its internal PROM registers
00050     Thread::wait(500); // some safety time
00051     readPROM(); // reads the PROM into object variables for later use
00052 }
00053 
00054 void MS561101BA::samplingthread_stub(void const *p) {
00055   MS561101BA *instance = (MS561101BA*)p;
00056   instance->samplingthread();
00057 }
00058 
00059 float MS561101BA::getPressure() {
00060   // see datasheet page 7 for formulas
00061   
00062   if(pressCache == NULL) {
00063     return NULL;
00064   }
00065   
00066   int32_t dT = getDeltaTemp();
00067   if(dT == NULL) {
00068     return NULL;
00069   }
00070   
00071   int64_t off  = ((uint32_t)_Cal[1] <<16) + (((int64_t)dT * _Cal[3]) >> 7);
00072   int64_t sens = ((uint32_t)_Cal[0] <<15) + (((int64_t)dT * _Cal[2]) >> 8);
00073   return ((( (pressCache * sens ) >> 21) - off) >> 15) / 100.0;
00074 }
00075 
00076 float MS561101BA::getTemperature() {
00077   // see datasheet page 7 for formulas
00078   int64_t dT = getDeltaTemp();
00079   
00080   if(dT != NULL) {
00081     return (2000 + ((dT * _Cal[5]) >> 23)) / 100.0;
00082   }
00083   else {
00084     return NULL;
00085   }
00086 }
00087 
00088 int32_t MS561101BA::getDeltaTemp() {
00089   if(tempCache != NULL) {
00090     return (int32_t)(tempCache - ((uint32_t)_Cal[4] << 8));
00091   }
00092   else {
00093     return NULL;
00094   }
00095 }
00096 
00097 void MS561101BA::samplingthread(){
00098     Thread::signal_wait(0x1);
00099     for (;;){
00100         char command = MS561101BA_D1 + _OSR;
00101         startConversion(&command);
00102         Thread::wait(13);
00103         getConversion();
00104         sem.wait();
00105         pressCache = conversion;
00106         command = MS561101BA_D2 + _OSR;
00107         startConversion(&command);
00108         Thread::wait(13);
00109         getConversion();
00110         sem.wait();
00111         tempCache = conversion;
00112         Thread::yield();
00113     }
00114 }
00115 
00116 void MS561101BA::start_sampling(uint8_t OSR){
00117     _OSR = OSR;
00118     _thread.signal_set(0x1);
00119 }
00120 
00121 int MS561101BA::rawTemperature(){
00122     return tempCache;
00123 }
00124 
00125 int MS561101BA::rawPressure(){
00126     return pressCache;
00127 }
00128 
00129 // see page 11 of the datasheet
00130 void MS561101BA::startConversion(char *command) {
00131   // initialize pressure conversion
00132   i2c.write(_addr, (char*)command, 1);
00133 }
00134 
00135 uint32_t getConversion_fin(uint32_t param){
00136     MS561101BA* ins = (MS561101BA*)param;
00137     ins->conversion = (ins->cobuf[0] << 16) + (ins->cobuf[1] << 8) + ins->cobuf[2];
00138     ins->sem.release();
00139     return 0;
00140 }
00141 
00142 void MS561101BA::getConversion() {
00143   i2c.write(_addr, (char*)&zero, 1);
00144   i2c.read_nb(_addr, (char*)cobuf, MS561101BA_D1D2_SIZE, &getConversion_fin, this);
00145 }
00146 
00147 /**
00148  * Reads factory calibration and store it into object variables.
00149 */
00150 int MS561101BA::readPROM() {
00151   for (int i=0;i<MS561101BA_PROM_REG_COUNT;i++) {
00152     char a = MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE);
00153     i2c.write(_addr, &a, 1);
00154     
00155     char tmp[2];
00156     if (i2c.read(_addr, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1;
00157     _Cal[i] = tmp[0] <<8 | tmp[1];
00158     Thread::wait(200);
00159   }
00160   return 0;
00161 }
00162 
00163 
00164 /**
00165  * Send a reset command to the device. With the reset command the device
00166  * populates its internal registers with the values read from the PROM.
00167 */
00168 void MS561101BA::reset() {
00169   i2c.write(_addr, (char*)&MS561101BA_RESET, 1);
00170 }