High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of ms5611 by
Revision 8:f3660f819e54, committed 2013-11-09
- Comitter:
- tyftyftyf
- Date:
- Sat Nov 09 08:51:15 2013 +0000
- Parent:
- 7:8545a1d1d1e4
- Child:
- 9:9f1d38b8d7c3
- Commit message:
- Implemented async mode
Changed in this revision
MS561101BA.cpp | Show annotated file Show diff for this revision Revisions of this file |
MS561101BA.h | Show annotated file Show diff for this revision Revisions of this file |
--- 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); }
--- a/MS561101BA.h Sat Nov 02 17:23:33 2013 +0000 +++ b/MS561101BA.h Sat Nov 09 08:51:15 2013 +0000 @@ -37,7 +37,7 @@ // registers of the device #define MS561101BA_D1 0x40 #define MS561101BA_D2 0x50 -#define MS561101BA_RESET 0x1E +//#define MS561101BA_RESET 0x1E // D1 and D2 result size (bytes) #define MS561101BA_D1D2_SIZE 3 @@ -54,30 +54,39 @@ #define MS561101BA_PROM_REG_COUNT 6 // number of registers in the PROM #define MS561101BA_PROM_REG_SIZE 2 // size in bytes of a prom registry. -#define I2C_SDA p28 -#define I2C_SCL p27 - class MS561101BA { public: MS561101BA(); - MS561101BA(I2C _i2c); void init(uint8_t addr); - float getPressure(uint8_t OSR); - float getTemperature(uint8_t OSR); - int32_t getDeltaTemp(uint8_t OSR); - uint32_t rawPressure(uint8_t OSR); - uint32_t rawTemperature(uint8_t OSR); + float getPressure(); + float getTemperature(); + int32_t getDeltaTemp(); + void start_sampling(uint8_t OSR); + int rawTemperature(); + int rawPressure(); int readPROM(); void reset(); uint32_t lastPresConv, lastTempConv; - private: - I2C i2c; + + MODI2C i2c; + + static void samplingthread_stub(void const *p); + void samplingthread(); + Thread _thread; + volatile uint32_t conversion; + uint8_t _OSR; + Semaphore sem; + char cobuf[3]; + Timer t; - void startConversion(uint8_t command); - uint32_t getConversion(uint8_t command); + void startConversion(char *command); + void getConversion(); uint8_t _addr; uint16_t _Cal[MS561101BA_PROM_REG_COUNT]; uint32_t pressCache, tempCache; + + char zero; + char MS561101BA_RESET; }; #endif // MS561101BA_h \ No newline at end of file