/*
YF‐ S201 Water Flow Sensor
Water Flow Sensor output processed to read in litres/min and total volume in litres
*/
volatile int flow_frequency; // Measures flow sensor pulses
unsigned long totalPulses = 0; // Total accumulated pulses for volume calculation
float pulsesPerLiter = 4600; // Replace with the correct value for your sensor
float vol = 0.0, l_minute;
unsigned char flowsensor = 3; // Sensor Input
int resetButtonPin = 6; // Reset button pin
int voltagePin = A7; // Pin for voltage measurement
int potPin = A1; // Pin where the potentiometer is connected
// Motor control pins
int motorPin1 = 10; // Pin D7 for motor direction 1
int motorPin2 = 9; // Pin D9 for motor direction 2
int fillButtonPin = 5; // FILL button pin
int drainButtonPin = 4; // DRAIN button pin
// PWM speed control (0-255, where 255 is full speed)
int motorSpeed = 120; // Set desired motor speed (can be changed)
float voltage = 0.0; // Variable to store the measured voltage
unsigned long currentTime;
unsigned long cloopTime;
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EasyButton.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
EasyButton btn_fill(fillButtonPin);
EasyButton btn_stop(resetButtonPin);
EasyButton btn_drain(drainButtonPin);
void flow() // Interrupt function
{
flow_frequency++; // Increment the pulse count
}
// Function to measure voltage on A7
float measureVoltage()
{
int sensorValue = analogRead(voltagePin); // Read the analog pin A7
float measuredVoltage = sensorValue * (5.0 / 1033.0); // Scale to actual voltage (assuming a 5V reference)
measuredVoltage *= 3.44; // Adjust based on the resistor divider ratio (19.8k and 8.1k)
return measuredVoltage;
}
enum States {
STOP,
FILL,
DRAIN
};
States pump_states;
void on_btn_fill()
{
pump_states = States::FILL;
}
void on_btn_stop()
{
pump_states = States::STOP;
}
void on_btn_drain()
{
pump_states = States::DRAIN;
}
void reset_display()
{
vol = 0.0; // Reset volume to 0
totalPulses = 0; // Reset pulse count to 0
display.clearDisplay();
display.setTextSize(3);
display.setCursor(14, 20);
display.println(F("Reset!"));
display.display();
delay(1500); // Short pause to prevent multiple button reads
}
void setup() {
pinMode(flowsensor, INPUT);
digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up
// Motor control pin setup
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
btn_fill.begin();
btn_stop.begin();
btn_drain.begin();
btn_fill.onPressed(on_btn_fill);
btn_stop.onPressed(on_btn_stop);
btn_drain.onPressed(on_btn_drain);
btn_drain.onPressedFor(1000, reset_display);
pump_states = States::STOP;
//pinMode(resetButtonPin, INPUT_PULLUP); // Setup reset button as INPUT_PULLUP
//pinMode(fillButtonPin, INPUT_PULLUP); // Setup FILL button as INPUT_PULLUP
//pinMode(drainButtonPin, INPUT_PULLUP); // Setup DRAIN button as INPUT_PULLUP
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(flowsensor), flow, RISING); // Setup Interrupt for flow sensor
// Initialize the display
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Stop if there's an error
}
// Initial display message
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(12, 10);
display.println(F("Smart Fuel Station"));
display.setCursor(32, 25);
display.println(F("loading ..."));
display.setCursor(6, 50);
display.println(F("Dr.Tom"));
display.display();
delay(4000);
display.clearDisplay();
currentTime = millis();
cloopTime = currentTime;
}
void loop() {
btn_fill.read();
btn_drain.read();
btn_stop.read();
currentTime = millis();
// Measure voltage on A7
voltage = measureVoltage();
int potValue = analogRead(potPin);
motorSpeed = map(potValue, 0, 1023, 60, 255); // Adjust motorSpeed based on potentiometer
switch(pump_states)
{
case States::STOP:
// do stop
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 0);
break;
case States::FILL:
// do fill
analogWrite(motorPin1, 0);
analogWrite(motorPin2, motorSpeed);
break;
case States::DRAIN:
// do draib
analogWrite(motorPin2, 0);
analogWrite(motorPin1, motorSpeed);
break;
}
// Calculate and display flow rate and total volume every second
if(currentTime >= (cloopTime + 1000)) {
cloopTime = currentTime; // Update cloopTime
if(flow_frequency != 0) {
// Flow rate in L/min = (pulses per second / pulsesPerLiter) * 60
l_minute = ((float)flow_frequency / pulsesPerLiter) * 60.0;
// Add the pulses to the total count
totalPulses += flow_frequency;
// Calculate total volume in liters
vol = (float)totalPulses / pulsesPerLiter;
// Reset flow frequency for the next second
flow_frequency = 0;
// Display results
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setTextSize(4);
display.setCursor(0, 0);
display.print(vol);
display.println(F("L"));
display.setCursor(10, 40);
display.setTextSize(2);
display.print(l_minute, 2);
display.println(F("L/min"));
display.display();
display.clearDisplay();
} else {
// If no flow detected, check if the battery voltage is below 6V
if (voltage < 6.5) {
display.clearDisplay();
display.setTextSize(2);
display.setCursor(45, 5);
display.println(F("Low"));
display.setCursor(20, 30);
display.println(F("Battery!"));
display.display();
display.setTextSize(1);
display.setCursor(20, 55);
display.print(F("Fuel "));
display.print(vol);
display.println(F("L"));
display.display();
display.clearDisplay();
} else {
// If no flow detected and voltage is above 6V, show total volume and voltage
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setTextSize(4);
display.setCursor(0, 0);
display.print(vol);
display.println(F("L"));
display.setTextSize(2);
display.setCursor(0, 40);
display.print(F("Bat:"));
display.print(voltage, 1);
display.println(F(" V")); // Display the voltage
display.display();
display.clearDisplay();
}
}
}
}