|
|
0
Offline
Tesla Member
Karma: 76
Posts: 6849
Arduino rocks
|
 |
« Reply #1 on: September 23, 2012, 07:35:51 pm » |
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
|
|
|
|
|
Norway
Offline
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #2 on: September 25, 2012, 11:26:25 am » |
Something like this? #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
Jr. Member
Karma: 0
Posts: 63
Arduino rocks
|
 |
« Reply #3 on: September 25, 2012, 09:41:07 pm » |
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
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #4 on: September 29, 2012, 05:50:57 pm » |
I think I am into something here: #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
Jr. Member
Karma: 0
Posts: 63
Arduino rocks
|
 |
« Reply #5 on: October 03, 2012, 09:24:31 pm » |
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 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
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #6 on: October 12, 2012, 05:18:40 pm » |
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.pdeI 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: #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
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 101
Posts: 9551
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #7 on: October 14, 2012, 10:14:26 am » |
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  #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
|
|
|
|
|
Norway
Offline
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #8 on: October 15, 2012, 03:20:14 pm » |
Hi Rob and thanks for your help with this!!  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  Regards, Fredrik
|
|
|
|
|
Logged
|
Best regards, Fredrik
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 101
Posts: 9551
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #9 on: October 16, 2012, 01:17:05 pm » |
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
|
|
|
|
|
Norway
Offline
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #10 on: October 16, 2012, 02:57:48 pm » |
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  Sure, I will post the final result, if other also are planning to do similar  Regard, Fredrik
|
|
|
|
|
Logged
|
Best regards, Fredrik
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 101
Posts: 9551
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #11 on: October 19, 2012, 04:19:25 am » |
That's the idea of open source, sharing and learning and building on top of each other.
|
|
|
|
|
Logged
|
|
|
|
|
Norway
Offline
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #12 on: December 25, 2012, 10:15:51 am » |
#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  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
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 101
Posts: 9551
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #13 on: December 25, 2012, 10:46:08 am » |
Super that it works now, some remarks if((now - oldTime > 1000)) I would use >= 1000 and the additional ()'s do not add anything  no need to 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 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 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
|
|
|
|
|
Norway
Offline
Newbie
Karma: 1
Posts: 43
Arduino rocks harder than ever!
|
 |
« Reply #14 on: December 25, 2012, 11:55:46 am » |
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: #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
|
|
|
|
|