High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of ms5611 by
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 }
Generated on Sat Jul 16 2022 20:50:21 by 1.7.2