Pressure differential sensor, analog input issue

Hey Guys,

I'm inputing and analog signal from a pressure differential sensor with the ultimate goal of keeping track of fuel usage on a vehicle using a Bernoulli Meter. My problem is that when there is no pressure difference it will automatically make a variable(tank) =0 even though it started out as 1. If I create a pressure difference right away it will count down from 1 like it is supposed to, but as soon as the difference goes to 0 everything goes to zero. The line in question is about 2/3 of the way down(tank=tank-volFlow) I have experience coding in MatLab, C++, and Basic but I have litte experience reading sensors. Sorry for the ton of variables at the top of the code, it has been rewritten several times over to try and correct this issue.

Thanks in advance

int counter1=1;
int counter2=1;
double kpa=0.0;
double vel=0.0;
double psi=0.0;
double volFlow=0.0;
double spentInt=0.0;
double spentTot=0.0;
double tank = 1.0; //one gallon of gas in tank to start
double total = 0.0;
const double area1=0.7854;
const double area2=1.7671;
const double rho=6.073; //density of gasoline


void setup() {

  Serial.begin(9600);
}

void loop() {
  // read input on analog pin 0
  float sensorValue = analogRead(A0);
  // Convert the analog reading to a voltage
  float voltage = sensorValue * (5.0 / 1023.0);
  //transfer function to pressure(kpa)
  kpa=((voltage/5.0)-0.04)/0.018;
  //convert kpa to psi
  psi=kpa/0.1450377;
  //convert pressure to output velocity(Bernoulli equation)
  vel=sqrt((2*psi)/(rho*(1-((area1/area2)*(area1/area2)))));
  //convert velocity to volumetric flow rate(gallon/sec)
  volFlow=(vel*area2)*0.004329;
  //subratcts the volumetric flow rate from amount left in tank
  tank=tank-volFlow; //this is were I think the problem is

  //print intantaneous usage then amount left in tank
  Serial.println("Gallons Per sec= ");
  Serial.print("\t");
  Serial.println(volFlow, OCT);
  Serial.println("tank= ");
  Serial.print("\t");
  Serial.println(tank, OCT);
  delay(1000);

  
}

Is the sensor a flow sensor ? Can you tell which one and add a link to it ? (just copy the url in the message).
In your code, the flow sensor must output 0V if there is no flow.

You use octal ('OCT') notation for a double precision floating point.
http://arduino.cc/it/Serial/Print
But the octal notation is only used by old programmer pioneers with long white beards.
Just use "Serial.println(volFlow);" to print a floating point number, or "Serial.println(volFlow,3);" with 3 digits after the comma. The same goes for the 'tank' variable.

Krodal:
Is the sensor a flow sensor ? Can you tell which one and add a link to it ? (just copy the url in the message).
In your code, the flow sensor must output 0V if there is no flow.

You use octal ('OCT') notation for a double precision floating point.
http://arduino.cc/it/Serial/Print
But the octal notation is only used by old programmer pioneers with long white beards.
Just use "Serial.println(volFlow);" to print a floating point number, or "Serial.println(volFlow,3);" with 3 digits after the comma. The same goes for the 'tank' variable.

Due to function overloading, if the first parameter is a floating point number the second parameter is taken as the precision, not the base. OCT is a macro equating to 8, so printing a floating point number with OCT will yield a floating point number with 8 decimal place precision. It will not display it as octal.

And I am neither old (well, not that old), and I don't have a grey beard (neither do I wear sandals), yet I do use octal on a daily basis. It is no more "old fashioned" than hexadecimal - it's just a different way of grouping bits - 3 instead of 4.

majenko:
Due to function overloading, if the first parameter is a floating point number the second parameter is taken as the precision, not the base. OCT is a macro equating to 8...

That's not how to use it, in my opionon. I thinks it's even erroneous misusage of something not ment for it.

About the octal usage, only people using octal think that way... :wink: I have used this long time ago (just once): PDP-11 - Wikipedia

Krodal:

majenko:
Due to function overloading, if the first parameter is a floating point number the second parameter is taken as the precision, not the base. OCT is a macro equating to 8...

That's not how to use it, in my opionon. I thinks it's even erroneous misusage of something not ment for it.

Oh, I never said it was right - I was just describing the effects of using it like that.

About the octal usage, only people using octal think that way... :wink: I have used this long time ago (just once): PDP-11 - Wikipedia

I have an emulator for that :stuck_out_tongue:

Is the sensor a flow sensor ? Can you tell which one and add a link to it ? (just copy the url in the message).
In your code, the flow sensor must output 0V if there is no flow.

Here is the link to the sensor I'm using.

It should read 0+- a little error. The analog reads about 30 when there is no pressure differential. thats a voltage of about 0.14

On a second note, I have not wired any capacitors in to the circuit yet, I am waiting to get the code working first, then im going to do calibration and noise suppression.

We are still in the dark.

Do you have a MPX5050 ?
That seems a nice sensor. It is linear and it's output (0-5V) is perfect for the Arduino.
This is the product summary: http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPXx5050
The offset of 0.14V is within the specifications.

But you have a pressure transducer (Bernoulli Meter) with a differential pressure sensor. Which sensor of the MPX5050 family do you have. Does that transducer have a name? did you built it yourselfe ? do you have a link to it or a photo?

Did you remove the 'OCT' parameter when printing 'volFlow' and 'tank'.

Your code seems okay. I don't know why it becomes 0.
Can you give us the result of a number of outputs. I guess that the 'volFlow' (gallons per second) is a small number.

Have you seen this: http://arduino.cc/playground/Main/Waterlevel

I have a project where I need to measure the flow of air with a similar setup. I had been so far unsuccessful finding a formula to use, so thanks for a formula I think I can use! But I have a question, what are area1 and 2. I have a constant area for the pipe the air is flowing through, with 30 inches between measurement points. Does the same formula fit?

Jim

One thing to try -
Zero flow is a special condition that means you don't have to do any calculations that time through the scan. It is possible that zero is causing one of your calculations do mess up and crash other variables.

Sorry I will be more specific: the sensor is the MPX5050DP, CASE 857C-05. I have not made the physical Bernoulli section, I have just put dumby areas in and created the pressure difference with my mouth. I am building my own Bernoulli meter. I tried removing OCT and it does not change the results. Here is a list from the serail monitor. I started with a pressure difference then stopped creating the pressure difference then created it again.

Gallons Per sec= 
	0.01644657
tank= 
	0.98355340
Gallons Per sec= 
	0.02999923
tank= 
	0.95355415
Gallons Per sec= 
	0.01239311
tank= 
	0.94116106
Gallons Per sec= 
	0.00000000
tank= 
	0.00000000
Gallons Per sec= 
	0.00000000
tank= 
	0.00000000
Gallons Per sec= 
	0.02830261
tank= 
	0.00000000
Gallons Per sec= 
	0.02782195
tank= 
	0.00000000
Gallons Per sec= 
	0.02877525
tank= 
	0.00000000
Gallons Per sec= 
	0.00000000
tank= 
	0.00000000
Gallons Per sec= 
	0.00000000
tank= 
	0.00000000
Gallons Per sec= 
	0.00000000

Any ideas? I may try inputing an if statement that controls when it starts subtracting?

On a second note: Jim that forumla will not fit your application, the difference in areas is what will create the pressure difference. My hose is a constant diameter with a small section that acts as the Bernoulli section(change in diameter). The reason I can do this is because liquids can be treated as incompressible fluids. Air is highly compressible under some conditions (above mach 0.3 and/or is pressure is above 1 atm). What is creating the pressure difference? and what is the ultimate goal? to measure losses in the pipe? Everything thing should remain constant inside that pipe because it has a constant area. What you really need is the stagnation pressure(pressure in the compressor) and then one pressure in the pipe. Using that information you can get the velocity in the pipe. The equations are slightly more complicated for your application. You just need more information.

Thank you for the additional information.

The way you test it is valid, the sensor is valid, and the sketch seems valid. So I tested your sketch, and got the same result. Also my tank became 0.00000. By printing every variable the problem was soon located:
You take the square-root of a negative number !
That causes to return an floating point number with an error, and that error is passed on to the next caculations.

Old code:vel=sqrt((2*psi)/(rho*(1-((area1/area2)*(area1/area2)))));

New code:

double t = (2*psi)/(rho*(1-((area1/area2)*(area1/area2))));
if (t > 0.0)
  vel = sqrt (t);
else
  vel=0.0;

I read that the avr gcc libraries changed the floating point part, but I don't know if the newest version is already in use by Arduino.

There are a few more things:

  • Remove the 'OCT', replace it with a number for the precision. Make it 5 or so.
  • Use 'double' for the 'sensorValue' and the 'voltage'.
  • I would also prefer this: double sensorValue = (double) analogRead(A0);

No thank you very much. I didn't even think about checking that. Thank you very much again I owe you a beer.

If anyone else is curious here is my final code with a switch input that will be used when the vehicle is refueled.

//measure gasoline velocity using a bernouli meter
double kpa=0.0;
double psi=0.0;
double vel=0.0; //velocity in area 2
double volFlow=0.0;
double tank = 1.0; //amount of fuel to start
const double area1=0.7854; //area of section inlet  
const double area2=1.7671; //area of section outlet
const double rho=6.073; //density of gasoline

void setup() {

  Serial.begin(9600);
  pinMode(2, INPUT);
}

void loop() {
  // read input on analog pin 0
  double sensorValue =(double) analogRead(A0);
  // Convert the analog reading to a voltage
  double voltage = sensorValue * (5.0 / 1023.0);
  volFlow=0;  
    kpa=((voltage/5.0)-0.04)/0.018; //transfer function to pressure(kpa)
    psi=kpa/0.1450377;   //convert kpa to psi
    double t = (2*psi)/(rho*(1-((area1/area2)*(area1/area2))));  //convert pressure to output velocity
    
    // makes sure code doesnt take sqrt of negative
    if (t > 0.0)
      vel = sqrt (t);
    else
      vel=0.0;
    
    volFlow=(vel*area2)*0.004329;  //convert velocity to volumetric flow rate(gallon/sec) 
    tank=tank-volFlow;  //subratcts the volumetric flow rate from amount left in tank
   
  //print intantaneous usage then amount left in tank
  
  Serial.println("Gallons Per sec= ");
  Serial.print("\t");
  Serial.println(volFlow, 5);
  Serial.println("tank= ");
  Serial.print("\t");
  Serial.println(tank, 5);
  int button = digitalRead(2);   // read button for fuel tank reset
  if ( button == 1)   //reset fuel tank if button is pressed
    tank = 1;
  delay(1000);
}

Glad to be of help. Your code is looking a lot better. :slight_smile: