Hello all,
I'm quite a newbie to Arduino and electronics, but have some background in coding. I'm building a automatic water pump to circulate liquid with a flow sensor and automatic cutoff when the liquid flow stops for 5 seconds (e.g. clogging etc). This topic seems to be quite popular, however I didn't find any answer to the problem I'm encountering.
I have an Arduino Uno that gets flow measurement from this Hall effect sensor:
"Ccylez YF-S401 DC5-24V Water Flow Sensor" (https://www.amazon.de/-/en/gp/product/B08D3NZSS5/ref=ppx_yo_dt_b_asin_title_o03_s03?ie=UTF8&psc=1)
It displays the flow rate on an LCD display. I also have a 6-12V pump controlled by the Arduino via a L293D chip: "Elecrow DIY61289P - 6-12V R385 DC Diaphragm Pumps"
There is a potentiometer that defines the voltage supplied to the pump by the L293D.
There is also a simple LED and reset/restart button that can be used to restart the flow sensor and motor.
My setup seems to work perfectly when powered via the Arduino USB (5V):
-Flow sensor reads values via the interrupt pin 2,
-potentiometer defines the speed of the pump, (except of course only up to 5V speed),
-screen displays everything correctly and
-if the flow stops for 5sec, the motor is cut off until the restart button is pressed.
BUT:
If I try to power the Arduino with an external 12V DC supply in order to get the full speed range for the pump, the flow sensor starts showing quite high and random ghost readings for flow. In this case I'm supplying the 12V from the Vin on the Arduino into the L293D that should pass it on as regulated by the potentiometer.
I mean there is no actual flow through the sensor but it claims to have some. This occurs if the voltage going to the motor defined with the potentiometer rises above approx 5V.
I'm completely lost here, but I'm quite sure it's not a code issue because everything works beautifully with the 5V input. I'm guessing it's electronics or wiring or something such.
Thank you for all ideas already in advance! ![]()
Here is my code:
[code]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27, 20, 4);
//define sensor
const int sensorInterrupt = 0; // interrupt 0
const int sensorPin = 2; //Digital Pin 2
const int alarmPin = 13; // Digital Pin 13 for alarming the user
unsigned int SetPoint = 400; //400 milileter
//define control data
int adcValue; // Define a variable to save the ADC value
int targetValue; // target value for output
int noFlowCount = 0; // time in seconds without flow
boolean noFlow = false;
//define the restarting button
const int resetButtonPin = 4; // the number of the pushbutton pin
int buttonState; // variable for reading the pushbutton status
//define motor (pump) control with L293D
int in1Pin = 10; // Define L293D channel 1 pin
int in2Pin = 9; // Define L293D channel 2 pin
int enable1Pin = 11; // Define L293D enable 1 pin
int motorSpd; // Define a variable to save the motor rotation speed
int motorV = 0; //Define a variable to announce the voltage going to the motor
/*The hall-effect flow sensor outputs pulses per second per litre/minute of flow.*/
float calibrationFactor = 90; //You can change according to your datasheet
volatile byte pulseCount = 0;
float flowRate = 0.0;
unsigned int flowMilliLitres = 0;
unsigned long totalMilliLitres = 0;
unsigned long oldTime = 0;
void setup()
{
// Initialize a serial connection for reporting values to the host
Serial.begin(9600);
//initialize motor control pins
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
pinMode(enable1Pin, OUTPUT);
pinMode(alarmPin, OUTPUT);
digitalWrite(alarmPin, LOW); //shut the alarm led
// initialize the pushbutton pin as an input:
pinMode(resetButtonPin, INPUT);
//initialize flow sensor
pinMode(sensorPin, INPUT_PULLUP); //TRYING THE PULLUP VERSION!!!!!
digitalWrite(sensorPin, HIGH);
// analogWrite(motorPin, targetValue);
/*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); //you can use Rising or Falling
// initialize the lcd-screen
lcd.init();
lcd.backlight(); // Turn on backlight
lcd.print("Julius"); // Print a message to the LCD
lcd.setCursor(0, 3); // set the cursor to column 0, line 1
lcd.print("Flow pump 1.1"); // Print a message to the LCD
delay(2000);
lcd.clear();
}
void loop()
{
// read the state of the resetbutton value:
buttonState = digitalRead(resetButtonPin);
//Serial.print("Button state: ");
//Serial.println(buttonState);
if (buttonState == LOW) { // check if the pushbutton is pressed. If it is, the buttonState is LOW, by default the buttonState is HIGH:
// turn LED off:
digitalWrite(alarmPin, LOW);
noFlowCount = 0;
noFlow = 0;
}
//detect potentiometer, so desired speed for motor
targetValue = analogRead(A0);
motorSpd = map(targetValue, 0, 1023, 0, 255);
motorV = map(targetValue, 0, 1023, 0, 13);
if (noFlowCount > 5) // test if there is liquid for pumping and light the alarm led
{
noFlow = true;
//analogWrite(enable1Pin, 0);
digitalWrite(alarmPin, HIGH);
//shut down the motor
motorSpd = 0;
motorV = 0;
// for debugging purposes
// Print the time that the pump has been withouth fluid
Serial.print("Out of liquid!\t");
Serial.print("No flow time: ");
Serial.print(noFlowCount);
Serial.println(" sec");
}
// LCD Print the voltage of the motor, after calibration will be changed to the desired flow rate.
lcd.setCursor(0, 3); // set the cursor to column 0, line 1
lcd.print("Motor V: ");
lcd.print(motorV);
// drive motor
digitalWrite(in1Pin, LOW);
digitalWrite(in2Pin, HIGH);
analogWrite(enable1Pin, motorSpd); //transfer the correct voltage to the motor
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);
// 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
totalMilliLitres += flowMilliLitres;
unsigned int frac;
if (flowMilliLitres == 0)
{
noFlowCount++;
}
else {
noFlowCount = 0;
}
// Print debugging information on the serial monitor.
// Print the flow rate for this second in litres / minute
Serial.print("Flow rate: ");
Serial.print(flowMilliLitres, DEC); // Print the integer part of the variable
Serial.print("mL/Second");
Serial.print("\t");
// Print the cumulative total of litres flowed since starting
Serial.print("Output Liquid Quantity: ");
Serial.print(totalMilliLitres, DEC);
Serial.print("mL");
Serial.print("\t");
// Print the voltage going to the motor
Serial.print("Motor V: ");
Serial.print(motorV); // Print the integer part of the variable
Serial.print("\t");
// Print the time without flow
Serial.print("No flow: ");
Serial.print(noFlowCount);
Serial.println(" sec");
// Display the relevant flow and motor speed information on the LCD screen.
// LCD Print the flow rate for this second in litres / minute
if (noFlow) {
//alert the user
lcd.clear();
lcd.print("Julius Flowpump 1.1"); // Print a message to the LCD
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("Out of Liquid! ");
lcd.print(noFlowCount);
lcd.print(" s");
} else {
lcd.clear();
lcd.print("Julius Flowpump 1.1"); // Print a message to the LCD
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("Flow: ");
lcd.print(flowMilliLitres, DEC); // Print the integer part of the variable
lcd.print(" mL/s");
lcd.setCursor(0, 2); // set the cursor to column 0, line 1
lcd.print("Total flow: ");
lcd.print(totalMilliLitres, DEC); // Print the integer part of the variable
lcd.print(" mL/s");
}
// 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);
}
}
//Interrupt Service Routine
void pulseCounter()
{
// Increment the pulse counter
pulseCount++;
}
[/code]
Here is my schematic: Sorry I'm not a pro, but tried to get everything there as it is on my breadboard. (Pls don't mind the LCD not connected to it's serial controller there, that is not the issue.)

