0

There is a problem with code related in link Interrupts Problem with Flow sensor. Code is working but when I stop the pumps, flow value on lcd is frozen until I reset the arduino. And when I start the pumps, flowmeter shows firstly 0.54 value, then begin to show real values. But always 0.54 down or up ( if flow is 5 lt/min, lcd show sometimes 5 lt/min, 5+0.54 lt/min or 5-0.54 lt/min ). When there are no oil flow into flow sensor, value of flow have fixed value that last readings. Could you help me ?

 #include <Wire.h> //I2C lib
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
 // LCD lib
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
const int pot_pin = A0;
const int pump_pwm = 3;
const int resetButton = 11;
byte press_pin = A1;
//flowmeter parameters
int flowPin = 2; // input pin on arduino D2
volatile double flowRate; // value intented to calculate
volatile double flowR; // flow value in lt
volatile double totalFlow; // total output of flow from system
byte sensorInterrupt = 0; // interrupt 0 on D2 pin Arduino Nano
volatile int count; ////integer needs to be set as volatile to ensure it updates correctly during the interrupt process. 
int pot_init= 0;
int pump_init= 0;
int percentValue =0;
unsigned long previous_read;
void setup() {
 pinMode(resetButton, INPUT);
 digitalWrite(resetButton, HIGH);
 lcd.begin(20,4); // A4 - A5 connection SDA - SCL
 lcd.backlight();
 Serial.begin(9600); 
 pinMode( flowPin,INPUT); // Set D2 pin as an input
 attachInterrupt(sensorInterrupt,Flow,RISING); // Configures interrupt 0 ( pin D2 on Arduino Nano ) to run function "Flow" 
}
void flow_control(void) {
 // Print the flow rate for this second in litres / minute
 Serial.print("Flow rate: ");
 Serial.print(int(flowRate)); // Print the integer part of the variable
 Serial.print("L/min");
 Serial.print("\t"); // Print tab space
 // Print the cumulative total of litres flowed since starting
 Serial.print("Output Liquid Quantity: "); 
 Serial.print(totalFlow/1000);
 Serial.println("L");
 if(digitalRead(resetButton) == LOW)
 {
 totalFlow = 0;
 lcd.setCursor(0, 3);
 lcd.print("Resetting.... ");
}
else {
 lcd.setCursor(0,3);
 lcd.print("Total: "); 
 lcd.setCursor(7,3);
 lcd.print(totalFlow/1000);
 lcd.print(" lt");
}
 lcd.setCursor(0,2);
 lcd.print("Flow: ");
 lcd.setCursor(6,2);
 lcd.print(flowRate);
 lcd.print(" lt/min");
}
void Flow(void) 
{
 count++; // every time this function is called, increment "count" by 1
 if(millis() - previous_read > 1000){
 noInterrupts(); // disable interrupts on arduino nano
 int local_count = count;
 count=0;
 interrupts(); // enables interrupts on arduino nano
 previous_read += 1000;
 flowR = (local_count*8.93); // 112 pulse/lt 423.84 pulse /gallon 
 flowRate= flowR*60; // convert seconds to minutes, new unit is ml/minutes
 flowRate= flowRate/1000; // convert ml to liters, new unit is lt/minutes
 totalFlow += flowR;
 //process flowrate based on local_count
 //calculation for flowmeter 
 }
}
void loop() {
 pressure_cal(); 
 pump_control();
 flow_control();
}
void pressure_cal(void) {
 float sensorVoltage = analogRead(press_pin); // sensor voltage A0
 float psi = ((sensorVoltage-102)/204)*25; // Offset 0 PSI= 0.5V=102 unit, 50 PSI= 2.5, 100 PSI= 4.5V, 1 PSI= 0.04V
 // calibration 
 float bar = psi*(0.0689475729); // Conversion PSI to BAR
 lcd.setCursor (0,1);
 lcd.print (psi);
 lcd.print (" PSI");
 lcd.setCursor ( 10,1);
 lcd.print(bar);
 lcd.print( " BAR");
 //lcd.setCursor(17,1);
 //lcd.print(sensorVoltage);
 Serial.print("\t Sensor Value = ");
 Serial.print(sensorVoltage);
 Serial.print("\t Bar = ");
 Serial.print(bar);
 Serial.print("\t PSI = ");
 Serial.println(psi);
 delay (100);
}
void pump_control(void)
{
 // read the analog in value:
 pot_init = analogRead(pot_pin);
 // map it to the range of the analog out:
 pump_init = map(pot_init, 0, 1023, 50, 230); // duty cycle between %20 - %90: speed control , duty cycle between %0 - %20: turned off , duty cycle between %90 - %100: full speed
 // map pump speed percent of full scale
 percentValue = map (pump_init, 50, 230,0,100);
 // change the analog out value:
 analogWrite(pump_pwm, pump_init);
 // print the results to the Serial Monitor:
 Serial.print("\t Speed Input = ");
 Serial.print(pot_init);
 Serial.print("\t Speed Output = ");
 Serial.print(pump_init);
 Serial.print("\t Pump Speed Percentage = ");
 Serial.println(percentValue);
 lcd.setCursor(2,0); 
 lcd.print("Speed: ");
 lcd.setCursor(8,0); 
 lcd.print("%"); 
 lcd.setCursor(9,0); 
 lcd.print(percentValue); 
 lcd.print(" "); 
 // delay after the last reading:
 delay(10);
}
asked Aug 27, 2018 at 6:05
2
  • It is about the variable flowRate? Where is that variable calculated? Spoiler: in the interrupt. When there are no interrupts, that value is not calculated. I don't see a simple solution. The interrupt counts and the flowR should use that count (even if it is zero). That means you have to calculate flowR in the Arduino loop, you can use millis to calculate the actual elapsed time to allow that it is sometimes longer than 1 second. Commented Aug 27, 2018 at 6:28
  • But I add the interrupt code in void loop and function called by main loop. Code dont work. The code I added works , but there is stability problem. When ı begin arduino, Flow sensor shows 0.54 lt/min on LCD. And when flow begin, flowrate changes with +- 0.54 error ( like 4.00 lt/min then 4.54lt/min then 3.46 lt/min and ) How can I solve this problem in void loop ? Commented Aug 28, 2018 at 6:40

1 Answer 1

1

if (millis() - previous_read > 1000) { [...] previous_read += 1000; [...] }

The code inside this block is obviously meant to be executed every second. However, since this belongs to the interrupt handler, it only has a chance to execute when the flow-meter sends interrupts. If the flow is zero or very weak, this will not execute often enough.

flowmeter shows firstly 0.54 value

It is no coincidence that 0.54 is what you get when count == 1.

The piece of code above should be moved to the main loop(), or to a function called from loop(). This way it will execute consistently irrespective of whether there is some flow or not, which is the only way to reliably read a zero flow. Note that for better timing consistency you should avoid doing something like...

delay(100);

Don't do this. Instead, use the same trick as above:

if (millis() - previous_pressure_print > 100) {
 previous_pressure_print += 100;
 pressure_cal();
}
answered Aug 27, 2018 at 7:40
2
  • But I add the interrupt code in void loop and function called by main loop. Code dont work. The code I added works , but there is stability problem. When ı begin arduino, Flow sensor shows 0.54 lt/min on LCD. And when flow begin, flowrate changes with +- 0.54 error ( like 4.00 lt/min then 4.54lt/min then 3.46 lt/min and ) How can I solve this problem in void loop ? Commented Aug 28, 2018 at 6:36
  • @sapphire: Do not describe the code, show it! Edit your question and add the version of the code you are talking about. Commented Aug 28, 2018 at 7:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.