Air pressure senor analog read fluctuates

I am using a 3000psi sensor from honeywell to read air pressure from an oxygen cylinder. The pressure seems to fluctuate high or low of around 50psi

String dev_name = "";
int voltsA;
int voltsB;
double pressureA = 0.0;
double pressureB = 0.0;
String client = "";
String location = "";
String device = "";

// Open a serial terminal and see the device name printed out
void handler(const char *topic, const char *data) {
    Serial.println("received " + String(topic) + ": " + String(data));
    dev_name = String(data);
}

void setup() {
  Serial.begin(9600);
  delay(5000);
  Particle.subscribe("particle/device/name", handler);
  Particle.publish("particle/device/name");
  delay(5000);
  
   //Setting the client, location, and device names for webhook
    char *str = new char [dev_name.length()+1];
    strcpy(str, dev_name.c_str());
    char *token = strtok(str, "-");
    
    int i = 0;
    while(token != NULL)
    {
        if (i == 0)
        {
           client = token; 
        }
        if (i == 1)
        {
           location = token; 
        }
        if (i == 2)
        {
           device = token; 
        }
        i = i+1;
        token = strtok(NULL, "-");
    }
  
}

void loop() {
    voltsA = analogRead(A0);
    delay(2000);
    voltsB = analogRead(A1);
    pressureA = (voltsA * 0.732177734375);
    pressureB = (voltsB * 0.732177734375);
    
    
    
    //Creating the string to publish to Particle
    String data = String::format(
        "{\"client\": \"%s\", \"location\": \"%s\", \"device\": \"%s\", \"pressureA\": %.0f, \"pressureB\": %.0f   }", client.c_str(), location.c_str(), device.c_str(), pressureA, pressureB);
    Particle.publish("Pressure", data, PRIVATE);
    //delay for one hour
    delay(3600000); 
    
    //delay 60 seconds for testing
    //delay(60000);

}

Hi @Scott76

[Edit: it looks like you have added part of a datasheet to your original post.]

I think you are going to have to tell us more about your sensor and how exactly you have hooked it up.

Your new datasheet screenshot shows 4V total FSS (which is too high for Particle devices–you need to stay under 3.3V!).

Your ADC counts look to be differences of around 40-50 steps in the data you show, so that would correspond to around 3.3V*(50/4096) ~= 40mV of noise or error in these readings. At 4V FSS, that is 1% of full scale. What does the rest of the datasheet say about repeatability and other error sources?

Here is the link to the sensor the one I have is MLH-03K-M-50-A page 5 gives you how this is mapped out.

I have the sensor hooked up to the 3v3 pin and gnd and I am reading from the A0 pin

Thanks for the help, i’m new at this!

Hi @Scott76

Table 5 on page 3 of that datasheet is saying that the accuracy is +/-0.25% or +/-0.5% depending on the pressure range, but then below says that the Total Error Band including many sources of error listed in the footnote is +/- 10% for lower pressures and +/- 5% for higher pressures. For the reading above of 1800 to 2200 psi, that would be an error margin of 90-110 psi so your readings probably not wrong, there are just error sources.

Do you know what the actual gage pressure on the tanks is? It would be very useful to double check the correctness here if there was an analog pressure gage that you could at least temporarily install on the lines.

I don’t think you are doing the math correctly by just scaling by 0.732177734375. I don’t know if the sensor will produce 0.5-2.7V for 0-3000psi on a 3.3V supply or not–the datasheet does not say since it assumes a 5V supply.

You should at least be subtracting out the 0.5V minimum value (0.5V = 620 ADC value) and then scaling.

2 Likes

I have been playing with the math a little bit. I am current using ADC * (2999/4096). I should probably use 3000 which is the max limit of the sensor.

From the actual pressure it’s about a 100-75 PSI higher

I’ve used Ratiometric 0.5V-4.5V pressure sensors that are supposed to be powered w/ 5V in the past with Electrons & powered with 3.3V.
The output is still proportional to the input voltage, but the 0 bias gets skewed, and the max output.
Measure the output at 0 psi, and use that instead of 0.5V.

 sensorValue = analogRead(A4) ;  
 voltage = (sensorValue) * ((3.3 / 4095.0));  
 pressure = ((voltage-XX) * (3000/YY) ) ; //  

XX = Voltage @ Zero Psi, will be less than 0.5V
YY = you have to either measure the output at Max rated pressure, or calculate the full range output (when using 3.3V source instead of 5V) based on a known reading & psi. Will be less than the 4V scale.
The good news is it’s a linear function.

I have this documented in my notes somewhere, but I cant find it ATM.

2 Likes

Just so I understand this correctly it should look something like this when is get the voltage at the top pressure and zero pressure

pressure = ((voltage-.2) * (3000/YY) )

and the YY is the max voltage are 3000 psi?

I can’t find my code or notes, but I seem to remember just using 4 for much smaller pressure range sensors (5psi, 15psi, etc). I’m not sure how…or why. I could be mistaken.

“IF” using the correct 5V supply voltage, the equation would have been:
pressure = ((voltage-0.5) * (MaxSensorPressure/4) ) ;
The 0.5 is the “Zero” offset that allows you to detect a problem with the sensor/measurement/wiring/etc if the voltage measured is ever < 0.5
The 4 is the full scale output range: 4.5V “max” minus 0.5V “min”.

Substitute your Zero offset into the standard equation and see if it calculates your known pressure correctly using 4 for YY.

1 Like

I would echo @bko about the accuracy and noise you will get in the ADC reading. ADCs accuracies depend upon the stability of the reference / supply voltages as will the sensor. It could be you are just seeing ripple in the voltage supply. You could try improving/removing this or use a low pass filter, kalman filter (simple 1D) to reduce the noise.

3 Likes

Either your product code is wrong, or you linked to the wrong datasheet.
Per the MLK sheet you linked, you have a 2% or a 5% accuracy sensor (+/-):


As @bko mentioned:
+/-2% of 3000 psi = + OR - 60 psi, or the actual pressure is somewhere in a 120 psi range centered on the measurement.

Following @armor recommendations will help to increase your precision (and definitely a good idea), but you are stuck with the accuracy of the sensor spec.
If you want to get swanky, you could also measure the temperature of the steel tank and track it along with pressure readings. By knowing that the pressure will only decrease over time, except for increases due to temperature changes- you can eventually create a pretty accurate equation for your measurement system to reduce systematic errors.

Or you can use a scale to constantly weight the cylinder and know exactly how much oxygen is in the tank (after a tare for empty cylinder). If you measure temperature, you can calculate the actual pressure in the tank using Gas Law.

2 Likes

I am using the M electrical connector, this is the right data sheet as I used this to buy the sensor directly from honeywell. I am monitoring a big oxygen tank that is usually at a max of 2500psi and sits in a storage room of a medical office. I’l see if I can find another way to power the sensor or do what @bko and @armor where talking about. The whole project is for a small business so having a nice IOT device really help against the big companies. Thanks every for the help!

1 Like

Hi @Scott76

Your part number is just missing the “P” for psi (vs. bar) and the “S” for sealed, but is otherwise consistent with that datasheet. The “03K” for 3000 psi, the “M” meter long cable and the “50” port 3/8-24 o-ring and the “A” for ratiometic all make sense.

2 Likes

It has the P&S in it, I mush have just missed it MLH03KPSL50A . I was also off on the cable length.

Even if you power the pressure sensor @ 5V, Particle devices cant read the 4.5V max output of this sensor, as @bko first mentioned.

But you have many choices, such as:

  • Add an external ADC that can safely measure 4.5V (like a 16-bit ADS1115).

  • Simple voltage divider to reduce the max 4.5V down to 3.3V and measure directly with Particle Device.

  • Use a sensor with a higher Max value than you will ever measure, “over-sized” so the max output is 3.3V or less at the maximum operating pressure that you expect to measure.

  • I’m sure there are other options too

Finding a 3.3V output pressure sensor is hard to do, at least finding one that doesn’t take 4-6 weeks for delivery.

I normally use DWYER 626 pressure sensors and haven’t had a single problem with them.
Example:
Dwyer 626-18-GH-P1-E3-S4 gets you a 0.25% FSS accuracy 0-3000psi (gauge), 0-5V output for $158
You would select any of the options listed above to safely read the 5V max output, or order the 5000 psi version that would be safe up to 3,300 psi for the Particle device (3.3V output).

BTW: There’s nothing wrong with your plan now, powering with 3.3V since the output is proportional to the input voltage (with your calibrated Zero Offset). Assuming that your tests show it tracks well with the 3.3V input.

2 Likes

Have you checked for sources of electrical interference? Have you looked at the sensor output with an oscilloscope?
Have you considered taking the average of multiple readings?

I too have a product reading a 3000psi (200 bar) O2 cylinder and I do all those things to achieve good stability in the measurements. I get less than 0.1 bar of flicker, out of 200 bar fullscale.

Keep an eye on those sensors - the first ones I used were also from Honeywell, and we had issues with them failing after a few weeks on pressure. Honeywell did identify the root cause though, so hopefully they’ve fixed the problem.

One other thing I want to check: you are ordering an oxygen cleaned version of the sensor? These sensors are usually calibrated using oil as the pressure media, and you don’t want that mixing with high pressure pure O2.

What sensors are you using? And if you don’t mind what does your code look like with these. I did start to take multiple readings and that did smooth it out a bit. I need to get back out there to check for interference. The sensor should be for air, the data sheet is in this thread if you see anything different.

We switched to an MPM281 series pressure sensor from Microsensors (http://www.microsensorcorp.com), as we needed to change supplier in a hurry, and they were willing to quickly customise a sensor to duplicate the Honeywell one we had been using. I think they were slightly cheaper too. So far no issues - with more than 100 sensors deployed in the field for over a year.

float Get_PO2(void) // read cylinder pressure
{
    int i;
    float temp =0;
    double acc=0;
    for (i=0;i<64;i++)  // long mutliread to get rid of noise
    {
        acc+=analogRead(Pcyl);
        delay(i);
    }
    acc=acc/64;
    temp= mapfloat(acc,  cyl_inlo,  cyl_inhi, 0, cyl_outhi);

As you can see I take 64 readings at progressively longer intervals and average the result. The variable delay helps avoid issues with single frequency interference, which could get aliased down to DC if you were really unlucky. If this seems excessive its not, as my system depends heavily on accurate pressure readings.
I use the mapfloat() function to convert to bar using my calibration values.

3 Likes

Nice, I never thought of that. Thanks for sharing @twospoons !

Strictly speaking the sampling intervals should be random, but this seemed a reasonable compromise of good filtering and predictable sample time.

1 Like

When sampling analog values with the Particle, be aware that the platform is not designed for high-precision/low-noise analog sampling. You are sharing the supply voltage and reference voltage with the digital board and the radio. I have done some testing and I find significant differences in the amount of noise with the radio on vs. off. You can reduce your outliers by turning off the radio before you sample, then turning it back on. Even if you are averaging multiple samples, outliers will pull your average.

If you want a clean, precise value on every measurement you will need to build a separate circuit with a separate ADC. From what you describe as your application, I doubt that you need to do that. If the objective is just to track the O2 level and know when it’s time to refill, you can take the noisy data and then use averaging and outlier-filtering on the back end (such as in ThingSpeak) to avoid false alerts.

1 Like