#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;
int press_pin =A1;
//flowmeter parameters
int flowPin = 2; // input pin on arduino D2
double flowRate; // value intented to calculate
double flowR; // flow value in lt
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;
void setup() {
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) {
count = 0; // reset counter so it could start counting from 0
interrupts(); // enables interrupts on arduino nano
delay(1000); // wait 1000 msec
noInterrupts(); // disable interrupts on arduino nano
//calculation for flowmeter
flowR = (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;
// 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");
lcd.setCursor(0,2);
lcd.print("Flow: ");
lcd.setCursor(8,2);
lcd.print(flowRate);
lcd.print("lt/min");
lcd.setCursor(0,3);
lcd.print("Total: ");
lcd.setCursor(8,2);
lcd.print(totalFlow/1000);
lcd.print("lt");
}
void Flow(void)
{
count++; // every time this function is called, increment "count" by 1
}
void loop() {
pressure_cal();
pump_control();
flow_control();
lcd_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.println (sensorVoltage);
Serial.println(bar);
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(2);
}
I try to write code including flow sensor, pressure sensor and pump. I wrote the code. But When I use interrupt , code stop. I used functions in " void loop()" . I moved the interrupt code ( flow_control) between void setup and void loop. But I can see outputs in serial monitor but I cannot see on lcd. Could you help me fix the problem ?
1 Answer 1
A lot of peripheral libraries requires interrupts to be enabled, especially when they use timing or the I2C/SPI pins. Instead of disabling interrupts for the majority of the sketch, what you want to do is isolate disabling the interrupts to just reading and resetting the count variable:
noInterrupts(); // disable interrupts on arduino nano
local_count = count;
count=0;
interrupts(); // enables interrupts on arduino nano
Also all that processing takes some time which will skew the timing so it's better to use timestamp and millis:
unsigned long previous_read;
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;
//process flowrate based on local_count
}
-
Should I replacey count*8.93 by local_count*8.93 ? When I do, Arduino says local_count was not declared in this scope? What should I do ? flowR = (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/minutessapphire– sapphire2018年08月12日 10:03:28 +00:00Commented Aug 12, 2018 at 10:03
-
that calculation should be inside the if (where the comment is), you only need to run it when processing the new count.ratchet freak– ratchet freak2018年08月12日 12:51:09 +00:00Commented Aug 12, 2018 at 12:51
-
Thank you so much ratchet. I want to add a button to reset only total flow on lcd void flow_control(void) { if(digitalRead(resetButtonA) == LOW) { totalMilliLitresA = 0; lcd.setCursor(0, 1); lcd.print("0L"); }sapphire– sapphire2018年08月13日 07:30:49 +00:00Commented Aug 13, 2018 at 7:30
-
Thank you so much. I want to add a reset button to reset only total flow on lcd. Is this code true inside void flow(void) ? void flow_control(void) { if(digitalRead(resetButton) == LOW) { totalFlow = 0; lcd.setCursor(0, 3); lcd.print("0L"); }sapphire– sapphire2018年08月13日 07:32:39 +00:00Commented Aug 13, 2018 at 7:32
Explore related questions
See similar questions with these tags.
lcd_control()
? You forgot to include that function.