High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of ms5611 by
Diff: MS561101BA.cpp
- Revision:
- 8:f3660f819e54
- Parent:
- 7:8545a1d1d1e4
- Child:
- 9:9f1d38b8d7c3
--- a/MS561101BA.cpp Sat Nov 02 17:23:33 2013 +0000 +++ b/MS561101BA.cpp Sat Nov 09 08:51:15 2013 +0000 @@ -24,48 +24,57 @@ */ #include "mbed.h" +#include "rtos.h" +#include "MODI2C.h" #include "MS561101BA.h" -#define CONVERSION_TIME 12000l // conversion time in microseconds -MS561101BA::MS561101BA():i2c(I2C_SDA,I2C_SCL){ -} +#ifndef I2C_SDA + #define I2C_SDA p28 + #define I2C_SCL p27 +#endif -MS561101BA::MS561101BA(I2C _i2c):i2c(_i2c) { - ; +MS561101BA::MS561101BA():i2c(I2C_SDA,I2C_SCL),_thread(&MS561101BA::samplingthread_stub, this),sem(0){ + zero = 0; + MS561101BA_RESET = 0x1E; + _OSR = NULL; } void MS561101BA::init(uint8_t address) { -lastPresConv=0; -lastTempConv=0; + lastPresConv=0; + lastTempConv=0; t.start(); - _addr = address; + _addr = address << 1; reset(); // reset the device to populate its internal PROM registers - wait_ms(500); // some safety time + Thread::wait(500); // some safety time readPROM(); // reads the PROM into object variables for later use } -float MS561101BA::getPressure(uint8_t OSR) { +void MS561101BA::samplingthread_stub(void const *p) { + MS561101BA *instance = (MS561101BA*)p; + instance->samplingthread(); +} + +float MS561101BA::getPressure() { // see datasheet page 7 for formulas - uint32_t rawPress = rawPressure(OSR); - if(rawPress == NULL) { + if(pressCache == NULL) { return NULL; } - int32_t dT = getDeltaTemp(OSR); + int32_t dT = getDeltaTemp(); if(dT == NULL) { return NULL; } int64_t off = ((uint32_t)_Cal[1] <<16) + (((int64_t)dT * _Cal[3]) >> 7); int64_t sens = ((uint32_t)_Cal[0] <<15) + (((int64_t)dT * _Cal[2]) >> 8); - return ((( (rawPress * sens ) >> 21) - off) >> 15) / 100.0; + return ((( (pressCache * sens ) >> 21) - off) >> 15) / 100.0; } -float MS561101BA::getTemperature(uint8_t OSR) { +float MS561101BA::getTemperature() { // see datasheet page 7 for formulas - int64_t dT = getDeltaTemp(OSR); + int64_t dT = getDeltaTemp(); if(dT != NULL) { return (2000 + ((dT * _Cal[5]) >> 23)) / 100.0; @@ -75,98 +84,77 @@ } } -int32_t MS561101BA::getDeltaTemp(uint8_t OSR) { - uint32_t rawTemp = rawTemperature(OSR); - if(rawTemp != NULL) { - return (int32_t)(rawTemp - ((uint32_t)_Cal[4] << 8)); +int32_t MS561101BA::getDeltaTemp() { + if(tempCache != NULL) { + return (int32_t)(tempCache - ((uint32_t)_Cal[4] << 8)); } else { return NULL; } } -//TODO: avoid duplicated code between rawPressure and rawTemperature methods -//TODO: possible race condition between readings.. serious headache doing this.. help appreciated! +void MS561101BA::samplingthread(){ + Thread::signal_wait(0x1); + for (;;){ + char command = MS561101BA_D1 + _OSR; + startConversion(&command); + Thread::wait(13); + getConversion(); + sem.wait(); + pressCache = conversion; + command = MS561101BA_D2 + _OSR; + startConversion(&command); + Thread::wait(13); + getConversion(); + sem.wait(); + tempCache = conversion; + Thread::yield(); + } +} -uint32_t MS561101BA::rawPressure(uint8_t OSR) { - uint32_t now = t.read_us(); - if(lastPresConv != 0 && (now - lastPresConv) >= CONVERSION_TIME) { - lastPresConv = 0; - pressCache = getConversion(MS561101BA_D1 + OSR); - } - else { - if(lastPresConv == 0 && lastTempConv == 0) { - startConversion(MS561101BA_D1 + OSR); - lastPresConv = now; - } - } - return pressCache; +void MS561101BA::start_sampling(uint8_t OSR){ + _OSR = OSR; + _thread.signal_set(0x1); } -uint32_t MS561101BA::rawTemperature(uint8_t OSR) { - unsigned long now = t.read_us(); - if(lastTempConv != 0 && (now - lastTempConv) >= CONVERSION_TIME) { - lastTempConv = 0; - tempCache = getConversion(MS561101BA_D2 + OSR); - } - else { - if(lastTempConv == 0 && lastPresConv == 0) { // no conversions in progress - startConversion(MS561101BA_D2 + OSR); - lastTempConv = now; - } - } - return tempCache; +int MS561101BA::rawTemperature(){ + return tempCache; } +int MS561101BA::rawPressure(){ + return pressCache; +} // see page 11 of the datasheet -void MS561101BA::startConversion(uint8_t command) { +void MS561101BA::startConversion(char *command) { // initialize pressure conversion - i2c.start(); - i2c.write(_addr<<1); - i2c.write(command); - i2c.stop(); + i2c.write(_addr, (char*)command, 1); } -uint32_t MS561101BA::getConversion(uint8_t command) { - uint32_t conversion = 0; - - // start read sequence - /*Wire.beginTransmission(_addr); - Wire.write(0); - Wire.endTransmission();*/ - i2c.start(); - i2c.write(_addr<<1); - i2c.write(0); - i2c.stop(); - - //Wire.beginTransmission(_addr); - //Wire.requestFrom(_addr, (uint8_t) MS561101BA_D1D2_SIZE); - char cobuf[3]; - if (i2c.read((_addr<<1)+1, cobuf, MS561101BA_D1D2_SIZE)!=0) {conversion=0xFFFFFFFF;}else{ - conversion = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2]; - } - return conversion; +uint32_t getConversion_fin(uint32_t param){ + MS561101BA* ins = (MS561101BA*)param; + ins->conversion = (ins->cobuf[0] << 16) + (ins->cobuf[1] << 8) + ins->cobuf[2]; + ins->sem.release(); + return 0; } +void MS561101BA::getConversion() { + i2c.write(_addr, (char*)&zero, 1); + i2c.read_nb(_addr, (char*)cobuf, MS561101BA_D1D2_SIZE, &getConversion_fin, this); +} /** * 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.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); - Wire.endTransmission();*/ - i2c.start(); - i2c.write(_addr<<1); - i2c.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); - i2c.stop(); + char a = MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE); + i2c.write(_addr, &a, 1); char tmp[2]; - if (i2c.read((_addr<<1)+1, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1; - _Cal[i] = tmp[0]<<8 | tmp[1]; - wait_ms(200); + if (i2c.read(_addr, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1; + _Cal[i] = tmp[0] <<8 | tmp[1]; + Thread::wait(200); } return 0; } @@ -177,11 +165,5 @@ * populates its internal registers with the values read from the PROM. */ void MS561101BA::reset() { - /*Wire.beginTransmission(_addr); - Wire.write(MS561101BA_RESET); - Wire.endTransmission();*/ - i2c.start(); - i2c.write(_addr<<1); - i2c.write(MS561101BA_RESET); - i2c.stop(); + i2c.write(_addr, (char*)&MS561101BA_RESET, 1); }