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:

MS4525DO/MS4525DO.cpp

Committer:
epremeaux
Date:
2019-09-13
Revision:
0:5965bf423184

File content as of revision 0:5965bf423184:


#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

}