Pages: [1] 2   Go Down
Author Topic: Using two flow sensors connected to one Arduino.  (Read 5113 times)
0 Members and 1 Guest are viewing this topic.
Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi.

My friend and I, are trying to figure out a way to use two flow sensor to read a fuel consumption. The first one is for main fuel flow into a pump. The other one is for return fuel from the injector and back to the fuel tank. So, if we call the main fuel sensor for sens1 and the return for sens2 the mathematics will be like this: sens1-sens2=actually fuel consumption.

How do we program two sensors together. How can we get one of the sensor values to be subtracted from the other sensor value?

We tried to use "NbTopsFan++" but it did not work.

We use two of these sensors http://www.btflowmeter.com/en/products/flow-meters-lowflow-flowmeters-low-flow-turbine-flow-meter-fuel-flow-meters-diesel-fuel-flow-meter-watermeters-paddlewheel-flow-meter-oil-flow-meter-oilflowmeter-waterflowmeter-water-meters-turbineflowmeter-oilflowmeter/low-flow-flowmeters-fch-m-pom-series-0002-8-lpm/fch-m-pom-lc-08-lpm-97478617-lc.html

Thanks for your help  smiley-cool

Best regards, Fredrik
« Last Edit: September 23, 2012, 02:42:40 pm by KapteinFredrik » Logged

Best regards, Fredrik

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12200
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The short answer is get one sensor working, then add another, then use the '-' operator on the results.  But there's v. similar posting recently that might be relevant: http://arduino.cc/forum/index.php/topic,123039.0.html
Logged

[ I won't respond to messages, use the forum please ]

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Something like this?

Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

byte sensorInterruptA  = 0; 
byte sensorInterruptB  = 1;
byte sensorPinA        = 2;
byte sensorPinB        = 3;

float calibrationFactor = 50;

volatile byte pulseCount;

float flowRate;
unsigned int turFuel;
unsigned int returFuel;

unsigned long oldTime;

void setup()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
 
  Serial.begin(38400);
 
  pulseCount    = 0;
  flowRate      = 0.0;
  turFuel       = 0;
  returFuel     = 0;
  oldTime       = 0;
 
  attachInterrupt(sensorInterruptA, pulseCounter, FALLING);
  attachInterrupt(sensorInterruptB, pulseCounter, FALLING);
}

//hovedprogrammet i loop.

void loop()
{
  if((millis() - oldTime > 1000)
  {
    detachInterrupt(sensorInterrupt);
   
    flowRate = ((1000.0 / (millis() - oldtime)) * pulseCounat) / calibrationFactor;
   
    oldTime =millis();
   
    flowrate = (turFuel - returFuel) / 8500;
   
    unsigned int frac;
   
    Serial.print(int(flowRate));
    Serial.print(".");           
    frac = (flowRate - int(flowRate)) * 10;
    Serial.print(frac, DEC) ;
   
    Serial.print(" ");             
    Serial.print(flowRate);
   
     lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Flow: ");
    if(int(flowRate) < 10)
    {
      lcd.print(" ");
    }
    lcd.print((int)flowRate);   
    lcd.print('.');             
    lcd.print(frac, DEC) ;     
    lcd.print(" L");
    lcd.print("/min");
   
    pulseCount = 0;
   
    attachInterrupt(sensorInterrupt, pulseCounterA, FALLING);
    attachInterrupt(sensorInterrupt, pulseCounterB, FALLING);
  }
}

void pulseCounter()
{
  pulseCount++;
}
   
   
   
   
Logged

Best regards, Fredrik

Indonesia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 70
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think we can use PinChangeInt

One Digital input for each FlowSensor

Lets say the variable to hold Fuel Consumption is 'fc'.
First PinChangeInt (The forward) will add 1 to fc, and the second (The return) will substract 1 from fc

The main loop only check for time periode.
When the periode reached, calculate the real fuel consumption basd on fc and your sensor spec (pulse/galon). That if you want consumption per time

Alternatively, if you easy about acuration, you can put freq devider (prescaler) between the Forward-Sensor and First PinChangeInt.

I'm pretty sure soon you will also want to look at the RPM.

Have a nice hack
-bino-
Logged

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I am into something here:

Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

byte sensorA = 0;
byte sensorB = 1;
byte sensorPinA = 2;
byte sensorPinB = 3;

float calibrationFactor = 50;

volatile byte pulseCount;

float flowRate;
unsigned int turFuel;
unsigned int returFuel;

unsigned long oldTime;

void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");

Serial.begin(38400);

pinMode(sensorA, INPUT);
pinMode(sensorB, INPUT);

pulseCount  = 0;
flowRate    = 0.0;
turFuel     = 0;
returFuel   = 0;
oldTime     = 0;

attachInterrupt(sensorA, pulseCounter, FALLING);
attachInterrupt(sensorB, pulseCounter, FALLING);
}

//hovedprogrammet i loop.

void loop()
{
if((millis() - oldTime > 1000))
{
detachInterrupt(sensorA);
detachInterrupt(sensorB);

flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

oldTime =millis();

flowRate = (sensorA - sensorB) / 8500;

unsigned int frac;

Serial.print(int(flowRate));
Serial.print(".");
frac = (flowRate - int(flowRate)) * 10;
Serial.print(frac, DEC) ;

Serial.print(" ");
Serial.print(flowRate);

lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Flow: ");
if(int(flowRate) < 10)
{
lcd.print(" ");
}
lcd.print((int)flowRate);
lcd.print('.');
lcd.print(frac, DEC) ;
lcd.print(" L");
lcd.print("/min");

pulseCount = 0;

attachInterrupt(sensorA, pulseCounter, FALLING);
attachInterrupt(sensorB, pulseCounter, FALLING);
}

void pulseCounter()
{
  pulseCount++;
}

Or what do you think? I get a problem in one of the last lines in this code. Can anyone help with that problem?

Regards, Fredrik.
Logged

Best regards, Fredrik

Indonesia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 70
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why you Attach two interupt pin to the same Function ( pulseCounter() ) ?
SensorPinA have to always *increase* the counter, and
SensorPinB have to alwayas *decrease* the counter.

I did it using PinChangeInt Library,
but here is the basic operation using attachInterupt


Code:

long lastMillis=0;
long curMillis=0;
int RptInterval=1000 ;

int SensorPinFwd = 2;
int SensorPinRtr = 3;
int FlowClick = 0;

void setup(){
   
    pinMode(SensorPinFwd, INPUT);
    pinMode(SensorPinRtr, INPUT);


    attachInterrupt(SensorPinFwd, FuncFlowFwd, FALLING);
    attachInterrupt(SensorPinRtr, FuncFlowRtr, FALLING);

    lastMillis=millis();
    curMillis=lastMillis;

    /*
    And do other setup for serial and LCD here
    */
}

void loop(){
    curMillis = millis();
    if (curMillis-lastMillis >RptInterval) {
        doReport;
        lastMillis = curMillis;
    }
   
}

void FuncFlowFwd(){
    FlowClick=FlowClick+1;
}
void FuncFlowRtr(){
    FlowClick=FlowClick-1;
}
void doReport(){
    /*
    Do any calculation and report/display here
    */
}

Logged

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for help binooetomo, but I can't get this to work properly. Actually, nothing work properly here right now. This works like a charmike a charm: https://github.com/practicalarduino/WaterFlowGauge/blob/master/WaterFlowGauge.pde

I have also tried to modify my first sketch to work, but nothing happends after compiling, uploading and opening the serial monitor.

I am so far here:
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

byte sensorInterruptA = 0;
byte sensorInterruptB = 1;
byte sensorPinA = 2;
byte sensorPinB = 3;

float calibrationFactor = 4.5;

volatile byte pulseCount;

float flowRate;
unsigned int flowRateA;
unsigned int turFuel;
unsigned int returFuel;

unsigned long oldTime;

void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");

Serial.begin(9600);

pinMode(sensorPinA, INPUT);
pinMode(sensorPinB, INPUT);
digitalWrite(sensorPinA, HIGH);
digitalWrite(sensorPinB, HIGH);

pulseCount           = 0;
pulseCount           = 0;
flowRate             = 0.0;
sensorInterruptA     = 0;
sensorInterruptB     = 0;
oldTime              = 0;

attachInterrupt(sensorInterruptA, pulseCounter, FALLING);
attachInterrupt(sensorInterruptB, pulseCounter, FALLING);
}

//hovedprogrammet i loop.

void loop()
{
  if((millis() - oldTime > 1000))
  {
  detachInterrupt(sensorInterruptA);
  detachInterrupt(sensorInterruptB);

  oldTime =millis();

  flowRate = (sensorInterruptA - sensorInterruptB) / 8500;
 
  flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
 
  flowRateA = (flowRate / 60) * 1000;
 
  unsigned int frac;

  Serial.print(int(flowRateA));
  Serial.print(".");
  frac = (flowRateA - int(flowRateA)) * 10;
  Serial.print(frac, DEC) ;
 
  Serial.print(" ");
  Serial.print(flowRateA);

  lcd.setCursor(0, 0);
  lcd.print(" ");
  lcd.setCursor(0, 0);
  lcd.print("Flow: ");
  if(int(flowRate) < 10)
  {
    lcd.print(" ");
  }
  lcd.print((int)flowRate);
  lcd.print('.');
  lcd.print(frac, DEC) ;
  lcd.print(" L");
  lcd.print("/min");

  pulseCount = 0;

  attachInterrupt(sensorInterruptA, pulseCounter, FALLING);
  attachInterrupt(sensorInterruptB, pulseCounter, FALLING);
  }
}
  void pulseCounter()
{
  pulseCount++;
}

Regards, Fredrik
Logged

Best regards, Fredrik

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

fiddled a bit with your code:
+ use #define for those vars that are not changeable
+ made 2 different IRQ's one for counting the IN pulses and one for counting the out pulses
+ changed some var names to reflect what they meant like litersperminute
+ use a copy of millis() in the if block as millis() might change during the block (accuracy)
+ probably screwed up the math but you should be able to fix that relative easily
+ made some vars local instead of global (reduce scope)

have a look and give it a try (not tested as I don't have an I2CLCD nearby smiley
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16, 2);

// as these are const one better use #defines
#define IRQ_A 0
#define IRQ_B 1
#define PIN_A 2
#define PIN_B 3

// a separate counter per channel
volatile unsigned long countIN = 0;
volatile unsigned long countOUT = 0;
unsigned long oldTime  = 0;

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

  Serial.begin(9600);

  pinMode(PIN_A, INPUT);
  pinMode(PIN_B, INPUT);
  digitalWrite(PIN_A, HIGH);
  digitalWrite(PIN_B, HIGH);

  attachInterrupt(IRQ_A, CounterIN, FALLING);
  attachInterrupt(IRQ_B, CounterOUT, FALLING);
}

void loop()
{
  // use a var for value of millis, as it might change in the if .... block
  // due to slow serial prints
  unsigned long now = millis();
  if((now - oldTime > 1000))
  {
    unsigned long duration = now - oldTime;
    oldTime = now;

    // use names that indicate the unit!
    // don't know if all math is correct anymore
    // 8500 pulses per liter?
    float liters = (countIN - countOUT) * 0.000117647; // faster than divide by 8500.0
    float litersPerMinute = (1000 * liters)/duration / 60; // optimized 16.66667*liters/duration

    Serial.print(duration);
    Serial.print(",");  // separate by comma's so you can copy output to Excel easily.
    Serial.println(litersPerMinute, 3);     // print a float with three decimals

    int LPM = litersPerMinute;               // implicit conversion to int
    int frac = (litersPerMinute-LPM)*10;
    lcd.setCursor(0, 0);
    lcd.print("Flow L/min: ");
    lcd.print(LPM); 
    lcd.print(".");   
    lcd.print(frac); 
    lcd.print(" ");
  }
}

void CounterIN()
{
  countIN++;
}

void CounterOUT()
{
  countOUT++;
}

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob and thanks for your help with this!!  smiley This looks very good, but this sketch did not work as I hoped it would, but I think you are into something good there. I will try to understand more of it tomorrow. I dont either have the LCD, but my companion will test it when he finnishes his work in the North Sea  smiley-razz

Regards, Fredrik
Logged

Best regards, Fredrik

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The code is definitely not correct (some parts are missing) but should inspire you to improve your coding skills.

Hopes it helps! Succes!

PS, please post your final result when it works
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The code is definitely not correct (some parts are missing) but should inspire you to improve your coding skills.

Hopes it helps! Succes!

PS, please post your final result when it works

Thanks so much smiley Sure, I will post the final result, if other also are planning to do similar  smiley-cool

Regard, Fredrik
Logged

Best regards, Fredrik

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's the idea of open source, sharing and learning and building on top of each other.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#define IRQ_A 0
#define IRQ_B 1
#define FlowA 2
#define FlowB 3

volatile unsigned long countIN = 0;
volatile unsigned long countOUT = 0;
unsigned long oldTime  = 0;
float flowRate;

volatile byte pulseCountIN;
volatile byte pulseCountOUT;
volatile byte pulseCount;

float liters;

void setup()
{
  Serial.begin(57600);
 
  pulseCountIN = 0;
  pulseCountOUT = 0;
  pulseCount = 0;
  flowRate = 0.0;

  pinMode(FlowA, INPUT);
  pinMode(FlowB, INPUT);
  digitalWrite(FlowA, HIGH);
  digitalWrite(FlowB, HIGH);
 
  liters = 0.0;

  attachInterrupt(IRQ_A, CounterIN, FALLING);
  attachInterrupt(IRQ_B, CounterOUT, FALLING);
}

void loop()
{
  unsigned long now = millis();
  if((now - oldTime > 1000))
  {
    unsigned long duration = now - oldTime;
    oldTime = now;

    liters = (countIN - countOUT);
    float litersPerMinute = (1000 * liters)/duration;
    Serial.println(litersPerMinute, 3);   
    int LPM = litersPerMinute;           
   
    pulseCount = pulseCountIN - pulseCountOUT;
       

    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount);
    unsigned int frac = (flowRate - int(flowRate))*10;
    Serial.print("pulseCount: ");
    Serial.print(pulseCount, DEC);
    Serial.println(" ");

       
    pulseCountIN = 0;
    pulseCountOUT = 0;
   
    attachInterrupt(IRQ_A, CounterIN, FALLING);
    attachInterrupt(IRQ_B, CounterOUT, FALLING); 
  }
}

void CounterIN()
{
  countIN++;
  pulseCountIN++;
}

void CounterOUT()
{
  countOUT++;
  pulseCountOUT++;
}

This is my last version of the sketch, and now it works! Thanks so much for your help smiley-grin  I will keep developing this sketch to work more properly. I added two more volatile bytes, because the first sketch did not work.
Logged

Best regards, Fredrik

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Super that it works now,

some remarks

Code:
if((now - oldTime > 1000))
I would use >= 1000   
and the additional ()'s do not add anything smiley


no need to
Code:
    attachInterrupt(IRQ_A, CounterIN, FALLING);
    attachInterrupt(IRQ_B, CounterOUT, FALLING); 
at the end of every loop, as you do not detach them (you shouldn't)

writing
Code:
float litersPerMinute = (1000.0 * liters)/duration;
makes explicit that the math is done in float (it is, as liters is already float, but just looking at the original line it could have been integer math)


for the readability I would group the math and the display statements in the loop, something like
Code:
void loop()
{
  unsigned long now = millis();
  if((now - oldTime >= 1000))
  {
    // TIME MATH
    unsigned long duration = now - oldTime;
    oldTime = now;

    // FLOW MATH
    liters = (countIN - countOUT);
    float litersPerMinute = (1000.0 * liters)/duration;
    int LPM = litersPerMinute;           
    pulseCount = pulseCountIN - pulseCountOUT;
    pulseCountIN = 0;
    pulseCountOUT = 0;

    flowRate = (1000.0 / duration) * pulseCount);
    unsigned int frac = (flowRate - int(flowRate))*10;

    // DISPLAY RESULTS
    Serial.println(litersPerMinute, 3);   
    Serial.print("pulseCount: ");
    Serial.print(pulseCount, DEC);
    Serial.println("  ");  // to remove trailing digit when printed on lcd iso serial
  }
}

How many pulses do the devices give per liter?


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 44
Arduino rocks harder than ever!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks. I have cleaned up a bit more here, but its not perfect yet. The whole system is not accurate enough. I need the sensors to be very accurate for this project, and I think it is something inside here who makes the difference:

Code:
#define IRQ_A 0
#define IRQ_B 1
#define FlowA 2
#define FlowB 3

volatile unsigned long countIN = 0;
volatile unsigned long countOUT = 0;
unsigned long oldTime  = 0;
float flowRate;



volatile float pulseCountIN;
volatile float pulseCountOUT;
volatile float pulseCount;

float liters;

void setup()
{
  Serial.begin(57600);
 
  pulseCountIN = 0.0;
  pulseCountOUT = 0.0;
  pulseCount = 0.0;
  flowRate = 0.0;

  pinMode(FlowA, INPUT);
  pinMode(FlowB, INPUT);
  digitalWrite(FlowA, HIGH);
  digitalWrite(FlowB, HIGH);
 
  liters = 0.0;

  attachInterrupt(IRQ_A, CounterIN, FALLING);
  attachInterrupt(IRQ_B, CounterOUT, FALLING);
}

void loop()
{
  unsigned long now = millis();
  if(now - oldTime >= 1000)
  {
    unsigned long duration = now - oldTime;
    oldTime = now;

    liters = (countIN - countOUT);
    float litersPerMinute = (1000 * liters)/duration;   
    int LPM = litersPerMinute;           
   
    pulseCount = (pulseCountIN - pulseCountOUT) / 10000.0 * 3600;
       

    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount);
    unsigned int frac;
    Serial.print("Liter per time: ");
    Serial.println(pulseCount, 4);
     
    pulseCountIN = 0;
    pulseCountOUT = 0;
     
  }
}

void CounterIN()
{
  countIN++;
  pulseCountIN++;
}

void CounterOUT()
{
  countOUT++;
  pulseCountOUT++;
}

When I connect the hoses and sensors to the water faucet, the sensors gives me this: results
Liter per time: 23.4000
Liter per time: 24.1200
Liter per time: 24.8400
Liter per time: 25.2000
Liter per time: 25.5600
Liter per time: 24.8400

...and that is not what I had expected.
The engines I develop this flow meter to, uses between 3 and 50 liters per hour.

Do you understand what I have done wrong?

Cheers, Fredrik

« Last Edit: December 25, 2012, 12:00:32 pm by KapteinFredrik » Logged

Best regards, Fredrik

Pages: [1] 2   Go Up
Jump to: