High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of ms5611 by Kevin Braun

Files at this revision

API Documentation at this revision

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