Library and demo program for MS4525DO differential pressure sensor based pitot tube, using I2C interface
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:
- https://forum.arduino.cc/index.php?topic=309653.0
- https://github.com/PX4/Firmware/blob/master/src/modules/commander/airspeed_calibration.cpp
- https://github.com/PX4/Firmware/tree/master/src/drivers/differential_pressure/ms4525
Revision 0:5965bf423184, committed 2019-09-13
- 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
diff -r 000000000000 -r 5965bf423184 F303_logger.h --- /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 +
diff -r 000000000000 -r 5965bf423184 MS4525DO/MS4525DO.cpp --- /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
diff -r 000000000000 -r 5965bf423184 MS4525DO/MS4525DO.h --- /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
diff -r 000000000000 -r 5965bf423184 main.cpp --- /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); + } +}
diff -r 000000000000 -r 5965bf423184 mbed.bld --- /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