High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of ms5611 by
MS561101BA.cpp@7:8545a1d1d1e4, 2013-11-02 (annotated)
- Committer:
- tyftyftyf
- Date:
- Sat Nov 02 17:23:33 2013 +0000
- Revision:
- 7:8545a1d1d1e4
- Child:
- 8:f3660f819e54
Initial Commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tyftyftyf | 7:8545a1d1d1e4 | 1 | /* |
tyftyftyf | 7:8545a1d1d1e4 | 2 | MS5611-01BA.cpp - Interfaces a Measurement Specialities MS5611-01BA with Arduino |
tyftyftyf | 7:8545a1d1d1e4 | 3 | See http://www.meas-spec.com/downloads/MS5611-01BA01.pdf for the device datasheet |
tyftyftyf | 7:8545a1d1d1e4 | 4 | |
tyftyftyf | 7:8545a1d1d1e4 | 5 | Copyright (C) 2011 Fabio Varesano <fvaresano@yahoo.it> |
tyftyftyf | 7:8545a1d1d1e4 | 6 | |
tyftyftyf | 7:8545a1d1d1e4 | 7 | Development of this code has been supported by the Department of Computer Science, |
tyftyftyf | 7:8545a1d1d1e4 | 8 | Universita' degli Studi di Torino, Italy within the Piemonte Project |
tyftyftyf | 7:8545a1d1d1e4 | 9 | http://www.piemonte.di.unito.it/ |
tyftyftyf | 7:8545a1d1d1e4 | 10 | |
tyftyftyf | 7:8545a1d1d1e4 | 11 | |
tyftyftyf | 7:8545a1d1d1e4 | 12 | This program is free software: you can redistribute it and/or modify |
tyftyftyf | 7:8545a1d1d1e4 | 13 | it under the terms of the version 3 GNU General Public License as |
tyftyftyf | 7:8545a1d1d1e4 | 14 | published by the Free Software Foundation. |
tyftyftyf | 7:8545a1d1d1e4 | 15 | |
tyftyftyf | 7:8545a1d1d1e4 | 16 | This program is distributed in the hope that it will be useful, |
tyftyftyf | 7:8545a1d1d1e4 | 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
tyftyftyf | 7:8545a1d1d1e4 | 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
tyftyftyf | 7:8545a1d1d1e4 | 19 | GNU General Public License for more details. |
tyftyftyf | 7:8545a1d1d1e4 | 20 | |
tyftyftyf | 7:8545a1d1d1e4 | 21 | You should have received a copy of the GNU General Public License |
tyftyftyf | 7:8545a1d1d1e4 | 22 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
tyftyftyf | 7:8545a1d1d1e4 | 23 | |
tyftyftyf | 7:8545a1d1d1e4 | 24 | */ |
tyftyftyf | 7:8545a1d1d1e4 | 25 | |
tyftyftyf | 7:8545a1d1d1e4 | 26 | #include "mbed.h" |
tyftyftyf | 7:8545a1d1d1e4 | 27 | #include "MS561101BA.h" |
tyftyftyf | 7:8545a1d1d1e4 | 28 | #define CONVERSION_TIME 12000l // conversion time in microseconds |
tyftyftyf | 7:8545a1d1d1e4 | 29 | |
tyftyftyf | 7:8545a1d1d1e4 | 30 | MS561101BA::MS561101BA():i2c(I2C_SDA,I2C_SCL){ |
tyftyftyf | 7:8545a1d1d1e4 | 31 | } |
tyftyftyf | 7:8545a1d1d1e4 | 32 | |
tyftyftyf | 7:8545a1d1d1e4 | 33 | MS561101BA::MS561101BA(I2C _i2c):i2c(_i2c) { |
tyftyftyf | 7:8545a1d1d1e4 | 34 | ; |
tyftyftyf | 7:8545a1d1d1e4 | 35 | } |
tyftyftyf | 7:8545a1d1d1e4 | 36 | |
tyftyftyf | 7:8545a1d1d1e4 | 37 | void MS561101BA::init(uint8_t address) { |
tyftyftyf | 7:8545a1d1d1e4 | 38 | lastPresConv=0; |
tyftyftyf | 7:8545a1d1d1e4 | 39 | lastTempConv=0; |
tyftyftyf | 7:8545a1d1d1e4 | 40 | t.start(); |
tyftyftyf | 7:8545a1d1d1e4 | 41 | _addr = address; |
tyftyftyf | 7:8545a1d1d1e4 | 42 | |
tyftyftyf | 7:8545a1d1d1e4 | 43 | reset(); // reset the device to populate its internal PROM registers |
tyftyftyf | 7:8545a1d1d1e4 | 44 | wait_ms(500); // some safety time |
tyftyftyf | 7:8545a1d1d1e4 | 45 | readPROM(); // reads the PROM into object variables for later use |
tyftyftyf | 7:8545a1d1d1e4 | 46 | } |
tyftyftyf | 7:8545a1d1d1e4 | 47 | |
tyftyftyf | 7:8545a1d1d1e4 | 48 | float MS561101BA::getPressure(uint8_t OSR) { |
tyftyftyf | 7:8545a1d1d1e4 | 49 | // see datasheet page 7 for formulas |
tyftyftyf | 7:8545a1d1d1e4 | 50 | |
tyftyftyf | 7:8545a1d1d1e4 | 51 | uint32_t rawPress = rawPressure(OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 52 | if(rawPress == NULL) { |
tyftyftyf | 7:8545a1d1d1e4 | 53 | return NULL; |
tyftyftyf | 7:8545a1d1d1e4 | 54 | } |
tyftyftyf | 7:8545a1d1d1e4 | 55 | |
tyftyftyf | 7:8545a1d1d1e4 | 56 | int32_t dT = getDeltaTemp(OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 57 | if(dT == NULL) { |
tyftyftyf | 7:8545a1d1d1e4 | 58 | return NULL; |
tyftyftyf | 7:8545a1d1d1e4 | 59 | } |
tyftyftyf | 7:8545a1d1d1e4 | 60 | |
tyftyftyf | 7:8545a1d1d1e4 | 61 | int64_t off = ((uint32_t)_Cal[1] <<16) + (((int64_t)dT * _Cal[3]) >> 7); |
tyftyftyf | 7:8545a1d1d1e4 | 62 | int64_t sens = ((uint32_t)_Cal[0] <<15) + (((int64_t)dT * _Cal[2]) >> 8); |
tyftyftyf | 7:8545a1d1d1e4 | 63 | return ((( (rawPress * sens ) >> 21) - off) >> 15) / 100.0; |
tyftyftyf | 7:8545a1d1d1e4 | 64 | } |
tyftyftyf | 7:8545a1d1d1e4 | 65 | |
tyftyftyf | 7:8545a1d1d1e4 | 66 | float MS561101BA::getTemperature(uint8_t OSR) { |
tyftyftyf | 7:8545a1d1d1e4 | 67 | // see datasheet page 7 for formulas |
tyftyftyf | 7:8545a1d1d1e4 | 68 | int64_t dT = getDeltaTemp(OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 69 | |
tyftyftyf | 7:8545a1d1d1e4 | 70 | if(dT != NULL) { |
tyftyftyf | 7:8545a1d1d1e4 | 71 | return (2000 + ((dT * _Cal[5]) >> 23)) / 100.0; |
tyftyftyf | 7:8545a1d1d1e4 | 72 | } |
tyftyftyf | 7:8545a1d1d1e4 | 73 | else { |
tyftyftyf | 7:8545a1d1d1e4 | 74 | return NULL; |
tyftyftyf | 7:8545a1d1d1e4 | 75 | } |
tyftyftyf | 7:8545a1d1d1e4 | 76 | } |
tyftyftyf | 7:8545a1d1d1e4 | 77 | |
tyftyftyf | 7:8545a1d1d1e4 | 78 | int32_t MS561101BA::getDeltaTemp(uint8_t OSR) { |
tyftyftyf | 7:8545a1d1d1e4 | 79 | uint32_t rawTemp = rawTemperature(OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 80 | if(rawTemp != NULL) { |
tyftyftyf | 7:8545a1d1d1e4 | 81 | return (int32_t)(rawTemp - ((uint32_t)_Cal[4] << 8)); |
tyftyftyf | 7:8545a1d1d1e4 | 82 | } |
tyftyftyf | 7:8545a1d1d1e4 | 83 | else { |
tyftyftyf | 7:8545a1d1d1e4 | 84 | return NULL; |
tyftyftyf | 7:8545a1d1d1e4 | 85 | } |
tyftyftyf | 7:8545a1d1d1e4 | 86 | } |
tyftyftyf | 7:8545a1d1d1e4 | 87 | |
tyftyftyf | 7:8545a1d1d1e4 | 88 | //TODO: avoid duplicated code between rawPressure and rawTemperature methods |
tyftyftyf | 7:8545a1d1d1e4 | 89 | //TODO: possible race condition between readings.. serious headache doing this.. help appreciated! |
tyftyftyf | 7:8545a1d1d1e4 | 90 | |
tyftyftyf | 7:8545a1d1d1e4 | 91 | uint32_t MS561101BA::rawPressure(uint8_t OSR) { |
tyftyftyf | 7:8545a1d1d1e4 | 92 | uint32_t now = t.read_us(); |
tyftyftyf | 7:8545a1d1d1e4 | 93 | if(lastPresConv != 0 && (now - lastPresConv) >= CONVERSION_TIME) { |
tyftyftyf | 7:8545a1d1d1e4 | 94 | lastPresConv = 0; |
tyftyftyf | 7:8545a1d1d1e4 | 95 | pressCache = getConversion(MS561101BA_D1 + OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 96 | } |
tyftyftyf | 7:8545a1d1d1e4 | 97 | else { |
tyftyftyf | 7:8545a1d1d1e4 | 98 | if(lastPresConv == 0 && lastTempConv == 0) { |
tyftyftyf | 7:8545a1d1d1e4 | 99 | startConversion(MS561101BA_D1 + OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 100 | lastPresConv = now; |
tyftyftyf | 7:8545a1d1d1e4 | 101 | } |
tyftyftyf | 7:8545a1d1d1e4 | 102 | } |
tyftyftyf | 7:8545a1d1d1e4 | 103 | return pressCache; |
tyftyftyf | 7:8545a1d1d1e4 | 104 | } |
tyftyftyf | 7:8545a1d1d1e4 | 105 | |
tyftyftyf | 7:8545a1d1d1e4 | 106 | uint32_t MS561101BA::rawTemperature(uint8_t OSR) { |
tyftyftyf | 7:8545a1d1d1e4 | 107 | unsigned long now = t.read_us(); |
tyftyftyf | 7:8545a1d1d1e4 | 108 | if(lastTempConv != 0 && (now - lastTempConv) >= CONVERSION_TIME) { |
tyftyftyf | 7:8545a1d1d1e4 | 109 | lastTempConv = 0; |
tyftyftyf | 7:8545a1d1d1e4 | 110 | tempCache = getConversion(MS561101BA_D2 + OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 111 | } |
tyftyftyf | 7:8545a1d1d1e4 | 112 | else { |
tyftyftyf | 7:8545a1d1d1e4 | 113 | if(lastTempConv == 0 && lastPresConv == 0) { // no conversions in progress |
tyftyftyf | 7:8545a1d1d1e4 | 114 | startConversion(MS561101BA_D2 + OSR); |
tyftyftyf | 7:8545a1d1d1e4 | 115 | lastTempConv = now; |
tyftyftyf | 7:8545a1d1d1e4 | 116 | } |
tyftyftyf | 7:8545a1d1d1e4 | 117 | } |
tyftyftyf | 7:8545a1d1d1e4 | 118 | return tempCache; |
tyftyftyf | 7:8545a1d1d1e4 | 119 | } |
tyftyftyf | 7:8545a1d1d1e4 | 120 | |
tyftyftyf | 7:8545a1d1d1e4 | 121 | |
tyftyftyf | 7:8545a1d1d1e4 | 122 | // see page 11 of the datasheet |
tyftyftyf | 7:8545a1d1d1e4 | 123 | void MS561101BA::startConversion(uint8_t command) { |
tyftyftyf | 7:8545a1d1d1e4 | 124 | // initialize pressure conversion |
tyftyftyf | 7:8545a1d1d1e4 | 125 | i2c.start(); |
tyftyftyf | 7:8545a1d1d1e4 | 126 | i2c.write(_addr<<1); |
tyftyftyf | 7:8545a1d1d1e4 | 127 | i2c.write(command); |
tyftyftyf | 7:8545a1d1d1e4 | 128 | i2c.stop(); |
tyftyftyf | 7:8545a1d1d1e4 | 129 | } |
tyftyftyf | 7:8545a1d1d1e4 | 130 | |
tyftyftyf | 7:8545a1d1d1e4 | 131 | uint32_t MS561101BA::getConversion(uint8_t command) { |
tyftyftyf | 7:8545a1d1d1e4 | 132 | uint32_t conversion = 0; |
tyftyftyf | 7:8545a1d1d1e4 | 133 | |
tyftyftyf | 7:8545a1d1d1e4 | 134 | // start read sequence |
tyftyftyf | 7:8545a1d1d1e4 | 135 | /*Wire.beginTransmission(_addr); |
tyftyftyf | 7:8545a1d1d1e4 | 136 | Wire.write(0); |
tyftyftyf | 7:8545a1d1d1e4 | 137 | Wire.endTransmission();*/ |
tyftyftyf | 7:8545a1d1d1e4 | 138 | i2c.start(); |
tyftyftyf | 7:8545a1d1d1e4 | 139 | i2c.write(_addr<<1); |
tyftyftyf | 7:8545a1d1d1e4 | 140 | i2c.write(0); |
tyftyftyf | 7:8545a1d1d1e4 | 141 | i2c.stop(); |
tyftyftyf | 7:8545a1d1d1e4 | 142 | |
tyftyftyf | 7:8545a1d1d1e4 | 143 | //Wire.beginTransmission(_addr); |
tyftyftyf | 7:8545a1d1d1e4 | 144 | //Wire.requestFrom(_addr, (uint8_t) MS561101BA_D1D2_SIZE); |
tyftyftyf | 7:8545a1d1d1e4 | 145 | char cobuf[3]; |
tyftyftyf | 7:8545a1d1d1e4 | 146 | if (i2c.read((_addr<<1)+1, cobuf, MS561101BA_D1D2_SIZE)!=0) {conversion=0xFFFFFFFF;}else{ |
tyftyftyf | 7:8545a1d1d1e4 | 147 | conversion = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2]; |
tyftyftyf | 7:8545a1d1d1e4 | 148 | } |
tyftyftyf | 7:8545a1d1d1e4 | 149 | return conversion; |
tyftyftyf | 7:8545a1d1d1e4 | 150 | } |
tyftyftyf | 7:8545a1d1d1e4 | 151 | |
tyftyftyf | 7:8545a1d1d1e4 | 152 | |
tyftyftyf | 7:8545a1d1d1e4 | 153 | /** |
tyftyftyf | 7:8545a1d1d1e4 | 154 | * Reads factory calibration and store it into object variables. |
tyftyftyf | 7:8545a1d1d1e4 | 155 | */ |
tyftyftyf | 7:8545a1d1d1e4 | 156 | int MS561101BA::readPROM() { |
tyftyftyf | 7:8545a1d1d1e4 | 157 | for (int i=0;i<MS561101BA_PROM_REG_COUNT;i++) { |
tyftyftyf | 7:8545a1d1d1e4 | 158 | /*Wire.beginTransmission(_addr); |
tyftyftyf | 7:8545a1d1d1e4 | 159 | Wire.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); |
tyftyftyf | 7:8545a1d1d1e4 | 160 | Wire.endTransmission();*/ |
tyftyftyf | 7:8545a1d1d1e4 | 161 | i2c.start(); |
tyftyftyf | 7:8545a1d1d1e4 | 162 | i2c.write(_addr<<1); |
tyftyftyf | 7:8545a1d1d1e4 | 163 | i2c.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); |
tyftyftyf | 7:8545a1d1d1e4 | 164 | i2c.stop(); |
tyftyftyf | 7:8545a1d1d1e4 | 165 | |
tyftyftyf | 7:8545a1d1d1e4 | 166 | char tmp[2]; |
tyftyftyf | 7:8545a1d1d1e4 | 167 | if (i2c.read((_addr<<1)+1, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1; |
tyftyftyf | 7:8545a1d1d1e4 | 168 | _Cal[i] = tmp[0]<<8 | tmp[1]; |
tyftyftyf | 7:8545a1d1d1e4 | 169 | wait_ms(200); |
tyftyftyf | 7:8545a1d1d1e4 | 170 | } |
tyftyftyf | 7:8545a1d1d1e4 | 171 | return 0; |
tyftyftyf | 7:8545a1d1d1e4 | 172 | } |
tyftyftyf | 7:8545a1d1d1e4 | 173 | |
tyftyftyf | 7:8545a1d1d1e4 | 174 | |
tyftyftyf | 7:8545a1d1d1e4 | 175 | /** |
tyftyftyf | 7:8545a1d1d1e4 | 176 | * Send a reset command to the device. With the reset command the device |
tyftyftyf | 7:8545a1d1d1e4 | 177 | * populates its internal registers with the values read from the PROM. |
tyftyftyf | 7:8545a1d1d1e4 | 178 | */ |
tyftyftyf | 7:8545a1d1d1e4 | 179 | void MS561101BA::reset() { |
tyftyftyf | 7:8545a1d1d1e4 | 180 | /*Wire.beginTransmission(_addr); |
tyftyftyf | 7:8545a1d1d1e4 | 181 | Wire.write(MS561101BA_RESET); |
tyftyftyf | 7:8545a1d1d1e4 | 182 | Wire.endTransmission();*/ |
tyftyftyf | 7:8545a1d1d1e4 | 183 | i2c.start(); |
tyftyftyf | 7:8545a1d1d1e4 | 184 | i2c.write(_addr<<1); |
tyftyftyf | 7:8545a1d1d1e4 | 185 | i2c.write(MS561101BA_RESET); |
tyftyftyf | 7:8545a1d1d1e4 | 186 | i2c.stop(); |
tyftyftyf | 7:8545a1d1d1e4 | 187 | } |