Go Down

Topic: MS 4525DO (Read 2811 times) previous topic - next topic

PriceyTrash

Hello community,

Has anyone used this differential pressure sensor to measure air speed?

I have been trying to program for it, there are limited sources online.

Here is the spec sheet:http://www.meas-spec.com/downloads/MS4525DO.pdf

There is some code I found for the sensor
here:   https://code.google.com/p/openxsensor/source/browse/#svn%2Ftrunk%2FopenXsensor

I am having trouble picking apart the code on here, I could really use some help.

If your interested in helping, I can post the code I am working with now.  It's too long to post into one message.

Thanks for any and all help!

Sam

knut_ny

Try talk to your sensor..
http://meas-spec.com/downloads/Interfacing_to_MEAS_Digital_Pressure_Modules.pdf

The differential pressure can be made by eg. plastic tubes, open ends facing forward/backward.
(pitot-tube)
The code you have found contains useful information, too.
Ny

PriceyTrash

Using that pdf, I was just able to start communicating with the sensor. It does respond to changes in airflow.

However, I cannot get the values to come close to normal pressure reading.  I tried to convert the values from the sensor using an equation given on the data sheet, page 4.
The eqn is A type Output (Decimal Counts)= ((.8*16383) / (Pmax-Pmin)) * (Papplied - Pmin) + (.1*16383)


However, I am not sure about a few things.  Is the Pmax and Pmin a constant from the max range of the sensor?  Then the value for Pmax - Pmin would be 1...for a 1psi range.

Or are those values variable readings?

I figured the Papplied is surely the variable.  I solved the equation for Papplied, but I get an error message.

P_dat is my sensor output

Equation: Papplied = ((P_dat - (.1*16383))(1) / (.8*16383))

data sheet:http://www.meas-spec.com/downloads/MS4525DO.pdf

Here is the code I have written

Code: [Select]
#include <Wire.h> //I2C library 0x28H
 
byte fetch_pressure(unsigned int *p_Pressure); //convert value to byte data type


#define TRUE 1
#define FALSE 0

void setup(void)
{
   Serial.begin(9600);
   Wire.begin();
   pinMode(4, OUTPUT);
   pinMode(5, OUTPUT);
   digitalWrite(5, HIGH);  // SCL remains high
   digitalWrite(4, HIGH); // SDA transfers from high to low
   digitalWrite(4, LOW);  // this turns on the MS4525, I think
   delay(5000);
   Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>");  // just to be sure things are working 
}

void loop()
{
  byte _status;
  unsigned int P_dat;
  float PR;
 
  while(1)
  {
    _status = fetch_pressure(&P_dat);
   
    switch(_status)
    {
      case 0: Serial.println("Read_MR.");
      break;
      case 1: Serial.println("Read_DF2.");
      break;
      case 2: Serial.println("Read_DF3.");
      break;
      default: Serial.println("Read_DF4.");
      break;
    }
   
    PR = (float)  ((P_dat - (.1*16383))(1) / (.8*16383)) ;
   
Serial.println(P_dat);
Serial.println(PR);
    Serial.print(" ");
   
    delay(1000);
  }
}
 
  byte fetch_pressure(unsigned int *p_P_dat)
  {
   
   
  byte address, Press_H, Press_L, _status;
  unsigned int P_dat;
  address= 0x28;;
  Wire.beginTransmission(address); 
  Wire.endTransmission();
  delay(100);
 
  Wire.requestFrom((int)address, (int) 4);
  Press_H = Wire.read();
  Press_L = Wire.read();
  Wire.endTransmission();
 
 
  _status = (Press_H >> 6) & 0x03;
      Press_H = Press_H & 0x3f;
      P_dat = (((unsigned int)Press_H) << 8) | Press_L;
      *p_P_dat = P_dat;
      return(_status);

 
 
  }
 
  /code]

Kambalunga

#3
May 07, 2015, 05:26 pm Last Edit: May 07, 2015, 06:22 pm by Kambalunga
No wonder you write.

Wire.requestFrom((int)address, (int) 4);//you request 4 bytes
 But you read only 2 bytes.
Change the request to 2 and you see a reaction.
A little bit more commentary were be helpfully.
Then use the notation x.x and not .x that won't work.
()() do not work

Code: [Select]

//#include <WireMW.h>
#include <Wire.h>   //I2C library 0x28H
byte fetch_pressure(unsigned int *p_Pressure); //convert value to byte data type


#define TRUE 1
#define FALSE 0

void setup(void)
{
   Serial.begin(9600);
   Wire.begin();
   delay(500);
   Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>");  // just to be sure things are working 
}

void loop()
{
  byte _status;
  unsigned int P_dat;
  float PR;
 
  while(1)
  {
    _status = fetch_pressure(&P_dat);
   
    switch(_status)
    {
      case 0: Serial.println("Read_MR.");
      break;
      case 1: Serial.println("Read_DF2.");
      break;
      case 2: Serial.println("Read_DF3.");
      break;
      default: Serial.println("Read_DF4.");
      break;
    }
   
   
    PR = (float)((P_dat - (0.1*16383)) / (0.8*16383)) ;
   
Serial.println(P_dat);
Serial.println(PR);
    Serial.print(" ");
   
    delay(1000);
  }
}
 
  byte fetch_pressure(unsigned int *p_P_dat)
  {
   
   
  byte address, Press_H, Press_L, _status;
  unsigned int P_dat;
  address= 0x28;
  Wire.beginTransmission(address); 
  Wire.endTransmission();
  delay(100);
 
  Wire.requestFrom((int)address, (int) 4);//Request 4 bytes need 4 bytes are read
  Press_H = Wire.read();
  Press_L = Wire.read();
 byte Temp_H = Wire.read();
 byte  Temp_L = Wire.read();
  Wire.endTransmission();
 
 
  _status = (Press_H >> 6) & 0x03;
      Press_H = Press_H & 0x3f;
      P_dat = (((unsigned int)Press_H) << 8) | Press_L;
      *p_P_dat = P_dat;
      return(_status);

 
 
  }

 

sergiokzy

Hi guy i had problems  but  you may want to see my code   it works  great  !!

it was based on the codes here written but it needed a lil push

Please tell me if you would improve it   

 :)


Code: [Select]

//#include <WireMW.h>
#include <Wire.h>   //I2C library 0x28H
byte fetch_pressure(unsigned int *p_Pressure); //convert value to byte data type


#define TRUE 1
#define FALSE 0

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  delay(500);
  Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>");  // just to be sure things are working
}

void loop()
{
  byte _status;
  unsigned int P_dat;
  unsigned int T_dat;
  double PR;
  double TR;
  double V;
  double VV;
  while (1)
  {
    _status = fetch_pressure(&P_dat, &T_dat);

    switch (_status)
    {
      case 0: Serial.println("Ok ");
        break;
      case 1: Serial.println("Busy");
        break;
      case 2: Serial.println("Slate");
        break;
      default: Serial.println("Error");
        break;
    }


    PR = (double)((P_dat-819.15)/(14744.7)) ;
    PR = (PR - 0.49060678) ;
    PR = abs(PR);
     V = ((PR*13789.5144)/1.225);
    VV = (sqrt((V)));

   
    TR = (double)((T_dat*0.09770395701));
    TR = TR-50;
   
 
   
   Serial.print("raw Pressure:");
   Serial.println(P_dat);
   //Serial.println(P_dat,DEC);
   //Serial.println(P_dat,BIN);
   Serial.print("pressure psi:");
   Serial.println(PR,10);
   Serial.print(" ");
   Serial.print("raw Temp:");
   Serial.println(T_dat);
   Serial.print("temp:");
   Serial.println(TR);
   Serial.print("speed m/s :");
   Serial.println(VV,5);
 



    delay(1000);
  }
}

byte fetch_pressure(unsigned int *p_P_dat, unsigned int *p_T_dat)
{


  byte address, Press_H, Press_L, _status;
  unsigned int P_dat;
  unsigned int T_dat;

  address = 0x28;
  Wire.beginTransmission(address);
  Wire.endTransmission();
  delay(100);

  Wire.requestFrom((int)address, (int) 4);//Request 4 bytes need 4 bytes are read
  Press_H = Wire.read();
  Press_L = Wire.read();
  byte Temp_H = Wire.read();
  byte  Temp_L = Wire.read();
  Wire.endTransmission();


  _status = (Press_H >> 6) & 0x03;
  Press_H = Press_H & 0x3f;
  P_dat = (((unsigned int)Press_H) << 8) | Press_L;
  *p_P_dat = P_dat;

  Temp_L = (Temp_L >> 5);
  T_dat = (((unsigned int)Temp_H) << 3) | Temp_L;
  *p_T_dat = T_dat;
  return (_status);



}

MadMadHoosier

Background:  Just before Christmas I had a massive tear of my rotator cuff.  While waiting on surgery and recovery, I decided to take on a project that required me to learn arduino programming.  Considering my only prior programming was basic on a Commodore 64 (many many years ago), I have done quite well with the effort.  But I'm still struggling with certain aspects.  Hence, this question.

While trying to extract the pressure and temperature data, via I2C, from a 86BSD-015PG-3AIC "gage" sensor - I became stumped.  While searching for prior art, I might learn from, I found this thread using a similar (internally anyway) MS 4525DO "differential" sensor.  I understand most of the code, but what I am learning is "bitmath and bit shifting" at the bottom of the code is beyond my current understanding.

Rather than output the differential pressure and calculate speed as in the original code, my goal is to output a single gage pressure and calculate water depth (vessel draft actually).  But so far I have been unable to modify the code to get the raw pressure to zero.  It currently hovers around 1590 digital counts, equating to 1.45psi and 3.36' deep.

Can anyone offer me some direction?  Thanks, Steve.

PS:  The temperature output seems to be working very well!


86BSD datasheet... http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=86BSD&DocType=Data+Sheet&DocLang=English&DocFormat=pdf&PartCntxt=CAT-MIPS0037

MadMadHoosier

Sorry I missed the insert code in the prior post:

Code: [Select]
#include <Wire.h>   //I2C library 0x28H
byte fetch_pressure(unsigned int *p_Pressure); //convert value to byte data type

#define TRUE 1
#define FALSE 0

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  delay(500);
  Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>");  // just to be sure things are working
}

void loop()
{
  byte _status;
  unsigned int P_dat;
  unsigned int T_dat;
  double P;
  double PR;
  double TR;
  double V;
  double VV;
  while (1)
  {
    _status = fetch_pressure(&P_dat, &T_dat);

    switch (_status)
    {
      case 0: Serial.println("Ok ");
        break;
      case 1: Serial.println("Busy");
        break;
      case 2: Serial.println("Slate");
        break;
      default: Serial.println("Error");
        break;
    }

    PR = (double)((P_dat-819.15)/(14744.7)) ;
    PR = (PR - 0.49060678) ;
    PR = abs(PR);
     P = (double) P_dat*.0009155;
     V = ((PR*13789.5144)/1.225);
    VV = (sqrt((V)));
 
    TR = (double)((T_dat*0.09770395701));
    TR = TR-50;

   Serial.print("raw Pressure:"); 
   Serial.println(P_dat);
   Serial.print("pressure psi:");
   Serial.println(P,10);
   Serial.print("Draft:");
   Serial.println(P*2.3067);
   
   Serial.print(" ");
   Serial.print("raw Temp:");
   Serial.println(T_dat);
   Serial.print("tempC:");
   Serial.println(TR);
   Serial.print("tempF:");
   Serial.println((TR*1.8)+32);
   Serial.println(" ");
 
    delay(3000);
  }
}

byte fetch_pressure(unsigned int *p_P_dat, unsigned int *p_T_dat)
{
  byte address, Press_H, Press_L, _status;
  unsigned int P_dat;
  unsigned int T_dat;

  address = 0x28;
  Wire.beginTransmission(address);
  Wire.endTransmission();
  delay(100);

  Wire.requestFrom((int)address, (int) 4);//Request 4 bytes need 4 bytes are read
  Press_H = Wire.read();
  Press_L = Wire.read();
  byte Temp_H = Wire.read();
  byte  Temp_L = Wire.read();
  Wire.endTransmission();

  _status = (Press_H >> 6) & 0x03;
  Press_H = Press_H & 0x3f;
  P_dat = (((unsigned int)Press_H) << 8) | Press_L;
  *p_P_dat = P_dat;

  Temp_L = (Temp_L >> 5);
  T_dat = (((unsigned int)Temp_H) << 3) | Temp_L;
  *p_T_dat = T_dat;
  return (_status);

}

756E6C

#7
Apr 22, 2017, 03:56 am Last Edit: Apr 22, 2017, 04:12 am by 756E6C
I'm not familiar with that sensor, but looking at the datasheet, looks like zero PSI = 0x666 or 1638 decimal, close to your 1590, let's call 1590 zero and full scale is 0x399A or 14746, so subtracting 1590 you have a range of 0 - 13156 = 0 to 15PSI. Let's say, after subtracting your offset (1590) you have a remaining count of 5555, 5555 / 13156 * 15PSI = 6.333 * 2.307 = 14.61ft.
Keep checking back, I'm sure one of the "gurus" will stop by and help with your program.

MadMadHoosier

Hmmm.  Am I reading the datasheet wrong?  I am new to all this, but from looking at figure 4 the 86BSD datasheet I thought the 0x0666 or 1638 decimal was 10% of the output.  And I assumed 10% of my 15psi sensor would be 1.5psi. 





756E6C

You're probably right, guess the best approach is trial and error, do you have an air pump, accurate gauge and a way to tee in the sensor?

MadMadHoosier

Yeah.  I have it hooked up to a pump and 10psi gauge (good enough because my application will seldom go above 7psi).  And I've been changing various areas of the code to see if I can accidentally get things working the way I expect - but have not stumbled onto the right solution yet.  I'm really struggling understanding what the bit shifting is doing at the bottom of the code.  Appreciate anyone else's input.
Thanks again, Steve.

756E6C

#11
Apr 23, 2017, 07:58 am Last Edit: Apr 23, 2017, 08:35 am by 756E6C
The bit shifting is done because the reading from the sensor is a 16 bit integer (2 bytes) and Wire only transfers 1 byte at a time, the bit shifting assembles the 2 bytes back to the whole 16 bit integer.
What kind of counts do you get at zero, 5 and 10PSI?
EDIT: After thinking about it, I believe the 10-90% thing is about guaranteed accuracy between 2 known points and then extrapolating to zero and full range, so maybe you should calibrate at 1.5 and 13.5 PSI and just take what you get outside that range. I know load cells are not very accurate and linear at the lower 3 - 4% of their range, I always preloaded them to 5% then subtracted that reading and called it "zero".

MadMadHoosier

#12
Apr 27, 2017, 11:25 pm Last Edit: Apr 28, 2017, 03:36 am by MadMadHoosier
Ok on the bit shifting.  My current pressuring system is good, but not precision.  Here are some readings.

0    PSI = 1590 digital counts
1.5 PSI = 3000 digital counts
5.0 PSI = 6250 digital counts
7.5 PSI = 8300 digital counts
10PSI= 10600 digital counts

Given 100% output (according to table in Figure-4) yields 16383 digital counts for my 15 PSI sensor.  And the other percentages in the table are precisely 1092.2 digital counts per PSI.  So I would expect 0 PSI to be zero digital counts - not 1590, and 1.5 PSI to be 1638 digital counts - not 3000.  I almost feel like the sensor is working properly, and something in the program is skewing the count, but have yet to figure out what it is.

I understand your point on the load cells.  If I get a sensor working in this application, it will never really be reading zero.  It will start at about .5 PSI and vary to a max of 6-7 PSI.  So hopefully I will be in a fairly precise zone of a 7.5 or 15 PSI sensor.

MadMadHoosier

So it is not the program skewing the count.  I did a very basic sketch to read bytes 1, 2 & 3.  At zero PSI

byte1 = 6   (high byte)
byte2 = 54 (low byte)
byte3 = 97 (temperature)

If I then combine the two 8 bit integers into a 16 bit integer....((high byte*256)+low byte)....

Decimal count = 1590 ((6*256)+54)

My confusion is obviously in how I interpret these Digital counts into pressure.


NOTE:  As I apply pressure to the sensor, bytes 1 & 2 go up and byte 3 remains static.  If I blow hot air onto the sensor, byte 3 goes up and bytes 1 & 2 remain static.


Go Up