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);
}
-
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.Jot– Jot2018年08月27日 06:28:54 +00:00Commented 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 ?sapphire– sapphire2018年08月28日 06:40:20 +00:00Commented Aug 28, 2018 at 6:40
1 Answer 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();
}
-
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 ?sapphire– sapphire2018年08月28日 06:36:21 +00:00Commented 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.Edgar Bonet– Edgar Bonet2018年08月28日 07:08:50 +00:00Commented Aug 28, 2018 at 7:08
Explore related questions
See similar questions with these tags.