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:

Committer:
epremeaux
Date:
Fri Sep 13 08:41:37 2019 +0000
Revision:
0:5965bf423184
initial commit. I dont trust the output values yet

Who changed what in which revision?

UserRevisionLine numberNew contents of line
epremeaux 0:5965bf423184 1
epremeaux 0:5965bf423184 2 #include "mbed.h"
epremeaux 0:5965bf423184 3 #include "MS4525DO.h"
epremeaux 0:5965bf423184 4
epremeaux 0:5965bf423184 5
epremeaux 0:5965bf423184 6 MS4525DO::MS4525DO(PinName sda, PinName scl, char slave_adr)
epremeaux 0:5965bf423184 7 :
epremeaux 0:5965bf423184 8 i2c_p(new I2C(sda, scl)),
epremeaux 0:5965bf423184 9 i2c(*i2c_p),
epremeaux 0:5965bf423184 10 address(slave_adr<<1)
epremeaux 0:5965bf423184 11 {
epremeaux 0:5965bf423184 12 initialize();
epremeaux 0:5965bf423184 13 }
epremeaux 0:5965bf423184 14
epremeaux 0:5965bf423184 15 MS4525DO::MS4525DO(I2C &i2c_obj, char slave_adr)
epremeaux 0:5965bf423184 16 :
epremeaux 0:5965bf423184 17 i2c_p(NULL),
epremeaux 0:5965bf423184 18 i2c(i2c_obj),
epremeaux 0:5965bf423184 19 address(slave_adr<<1)
epremeaux 0:5965bf423184 20 {
epremeaux 0:5965bf423184 21 initialize();
epremeaux 0:5965bf423184 22 }
epremeaux 0:5965bf423184 23
epremeaux 0:5965bf423184 24 MS4525DO::~MS4525DO()
epremeaux 0:5965bf423184 25 {
epremeaux 0:5965bf423184 26 if (NULL != i2c_p)
epremeaux 0:5965bf423184 27 delete i2c_p;
epremeaux 0:5965bf423184 28 }
epremeaux 0:5965bf423184 29
epremeaux 0:5965bf423184 30
epremeaux 0:5965bf423184 31 /* public functions
epremeaux 0:5965bf423184 32 void initialize(void);
epremeaux 0:5965bf423184 33 int measure(void); // returns status of measurement
epremeaux 0:5965bf423184 34 float getPSI(void); // returns the PSI of last measurement
epremeaux 0:5965bf423184 35 float getTemperature(void); // returns temperature of last measurement
epremeaux 0:5965bf423184 36 float getAirSpeed(void); // calculates and returns the airspeed
epremeaux 0:5965bf423184 37 int calibrate(void); // attempts to calibrate and returns a status code
epremeaux 0:5965bf423184 38 */
epremeaux 0:5965bf423184 39
epremeaux 0:5965bf423184 40 void MS4525DO::initialize()
epremeaux 0:5965bf423184 41 {
epremeaux 0:5965bf423184 42 // i2c writes to set up addresses, etc.
epremeaux 0:5965bf423184 43
epremeaux 0:5965bf423184 44 }
epremeaux 0:5965bf423184 45
epremeaux 0:5965bf423184 46 // combine measure and collect into one function that returns the status code only, and holds the results in variables
epremeaux 0:5965bf423184 47 // other subroutines for returning clean values should be get functions
epremeaux 0:5965bf423184 48
epremeaux 0:5965bf423184 49
epremeaux 0:5965bf423184 50 int MS4525DO::measure()
epremeaux 0:5965bf423184 51 {
epremeaux 0:5965bf423184 52 char ret;
epremeaux 0:5965bf423184 53 ret = fetch_pressure(P_dat, T_dat);
epremeaux 0:5965bf423184 54 return ret;
epremeaux 0:5965bf423184 55 }
epremeaux 0:5965bf423184 56
epremeaux 0:5965bf423184 57
epremeaux 0:5965bf423184 58 char MS4525DO::fetch_pressure(uint16_t &P_dat, uint16_t &T_dat)
epremeaux 0:5965bf423184 59 {
epremeaux 0:5965bf423184 60 char _status;
epremeaux 0:5965bf423184 61 char Press_H;
epremeaux 0:5965bf423184 62 char Press_L;
epremeaux 0:5965bf423184 63 char Temp_H;
epremeaux 0:5965bf423184 64 char Temp_L;
epremeaux 0:5965bf423184 65
epremeaux 0:5965bf423184 66 char cmd[1];
epremeaux 0:5965bf423184 67 cmd[0] = 0x00;
epremeaux 0:5965bf423184 68 // 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).
epremeaux 0:5965bf423184 69 // MS4525DAddress
epremeaux 0:5965bf423184 70 i2c.write(address, cmd, 1, true); // select the register, no I2C Stop
epremeaux 0:5965bf423184 71
epremeaux 0:5965bf423184 72
epremeaux 0:5965bf423184 73 char data[4];
epremeaux 0:5965bf423184 74 // i2c.read(MS4525DAddress, static_cast<uint8_t>(4), static_cast<uint8_t>(true)); //Request 4 bytes, 2 pressure/status and 2 temperature
epremeaux 0:5965bf423184 75 i2c.read(address, data, 4);
epremeaux 0:5965bf423184 76
epremeaux 0:5965bf423184 77
epremeaux 0:5965bf423184 78 Press_H = data[0];
epremeaux 0:5965bf423184 79 Press_L = data[1];
epremeaux 0:5965bf423184 80 Temp_H = data[2];
epremeaux 0:5965bf423184 81 Temp_L = data[3];
epremeaux 0:5965bf423184 82
epremeaux 0:5965bf423184 83 _status = (Press_H >> 6) & 0x03;
epremeaux 0:5965bf423184 84 Press_H = Press_H & 0x3f;
epremeaux 0:5965bf423184 85 P_dat = (((uint16_t)Press_H) << 8) | Press_L;
epremeaux 0:5965bf423184 86
epremeaux 0:5965bf423184 87 Temp_L = (Temp_L >> 5);
epremeaux 0:5965bf423184 88 T_dat = (((uint16_t)Temp_H) << 3) | Temp_L;
epremeaux 0:5965bf423184 89
epremeaux 0:5965bf423184 90 return _status;
epremeaux 0:5965bf423184 91 }
epremeaux 0:5965bf423184 92
epremeaux 0:5965bf423184 93
epremeaux 0:5965bf423184 94
epremeaux 0:5965bf423184 95 float MS4525DO::getPSI(void){ // returns the PSI of last measurement
epremeaux 0:5965bf423184 96 // convert and store PSI
epremeaux 0:5965bf423184 97 psi=(static_cast<float>(static_cast<int16_t>(P_dat)-MS4525ZeroCounts))/static_cast<float>(MS4525Span)*static_cast<float>(MS4525FullScaleRange);
epremeaux 0:5965bf423184 98 // apply PSI calibration data
epremeaux 0:5965bf423184 99 // psi = psi + 0.007f;
epremeaux 0:5965bf423184 100
epremeaux 0:5965bf423184 101 /* Below code is Pixhawk code which doesnt seem to work correctly */
epremeaux 0:5965bf423184 102 // Calculate differential pressure. As its centered around 8000
epremeaux 0:5965bf423184 103 // and can go positive or negative
epremeaux 0:5965bf423184 104 /*
epremeaux 0:5965bf423184 105 const float P_min = -1.0f;
epremeaux 0:5965bf423184 106 const float P_max = 1.0f;
epremeaux 0:5965bf423184 107 const float PSI_to_Pa = 6894.757f;
epremeaux 0:5965bf423184 108 */
epremeaux 0:5965bf423184 109 /*
epremeaux 0:5965bf423184 110 this equation is an inversion of the equation in the
epremeaux 0:5965bf423184 111 pressure transfer function figure on page 4 of the datasheet
epremeaux 0:5965bf423184 112 We negate the result so that positive differential pressures
epremeaux 0:5965bf423184 113 are generated when the bottom port is used as the static
epremeaux 0:5965bf423184 114 port on the pitot and top port is used as the dynamic port
epremeaux 0:5965bf423184 115 */
epremeaux 0:5965bf423184 116 /*
epremeaux 0:5965bf423184 117 float diff_press_PSI = -((T_dat - 0.1f * 16383) * (P_max - P_min) / (0.8f * 16383) + P_min);
epremeaux 0:5965bf423184 118 float diff_press_pa_raw = diff_press_PSI * PSI_to_Pa;
epremeaux 0:5965bf423184 119 */
epremeaux 0:5965bf423184 120
epremeaux 0:5965bf423184 121
epremeaux 0:5965bf423184 122 return psi;
epremeaux 0:5965bf423184 123 }
epremeaux 0:5965bf423184 124
epremeaux 0:5965bf423184 125 float MS4525DO::getTemperature(void){ // returns temperature of last measurement
epremeaux 0:5965bf423184 126 // convert and store Temperature
epremeaux 0:5965bf423184 127 temperature= (static_cast<float>(static_cast<int16_t>(T_dat)));
epremeaux 0:5965bf423184 128 temperature = (temperature / 10); // now in deg F
epremeaux 0:5965bf423184 129 temperature = ((temperature -32) / 1.8f); // now in deg C
epremeaux 0:5965bf423184 130
epremeaux 0:5965bf423184 131 /* Below code is pixhawk version which DOES work correctly */
epremeaux 0:5965bf423184 132 /*
epremeaux 0:5965bf423184 133 PX4temperature = ((200.0f * T_dat) / 2047) - 50;
epremeaux 0:5965bf423184 134 terminal.printf("PX4 Temperature: ");
epremeaux 0:5965bf423184 135 terminal.printf("%0.1f\n", PX4temperature);
epremeaux 0:5965bf423184 136 */
epremeaux 0:5965bf423184 137
epremeaux 0:5965bf423184 138 return temperature;
epremeaux 0:5965bf423184 139 }
epremeaux 0:5965bf423184 140
epremeaux 0:5965bf423184 141 float MS4525DO::getAirSpeed(void){ // calculates and returns the airspeed
epremeaux 0:5965bf423184 142 /* Velocity calculation from a pitot tube explanation */
epremeaux 0:5965bf423184 143 /* +/- 1PSI, approximately 100 m/s */
epremeaux 0:5965bf423184 144 float rho = 1.225; // density of air
epremeaux 0:5965bf423184 145 // velocity = squareroot( (2*differential) / rho )
epremeaux 0:5965bf423184 146 float velocity;
epremeaux 0:5965bf423184 147 if (psi<0) {
epremeaux 0:5965bf423184 148 velocity = -sqrt(-(2*psi) / rho);
epremeaux 0:5965bf423184 149 }else{
epremeaux 0:5965bf423184 150 velocity = sqrt((2*psi) / rho);
epremeaux 0:5965bf423184 151 }
epremeaux 0:5965bf423184 152 velocity = velocity*10;
epremeaux 0:5965bf423184 153
epremeaux 0:5965bf423184 154 return velocity;
epremeaux 0:5965bf423184 155 }
epremeaux 0:5965bf423184 156
epremeaux 0:5965bf423184 157
epremeaux 0:5965bf423184 158 int MS4525DO::calibrate(void){ // attempts to calibrate and returns a status code
epremeaux 0:5965bf423184 159
epremeaux 0:5965bf423184 160 }