0,0 → 1,143 |
/* |
MS5611-01BA.cpp - Interfaces a Measurement Specialities MS5611-01BA with Arduino |
See http://www.meas-spec.com/downloads/MS5611-01BA01.pdf for the device datasheet |
|
Copyright (C) 2011 Fabio Varesano <fvaresano@yahoo.it> |
|
Development of this code has been supported by the Department of Computer Science, |
Universita' degli Studi di Torino, Italy within the Piemonte Project |
http://www.piemonte.di.unito.it/ |
|
|
This program is free software: you can redistribute it and/or modify |
it under the terms of the version 3 GNU General Public License as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
#include "MS561101BA.h" |
#define EXTRA_PRECISION 5 // trick to add more precision to the pressure and temp readings |
|
MS561101BA::MS561101BA() { |
; |
} |
|
void MS561101BA::init(uint8_t address) { |
_addr = address; |
|
// disable internal pullups of the ATMEGA which Wire enable by default |
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) |
// deactivate internal pull-ups for twi |
// as per note from atmega8 manual pg167 |
cbi(PORTC, 4); |
cbi(PORTC, 5); |
#else |
// deactivate internal pull-ups for twi |
// as per note from atmega128 manual pg204 |
cbi(PORTD, 0); |
cbi(PORTD, 1); |
#endif |
|
reset(); // reset the device to populate its internal PROM registers |
delay(1000); // some safety time |
readPROM(); // reads the PROM into object variables for later use |
} |
|
float MS561101BA::getPressure(uint8_t OSR) { |
// see datasheet page 7 for formulas |
int64_t dT = getDeltaTemp(OSR); |
int64_t off = (((int64_t)_C[1]) << 16) + ((_C[3] * dT) >> 7); |
int64_t sens = (((int64_t)_C[0]) << 15) + ((_C[2] * dT) >> 8); |
return ((((rawPressure(OSR) * sens) >> 21) - off) >> (15-EXTRA_PRECISION)) / ((1<<EXTRA_PRECISION) * 100.0); |
} |
|
float MS561101BA::getTemperature(uint8_t OSR) { |
// see datasheet page 7 for formulas |
return ((1<<EXTRA_PRECISION)*2000l + ((getDeltaTemp(OSR) * _C[5]) >> (23-EXTRA_PRECISION))) / ((1<<EXTRA_PRECISION) * 100.0); |
} |
|
int64_t MS561101BA::getDeltaTemp(uint8_t OSR) { |
return rawTemperature(OSR) - (((int32_t)_C[4]) << 8); |
} |
|
int32_t MS561101BA::rawPressure(uint8_t OSR) { |
return doConversion(MS561101BA_D1 + OSR); |
} |
|
int32_t MS561101BA::rawTemperature(uint8_t OSR) { |
return doConversion(MS561101BA_D2 + OSR); |
} |
|
|
unsigned long MS561101BA::doConversion(uint8_t command) { |
unsigned long conversion = 0; |
|
// see page 11 of the datasheet |
|
// initialize pressure conversion |
Wire.beginTransmission(_addr); |
Wire.send(command); |
Wire.endTransmission(); |
|
delay(10); // the conversion will take a time <= 9.04 ms to have the output ready |
// TODO: make the delay dependant on the OSR requested in the command |
|
// start read sequence |
Wire.beginTransmission(_addr); |
Wire.send(0); |
Wire.endTransmission(); |
|
Wire.beginTransmission(_addr); |
Wire.requestFrom(_addr, (uint8_t) MS561101BA_D1D2_SIZE); |
if(Wire.available()) { |
conversion = Wire.receive() * 65536 + Wire.receive() * 256 + Wire.receive(); |
} |
else { |
conversion = -1; |
} |
|
return conversion; |
} |
|
|
/** |
* Reads factory calibration and store it into object variables. |
*/ |
int MS561101BA::readPROM() { |
for (int i=0;i<MS561101BA_PROM_REG_COUNT;i++) { |
Wire.beginTransmission(_addr); |
Wire.send(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); |
Wire.endTransmission(); |
|
Wire.beginTransmission(_addr); |
Wire.requestFrom(_addr, (uint8_t) MS561101BA_PROM_REG_SIZE); |
if(Wire.available()) { |
_C[i] = Wire.receive() << 8 | Wire.receive(); |
|
//DEBUG_PRINT(_C[i]); |
} |
else { |
return -1; // error reading the PROM or communicating with the device |
} |
} |
return 0; |
} |
|
|
/** |
* Send a reset command to the device. With the reset command the device |
* populates its internal registers with the values read from the PROM. |
*/ |
void MS561101BA::reset() { |
Wire.beginTransmission(_addr); |
Wire.send(MS561101BA_RESET); |
Wire.endTransmission(); |
} |