Pressure transducer code

Hi,

I have one of these sensors too and I have mapped a part of its range with a "precision" digital tire gauge and a 10-bit ADC in a PIC microcontroller. By "precision" digital tire gauge, I mean it has 0.01 bar resolution but is accurate to 1psi or roughly 0.07 bar (I work with bar, not psi, sorry).

I managed to map from 2.67 bar to 6.32 bar. At what should have been 6.47 bar, the display showed 0.00 and I think I broke the tire gauge :o the readings in the normal tire pressure range is all over the place so these data is worth a new $42 tire gauge! :money_mouth_face:

Anyway, I took a small propane canister, put it in the freezer overnight, and then hooked it up to the digital tire gauge and the pressure transducer. As the propane temperature slowly rises, the pressure does too and it was easy to take a pressure reading for every 10 ADC count. I put all the data into a Google Sheet and then calculated the difference between each of the pressure readings and calculated the average. I did a graph of the pressure readings and they looked very linear, see for yourself in the attachments.

I then interpolated the values up to ~13 bar and down to ~0 bar.

I have attached a save of the Google Sheet both as PDF and Excel format. The yellow cells are the readings, the green cells are calculated values.

Basically, using a 10-bit ADC with supply as Vref, a 1 count change equals a pressure change of 0.0146 bar or 0.212 psi, calculated as 0.04 bar = 100, 13.04 bar = 990, difference is 13 bar and 890 counts: 13 bar / 890 counts = 0.0146 bar/count.

In my case, the supply voltage of PIC/ADC and transducer was regulated to 4.975V but as I understand, the sensor is radiometric, so the output voltage is dependent on the supply voltage so the 0.5% voltage regulation error from 5V does not matter.

I hope this can help someone that comes by here like I did, looking for information. Sorry, no Arduino code, just info on the sensor.

Pressure transducer logging.pdf (148 KB)

Pressure transducer logging.zip (6.39 KB)

[quote author=6v6gt link=msg=2596192

so the formula is Pressure (PSI) = ( Analog Reading - 102 ) * 175 / ( 921 - 102 )
which, allowing for rounding errors, is where my 818 came from.

[/quote]

I am trying the same thing only on a unit that maxes out at 100psi

that is the only difference between wwiitteekk

the max i read is 32 psi

I hooked up a 10k rheostat the highest i got was 32psi and the lowest was -12psi

heres my code
--------------------------------------------------------------#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int psival;
int Psipin = 0;

void setup() {
lcd.begin (16, 2);
}

void loop() {
psival = analogRead(Psipin);
float y = (psival-102)*100/(921-102);

lcd.print("BOOST = ");
lcd.setCursor(0, 1);
lcd.print(y);
lcd.setCursor(5, 1);
lcd.print("PSI");
delay (100);
lcd.clear();
}

and a link the info on the pressure transducer

http://aemelectronics.com/files/instructions/30-2131-XXX%20Brass%20Pressure%20Sensor.pdf

anything will help thank you in advance

Good ol' boy 6v6gt!

Guys,

  1. How to recalculate this formula if I want to connect the output of this sensor to ESP8266 (3.3V)? I think I should use a voltage divider. Is it right if I map the output voltage this way:

Vout_mapped = (Vout / 5V) * 3.3V

  1. Besides, in a datasheet I found this formula:

Vout = 5V * (0.6667 * MPa + 0.1)

MPa out of it is calculated as follows:

MPa = (Vout - 0.1 * 5V) / (5V * 0.6667);

Very useful topic, just started playing around with the same ebay transducer that the thread was started with.

We work in bar, so my formula looks like this, since the working pressure of the transducer is 12 bar:

outputBAR = ((transducer - 102) * 12 / 819);

I'm using a MEGA 2560 and I would like to make use of the internal 1.1V reference to make the reading more accurate, but I'm not sure how to change the formula above to use the 1.1v ref. instead of 5v.

I have thrown around multiplying and dividing with 5 and 1.1 in several places in the formula but I've ended up with either 1 bar or 1.2 bar when its meant to read zero.

Help would be appreciated.

Hein

Help would be appreciated.

But, without seeing your code, and your serial output, unlikely.

This is just using standard 5V as reference:

void getPressure()
{
  unsigned long pressurecount = 0;
  float transducer = 0;
  float pressureTotal = 0;
  float outputBAR = 0;

  Serial.println(F("<<< Getting Pressure Values... >>>"));
  for (int a = 0; a < 100; a++)
  {
    transducer = analogRead(A7);
    outputBAR = ((transducer - 102) * 12 / 819);   
    Serial.print("Bar: ");
    Serial.println(outputBAR, 2);  
    pressureTotal = pressureTotal + outputBAR;
    pressurecount++;
  }
  barAVG = pressureTotal / pressurecount;
  Serial.print(F("<<< Current Running Pressure = "));  
  Serial.print(barAVG, 2);
  Serial.println(F(" bar"));
  barAVGStr = String(barAVG, 2);
  barAVG = 0;
}

Serial output:

<<< Getting Pressure Values... >>>
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.03
Bar: -0.01
Bar: -0.01
Bar: -0.01

.... etc, etc.

Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
Bar: -0.01
<<< Current Running Pressure = -0.02 bar

When using INTERNAL1V1 the values change to this, what is meant to be zero becomes 5.5

<<< Getting Pressure Values... >>>
Bar: 4.79
Bar: 5.51
Bar: 5.48
Bar: 5.51
Bar: 5.47
Bar: 5.51
Bar: 5.45
Bar: 5.45
Bar: 5.51
Bar: 5.49
Bar: 5.51
Bar: 5.45
Bar: 5.51

What I can't wrap my head around is how to change the line below to make use of internal1.1V. I know it must be very simple...

outputBAR = ((transducer - 102) * 12 / 819);

heinburgh:
This is just using standard 5V as reference...

A ratiometric (pressure) sensor MUST use default Aref, to keep it's ratiometric behaviour.
Using 1.1volt Aref would make the pressure reading dependent of the (potentially unstable) supply.

It seems you're calculating in integers.
Try: outputBAR = ((transducer - 102) * 12.0 / 819.0);

Leo..

Gotcha. Sticking to 5v then, thanks.

I calculate ~60 A/D values per bar if you're using a 1.2MPa sensor.
Not quite enough for two decimal places, but close.
Multiple reads and averaging could help.
Leo..

outputP1 = ((float)inputP1/1024*175);
// Divide by 1024 for arduino input - multiply by 175 as transducer reads 0 to 175psi

can you please explain how the formula came . please

The analog to digital converter (ADC)converts an analog DC voltage between 0 and AREF (the default AREF value is 5 volts for Arduino UNO), to a number between 0 and 1023 (1024 possible values).
Let's assume a pressure transducer outputs a voltage between 0 and 5 volts for pressures between 0 and 100, and further assume the current pressure is 50. The voltage from the transducer will be: 50 / 100 * 5 volts = 2.5 volts, so the ADC output will be: 2.5 * 1024 / AREF = 512.
To convert the ADC value back to voltage: ADC value * AREF / 1024 = voltage, or: 512 * 5 / 1024 = 2.5.
To convert voltage back to pressure: voltage * 100 / AREF,
To convert ADC value directly to pressure: ADC value / 1024 * 100 = 50.

hello i am rohith ,
can you please explain me how did you write the code

1 Like

How to interpret pressure transducer signals:

  • Calibration is key (temperature and atmosphere). If you're going to use the sensor for fluid level detection, leave the sensor in a bucket of water to bring it down to a normalized temperature before sampling your zero pressure reading.

  • The readings from transducers fluctuate. Using a circular filtering buffer is a most accurate way, but
    if memory is limited, use a high low median approach or both (smaller buffer). i.e. if reading is > p-high (store), if reading is lower than p-low (store), then divide by 2. Do this in some interval like every 250ms, then feed these results into a small circular buffer (like 20 samples), then perform median calculation. This also works well with ammeters and AC voltage detection. My example only uses a circular buffer of 200 samples but produces amazingly accurate and consistent results.

  • Size the transducer as small as possible for highest resolution, though 12-bit ADCs will be accurate even if massively oversized. For example, a 174Psi transducer on an Arduino Due has 2cm resolution when measuring water head (up to 80 meters); whereas an Uno has only 12cm of resolution (up to 122 meters depth). A 100psi transducer on a Due is accurate to 1.3cm or about 7.4cm on an Uno.

  • As far as I know, pressure transducers are the most accurate and reliable way of measuring fluid level in a well or tank of any depth. I cut around the base of the female connector of the transducer (to expose the pins better) and solder 23AWG direct burial Ethernet cable directly to the pins, bend the pins away from eachother for easier soldering. Then encase the connections in contact cement like "Amazing Goop" or silicone. This will never leak if you do it right and its good in a well over 150ft deep. The supplied connector is not even drip proof despite the seal, its complete rubbish and it has a flaky connection %80 of the time. I've thrown away perfectly good transducers by accident. Don't reverse the polarity or it's toast. The single vertical is the analog output and the two lower horizontal pins are positive 5v (left) and ground (right), confirm this by testing the connector before you solder.

  • If there is long distance between the Arduino and the transducer, make sure to use multiple conductors of the Ethernet cable but make sure that the ground wires(s) and signal return wire(s) are twisted together (to cut down on EMI). Use Green and Blue for ground and Green Strip and Blue Stripe for signal, blue/green pairs have more twists per foot and therefore are more resistant to EMI. If your motors have VFDs then you may need shielded/loomed cable.

  • Normally I use a Due or Arduino Zero - I apply 5v to the transducer. Since limited to 3.3v, the transducer will only be good for %66 of its pressure rating (to prevent over-voltage). Normally this is not an issue, just de-rate by %33 accordingly. So a 100psi transducer will have 1.34cm accuracy up to 46 meters in water or handle up to 66psi with .02psi accuracy.

Use this example to determine transducer resolution and max depth. The lower the pressure rating of transducer, the more accurate it will be.

short pressZero = 112;        //put the highest raw reading you see here at atmospheric pressure
short pressMax = 30;         //reduce pressure rating by %66 if 3.3v logic but still use 5v input
float resolution = 921.6;      //3686.4 for Due/Zero and add analogReadResolution(12) to void setup
byte analogPin = 0;           //transducer pin number
boolean autoCalibrate = true; //will automatically select highest raw reading in 10sec period

///////////////////////////////////////////////////////////////////////////////////////////////////////
byte pressStep;
short rawRead[201];
unsigned long timer;
byte calibrate;
boolean autoCalibrateComplete = false;
short pressZeroTemp;
String buf;

void setup()
{
  buf.reserve(40);
  Serial.begin(115200);
  transProp();
  delay(6000);
}

void loop()
{
  if (millis() - timer >= 1000)
  {
    float pressPsi;
    unsigned long rawTemp = 0;
    short raw;
    for (byte x = 0; x < 200; x++) rawTemp += rawRead[x];
    raw = rawTemp / 200;
    unsigned short calc1 = raw - pressZero;
    unsigned long calc2 = calc1 * pressMax;
    float calc3 = resolution - float(pressZero);
    if (raw <= pressZero) pressPsi = 0.0;
    else pressPsi = float(calc2) / float(calc3);
    float pressMeter = pressPsi * .7030695782; // psi to meters of water head
    buf = F("Raw: ");
    buf += raw;
    buf += F(" psi: ");
    buf += pressPsi;
    buf += F(" meters: ");
    buf += pressMeter;
    Serial.println(buf);
    if (autoCalibrate == true && calibrate >= 10)
    {
      if (autoCalibrateComplete == false)
      {
        pressZero = pressZeroTemp;
        buf = F("\n\nsensor re-calibrated to : ");
        buf += pressZero;
        buf += F(" (raw)\n");
        Serial.println(buf);
        transProp();
        delay(6000);
        autoCalibrateComplete = true;
      }
    }
    else
    {
      if (raw > pressZeroTemp) pressZeroTemp = raw;
      calibrate++;
    }
    timer = millis();
  }
  if (pressStep < 200) pressStep++;
  else pressStep = 0;
  rawRead[pressStep] = analogRead(analogPin);
}

void transProp() {
  buf = (F("max depth: "));
  float tDepth = pressMax;
  buf += (round(tDepth * .7030695782));
  buf += (F(" meters\n"));
  buf += (F("max resolution: "));
  float tRes = (tDepth / (resolution - float(pressZero)));
  buf += (tRes * 70.30695782);
  buf += (F("cm  or  "));
  buf += (tRes);
  buf += (F(" psi\n\n"));
  Serial.println(buf);
}

sceptre357:
Normally I use a Due or Arduino Zero. I apply 5v to the transducer, since your limited to 3.3v the transducer will only be good for %66 of its pressure rating to prevent over voltage...

This sound wrong, at least for common ratiometric pressure sensors.

Zero pressure offset and gain of the sensor also depend on sensor supply voltage,
and supply variations are cancelled out when the A/D is powered from the same supply.
With two supplies (5volt and 3.3volt), this ratiometric cancellation is lost, and you must also add sensor supply variations in your calculations.
Leo..

Wawa:
Zero pressure offset and gain of the sensor also depend on sensor supply voltage,

The supply voltage is 5v, what the transducer is rated for. Such as it is, the output remains linear.

and you must also add sensor supply variations in your calculations.

My supply doesn't have variations, or variations significant enough to affect the final result in a way that's perceivable. This isn't a relevant concern as per my conditions (externally powered 5v rail) and experience (numerous and diverse situations making full use of 12-bit ADC).

This isn't a theory but rather a well proven implementation. For example, we have a 4HP reverse osmosis system. It has 7 (cheap Chinese) pressure transducers of various ratings (100-500PSI). They all are connected to an Arduino Due @ 5v. Both motors are connected to a VFD and there is so much EMI that Hall Effect flow meters don't even work properly without shielding, signal filters and filtering capacitors. Yet, the 7 pressure transducers work perfectly fine over unshielded ethernet cable. Over 3.5 years their signals have remained true (throughout the rated range) to the analog pressure gauges and there is no difference when using a 5v MCU other than its less accurate and doesn't have the RAM for good signal buffering.

You might have taken measures to make the supply of the sensors stable (accurate is irrelevant).
But sensor readout also depends on MCU/Aref supply, and that's usually bad (blinking LEDs, LCD displays etc).
From your story I gather that you don't understand the ratiometric concept.

But you might not need or use the full 12-bit resolution, and thus don't see small variations in the readout.
Leo..

Wawa:
You might have taken measures to make the supply of the sensors stable

Yes i have; driving the MCU via external power supply directly to the 5v rail and my power supply has magical smoke.

(accurate is irrelevant).

Um accuracy is absolutely relevant; particularly when tens-of-thousands of dollars of equipment are at stake. Actually your hypothesis doesn't even apply because of the conditions; though it could in some other cases.

sensor readout also depends on MCU/Aref supply, and that's usually bad

I'm not using MCU supply and that's why it works. Im not powering other high current devices on this circuit, typically sensor boards have their own power supplies and are grounded.

From your story I gather that you don't understand the ratiometric concept.

Bold assumption, if your assuming that in all cases you cannot or should not use a 5v transducer @5v on a 3.3v ADC; this just is not accurate. In fact, using transducers (de-rated) @ 5v on a 3.3v ADC has produced wonderful results in a wide range of industrial applications. That withstanding, I appreciate your input and given some other use case there absolutely could be the potential for error but not in my case.

But you might not need or use the full 12-bit resolution, and thus don't see small variations in the readout.

I am using the full resolution. For example in large tanks even a 175psi transducer (massively oversized for only 14ft of head) gives unbelievably consistent and accurate readings with 2cm resolution. That is making use of the "full 12-bit resolution", like every single bit. I can confirm in real world use cases that it's a perfectly acceptable implementation provided proper conditions are met and i have now stated all those conditions.