Go Down

Topic: Uno : subtract digi inputs (Read 1 time) previous topic - next topic

nimba

Hi :)

I work with a flow meter with Hall-effect sensors to read the flow through a pipe (sensor A). some of the flow is not "used" and comes back in a different tube for sensor B)

I have programmed two digital inputs (2 and 3) to read the signal from the sensors

But .. can anyone help me to subtract the input signal so that I only read  the total of flow  (Sensor A - Sensor B)


The hall-effect sensors connects to pin 2 and 3 and uses interrupt 0,

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

Thanks...

MarkT

I suggest reading each flow meter separately into its own variable (by the relevant interrupt routine), and do the subtraction in loop() or whatever as needed - this means you have the option of calibrating each flow sensor separately before taking the difference.
[ I won't respond to messages, use the forum please ]

nimba

okey ... both sensors are identical and calibrated to show the same flow in input 2 & 3
Does this under say you anything ?


// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 10;


volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitresA;
unsigned long totalMilliLitresB;

unsigned long oldTime;

void setup()
{



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

  pulseCount = 0;
  flowRate = 0.0;
  flowMilliLitres = 0;
  totalMilliLitresA = 0;
  totalMilliLitresB = 0;
  oldTime = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
attachInterrupt(sensorInterruptA, pulseCounter, FALLING);
  attachInterrupt(sensorInterruptB, pulseCounter, FALLING);

:) :)

PeterH


okey ... both sensors are identical and calibrated to show the same flow in input 2 & 3


Even so, I'd use the approach MarkT suggested and process each sensor separately and then subtract the resulting flow values.
I only provide help via the forum - please do not contact me for private consultancy.

nimba

hmm...?? I dont now if I understand you , the inputs (2 and 3) read each sensor separately already .

:smiley-red:

PaulS

Quote
Does this under say you anything ?

Yep. It says "INCOMPLETE!".

MarkT

If you know the rates are calibrated the same you can get the interrupt routines to manipulate the same counter variable - you just need
to be sure that one interrupt routine can't interrupt the other (offhand I don't know, the datasheet for the ATmega328 should say).
[ I won't respond to messages, use the forum please ]

nimba

Hi

The Arduino boards have two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3).
so I would assume it would be possible, I have tested both inputs, but I can not put up a new calculation for both on the same display, someone will help a newbie ...

/**
* Water Flow Gauge
*
* Uses a hall-effect flow sensor to measure the rate of water flow and
* output it via the serial connection once per second. The hall-effect
* sensor connects to pin 2 and uses interrupt 0, and an LED on pin 13
* pulses with each interrupt. Two volume counters and current flow rate
* are also displayed on a 2-line by 16-character LCD module, and the
* accumulated totals are stored in non-volatile memory to allow them to
* continue incrementing after the device is reset or is power-cycled.
*
* Two counter-reset buttons are provided to reset the two accumulating
* counters. This allows one counter to be left accumulating indefinitely
* as a "total" flow volume, while the other can be reset regularly to
* provide a counter for specific events such as having a shower, running
* an irrigation system, or filling a washing machine.
*
* Copyright 2009 Jonathan Oxer <jon@oxer.com.au>
* Copyright 2009 Hugh Blemings <hugh@blemings.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. http://www.gnu.org/licenses/
*
* www.practicalarduino.com/projects/water-flow-gauge
123456789abcdef
1239.4L 8073.4L
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
// set the LCD address to 0x27 for a 20 chars and 2 line display


byte  sensorInterrupt = 0;// 0 = pin 2; 1 = pin 3


byte sensorPin = 2;



// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 50;


volatile byte pulseCount;



float flowRate;

unsigned int flowMilliLitres;



unsigned long oldTime;

void setup()
{
 
  delay(500);
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0, 0);
delay(100);

  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print(" ");
  lcd.setCursor(0, 1);
  lcd.print(" ");
 
  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
   
  // Set up the status LED line as an output
// We have an active-low LED attached
 
  // Set up the pair of counter reset buttons and activate internal pull-up resistors

 
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
 

  pulseCount = 0;

  flowRate = 0.0;
 
 
  flowMilliLitres = 0;
 
  oldTime = 0;
 
 

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt (sensorInterrupt, pulseCounter, FALLING);

 
}

/**
* Main program loop
*/
void loop()
{
 
  if((millis() - oldTime) > 1000)

  // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    //lcd.setCursor(15, 0);
    //lcd.print("*");
   
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
   

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
   
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate  / 60) * 1000;
   
   
    // Add the millilitres passed in this second to the cumulative total


 
    // During testing it can be useful to output the literal pulse count value so you
    // can compare that and the calculated flow rate against the data sheets for the
    // flow sensor. Uncomment the following two lines to display the count value.
    //Serial.print(pulseCount, DEC);
    //Serial.print(" ");
   
    // Write the calculated value to the serial port. Because we want to output a
    // floating point value and print() can't handle floats we have to do some trickery
    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;
   
    // Print the flow rate for this second in litres / minute
    Serial.print(int(flowRate )); // Print the integer part of the variable
   
    Serial.print("."); // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate )) * 10;
   
    Serial.print(frac, DEC) ; // Print the fractional part of the variable
   
    // Print the number of litres flowed in this second
    Serial.print(" "); // Output separator
    Serial.print(flowMilliLitres);
   
   

    // Print the cumulative total of litres flowed since starting
    Serial.print(" "); // Output separator

   

   
    lcd.setCursor(0, 0);
    lcd.print(" ");
    lcd.setCursor(0, 0);
    lcd.print("Flow:");
    if(int(flowRate ) < 10)
    {
      lcd.print(" ");
    }
    lcd.print((int)flowRate ); // Print the integer part of the variable
    lcd.print('.'); // Print the decimal point
    lcd.print(frac, DEC) ; // Print the fractional part of the variable
    lcd.print(" L");
    lcd.print("/min");
   
   
   
   
   
   


   
   

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
   
   
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

  }
}

/**
* Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
* handlers should be kept as small as possible so they return quickly.
*/
void pulseCounter()

{
  // Increment the pulse counter
  pulseCount++;

}


:) :)

PaulS

Quote
The Arduino boards have two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3).
so I would assume it would be possible, I have tested both inputs

Not with this code, you haven't.

Quote
but I can not put up a new calculation for both on the same display, someone will help a newbie ...

Sure. You take the first step, and we'll let you know if you are going the right way.

nimba

Thanks... :) :)

Then this will be my first step...if I "aktivate" Interrupt 1 on pin 3
This will give me the opportunity to read a sensor at pin 3 ??

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
// set the LCD address to 0x27 for a 20 chars and 2 line display


byte  sensorInterrupt = 0;// 0 = pin 2; 1 = pin 3
byte  sensorInterrupt = 1;// 0 = pin 2; 1 = pin 3


byte sensorPin = 2;
byte sensorPin = 3;


// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 50;


volatile byte pulseCount;

float flowRate;

unsigned int flowMilliLitres;

unsigned long oldTime;


  :smiley-red:

PaulS

Quote
if I "aktivate" Interrupt 1 on pin 3
This will give me the opportunity to read a sensor at pin 3 ??

Yes.

Code: [Select]
byte  sensorInterrupt = 0;// 0 = pin 2; 1 = pin 3
byte  sensorInterrupt = 1;// 0 = pin 2; 1 = pin 3

The compiler won't like this, and will let you know. You need different names for the two variables.

Code: [Select]
byte sensorPin = 2;
byte sensorPin = 3;

Ditto.

Code: [Select]
volatile byte pulseCount;
I'm pretty sure you'll need two of these, too. Can't use the same name for both of them, either.

nimba

In a earlier scetch I just use different letters to make them different...and it works !
So I try here...

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
// set the LCD address to 0x27 for a 20 chars and 2 line display


byte  sensorInterruptA = 0;// 0 = pin 2; 1 = pin 3
byte  sensorInterruptB = 1;// 0 = pin 2; 1 = pin 3


byte sensorPinA = 2;
byte sensorPinB = 3;


// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 50;


volatile byte pulseCountA;
volatile byte pulseCountB;



:smiley-red:


PaulS

Quote
So I try here...

It's a good start.

nimba

:) fun...
and the rest before setup.. its the same


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
// set the LCD address to 0x27 for a 20 chars and 2 line display


byte  sensorInterruptA = 0;// 0 = pin 2; 1 = pin 3
byte  sensorInterruptB = 1;// 0 = pin 2; 1 = pin 3


byte sensorPinA = 2;
byte sensorPinB = 3;


// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 50;


volatile byte pulseCountA;
volatile byte pulseCountB;

float flowRate;

unsigned int flowMilliLitres;

unsigned long oldTime;

:smiley-red:

Go Up