Library and demo program for MS4525DO differential pressure sensor based pitot tube, using I2C interface

Dependencies:   mbed

Temperature values are correct. But I dont trust the PSI and airspeed (especially airspeed).

Code blended and ported from a combination of the following sources:

Files at this revision

API Documentation at this revision

Comitter:
epremeaux
Date:
Fri Sep 13 08:41:37 2019 +0000
Commit message:
initial commit. I dont trust the output values yet

Changed in this revision

F303_logger.h Show annotated file Show diff for this revision Revisions of this file
MS4525DO/MS4525DO.cpp Show annotated file Show diff for this revision Revisions of this file
MS4525DO/MS4525DO.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F303_logger.h	Fri Sep 13 08:41:37 2019 +0000
@@ -0,0 +1,29 @@
+
+// Telemetry UART
+#define TELEM_TX    PA_9
+#define TELEM_RX    PA_10
+
+// Battery ADC
+#define BAT_V       PB_0
+
+// I2C
+#define I2CSDA      PB_7
+#define I2CSCL      PB_6
+
+// Strain Gauges
+#define LIFT_CLK    PB_1
+#define LIFT_DAT    PF_0
+#define DRAG_CLK    PF_1
+#define DRAG_DAT    PA_8
+
+// Buzzer
+
+// SD Card
+#define MOSI    PA_7
+#define MISO    PA_6
+#define SCLK    PA_5
+#define SSEL    PA_4 
+
+
+// Local ADC
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MS4525DO/MS4525DO.cpp	Fri Sep 13 08:41:37 2019 +0000
@@ -0,0 +1,160 @@
+
+#include "mbed.h"
+#include "MS4525DO.h"
+
+
+MS4525DO::MS4525DO(PinName sda, PinName scl, char slave_adr)
+    :
+    i2c_p(new I2C(sda, scl)), 
+    i2c(*i2c_p),
+    address(slave_adr<<1)
+{
+    initialize();
+}
+
+MS4525DO::MS4525DO(I2C &i2c_obj, char slave_adr)
+    :
+    i2c_p(NULL), 
+    i2c(i2c_obj),
+    address(slave_adr<<1)
+{
+    initialize();
+}
+
+MS4525DO::~MS4525DO()
+{
+    if (NULL != i2c_p)
+        delete  i2c_p;
+}
+
+
+/* public functions
+        void initialize(void);
+        int measure(void);              // returns status of measurement
+        float getPSI(void);             // returns the PSI of last measurement
+        float getTemperature(void);     // returns temperature of last measurement
+        float getAirSpeed(void);        // calculates and returns the airspeed
+        int calibrate(void);            // attempts to calibrate and returns a status code
+        */
+
+void MS4525DO::initialize()
+{
+    // i2c writes to set up addresses, etc.
+    
+}
+
+// combine measure and collect into one function that returns the status code only, and holds the results in variables
+// other subroutines for returning clean values should be get functions
+
+
+int MS4525DO::measure()
+{
+    char ret;
+    ret = fetch_pressure(P_dat, T_dat);
+    return ret;
+}
+
+
+char MS4525DO::fetch_pressure(uint16_t &P_dat, uint16_t &T_dat)
+{
+    char _status;
+    char Press_H;
+    char Press_L;
+    char Temp_H;
+    char Temp_L;
+
+    char cmd[1];
+    cmd[0] = 0x00;
+    // So a device with a 'physical' address of 0x28, will need 'address bytes' of 0x50 for a write (R/W low), and 0x51 for a read (R/W high). 
+    //      MS4525DAddress
+    i2c.write(address, cmd, 1, true);  // select the register, no I2C Stop 
+       
+
+    char data[4];
+//    i2c.read(MS4525DAddress, static_cast<uint8_t>(4), static_cast<uint8_t>(true));  //Request 4 bytes, 2 pressure/status and 2 temperature
+    i2c.read(address, data, 4);
+    
+
+    Press_H = data[0];
+    Press_L = data[1];
+    Temp_H = data[2];
+    Temp_L = data[3];
+   
+     _status = (Press_H >> 6) & 0x03;
+    Press_H = Press_H & 0x3f;
+    P_dat = (((uint16_t)Press_H) << 8) | Press_L;
+
+    Temp_L = (Temp_L >> 5);
+    T_dat = (((uint16_t)Temp_H) << 3) | Temp_L;
+ 
+    return _status;
+}
+
+
+
+float MS4525DO::getPSI(void){             // returns the PSI of last measurement
+    // convert and store PSI
+    psi=(static_cast<float>(static_cast<int16_t>(P_dat)-MS4525ZeroCounts))/static_cast<float>(MS4525Span)*static_cast<float>(MS4525FullScaleRange);
+    // apply PSI calibration data
+    //   psi = psi + 0.007f;
+    
+    /* Below code is Pixhawk code which doesnt seem to work correctly */
+    // Calculate differential pressure. As its centered around 8000
+    // and can go positive or negative
+    /*
+    const float P_min = -1.0f;
+    const float P_max = 1.0f;
+    const float PSI_to_Pa = 6894.757f;
+    */ 
+    /*
+      this equation is an inversion of the equation in the
+      pressure transfer function figure on page 4 of the datasheet
+      We negate the result so that positive differential pressures
+      are generated when the bottom port is used as the static
+      port on the pitot and top port is used as the dynamic port
+     */
+     /*
+    float diff_press_PSI = -((T_dat - 0.1f * 16383) * (P_max - P_min) / (0.8f * 16383) + P_min);
+    float diff_press_pa_raw = diff_press_PSI * PSI_to_Pa;
+    */
+    
+    
+    return psi;
+}             
+  
+float MS4525DO::getTemperature(void){     // returns temperature of last measurement
+    // convert and store Temperature
+    temperature= (static_cast<float>(static_cast<int16_t>(T_dat)));
+    temperature = (temperature / 10);   // now in deg F
+    temperature = ((temperature -32) / 1.8f);   // now in deg C
+    
+    /* Below code is pixhawk version which DOES work correctly */
+    /*
+    PX4temperature = ((200.0f * T_dat) / 2047) - 50;
+    terminal.printf("PX4 Temperature: ");
+    terminal.printf("%0.1f\n", PX4temperature);
+    */
+    
+    return temperature;
+}
+
+float MS4525DO::getAirSpeed(void){        // calculates and returns the airspeed
+    /* Velocity calculation from a pitot tube explanation */
+    /* +/- 1PSI, approximately 100 m/s */
+    float rho = 1.225; // density of air 
+    // velocity = squareroot( (2*differential) / rho )
+    float velocity;
+    if (psi<0) {
+        velocity = -sqrt(-(2*psi) / rho);
+    }else{
+        velocity = sqrt((2*psi) / rho);
+        }
+    velocity = velocity*10;
+    
+    return velocity;
+}
+
+
+int MS4525DO::calibrate(void){            // attempts to calibrate and returns a status code
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MS4525DO/MS4525DO.h	Fri Sep 13 08:41:37 2019 +0000
@@ -0,0 +1,73 @@
+
+#ifndef MS4525DO_H
+#define MS4525DO_H
+
+#include "mbed.h"
+
+#define I2C_ADDRESS_MS4525DO    0x28    /**< 7-bit address =0x28. 8-bit is 0x50. Depends on the order code (this is for code "I") */
+
+/* Register address */
+#define ADDR_READ_MR            0x00    /* write to this address to start conversion */
+
+// MS4525D sensor full scale range and units
+const int16_t MS4525FullScaleRange = 1;  // 1 psi
+
+// MS4525D Sensor type (A or B) comment out the wrong type assignments
+// Type A (10% to 90%)
+const int16_t MS4525MinScaleCounts = 1638;
+const int16_t MS4525FullScaleCounts = 14746;
+
+const int16_t MS4525Span=MS4525FullScaleCounts-MS4525MinScaleCounts;
+
+//MS4525D sensor pressure style, differential or otherwise. Comment out the wrong one.
+//Differential
+const int16_t MS4525ZeroCounts=(MS4525MinScaleCounts+MS4525FullScaleCounts)/2;
+
+
+class MS4525DO
+{
+    public:
+    // instance methods
+        // explicit I2C pin names
+        MS4525DO(PinName sda, PinName sck, char slave_adr = I2C_ADDRESS_MS4525DO);
+        
+        // pin names as an object (ideal when sharing the bus)
+        MS4525DO(I2C &i2c_obj, char slave_adr = I2C_ADDRESS_MS4525DO);
+    
+        virtual ~MS4525DO();
+    
+    // public functions
+        void initialize(void);
+        int measure(void);              // returns status of measurement
+        float getPSI(void);             // returns the PSI of last measurement
+        float getTemperature(void);     // returns temperature of last measurement
+        float getAirSpeed(void);        // calculates and returns the airspeed
+        int calibrate(void);            // attempts to calibrate and returns a status code
+         
+    
+    private:
+        I2C         *i2c_p;
+        I2C         &i2c;
+        char        address;
+        char        _status;
+        float       psi;
+        float       temperature;
+        float       airspeed;
+        uint16_t    P_dat;  // 14 bit pressure data
+        uint16_t    T_dat;  // 11 bit temperature data
+        
+    // private functions
+        int collect(void);
+        char fetch_pressure(uint16_t &P_dat, uint16_t &T_dat);
+          
+    
+};  // end of the class
+
+
+/** airspeed scaling factors; out = (in * Vscale) + offset */
+struct airspeed_scale {
+    float   offset_pa;
+    float   scale;
+};
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Sep 13 08:41:37 2019 +0000
@@ -0,0 +1,46 @@
+#include "mbed.h"
+#include "F303_logger.h"
+#include "MS4525DO.h"
+
+Serial terminal(USBTX, USBRX);
+I2C i2c(I2CSDA, I2CSCL);
+
+MS4525DO Pitot(i2c); 
+
+DigitalOut myled(LED1);
+
+
+int main() {
+    terminal.baud(115200); 
+    terminal.printf("MS4525DO library test\n");
+
+    while(1) {
+        char PitotStatus;    // A two bit field indicating the status of the I2C read
+        PitotStatus = Pitot.measure();
+
+        switch (PitotStatus)
+        {
+            case 0:
+            //Serial.println("Ok ");
+            terminal.printf("PSI: %f\n", Pitot.getPSI());
+            terminal.printf("Temperature: %f\n", Pitot.getTemperature());
+            terminal.printf("Airspeed: %f\n", Pitot.getAirSpeed());
+            terminal.printf("\n");
+            break;
+            
+            case 1:
+            terminal.printf("Busy\n");
+            break;
+            
+            case 2:
+            terminal.printf("Stale\n");
+            break;
+            
+            default:
+            terminal.printf("Error\n");
+            break;
+        }
+        myled = !myled;
+        wait_ms(200);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Sep 13 08:41:37 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file