/*
Flow Sensor Counter Meter FS300A G3/4
Flow rate : 1-60 L/min
Flow Pulse: 508 pulse / Liter
Description: This code interfaces with the FS300A flow sensor to measure flow rate and frequency.
It uses an external interrupt (CHANGE mode) on pin 2, counts edges, and calculates
frequency and flow rate based on actual elapsed time.
*/
#define FS300A_PULSE 508 // Number of pulses per liter
#define FS300A_FLOW_RATE 60 // Maximum flow rate in liters per minute (informational)
// Conversion factor: from frequency (Hz) to flow (L/min)
// NOTE: This is 60 / pulses_per_liter (do not use FS300A_FLOW_RATE here)
const float factor = 60.0f / (float)FS300A_PULSE;
#define interruptPin 2 // Interrupt pin for flow sensor (Arduino MEGA D2)
// ------------ State ------------
volatile uint32_t pulse = 0; // Edge counter updated in ISR (counts BOTH edges in CHANGE mode)
float frequency; // frequency in Hz
float flowRate; // flow in L/min
// ------------ Setup ------------
void setup() {
Serial.begin(115200); // Initialize serial communication
while (!Serial) { /* wait if native USB; MEGA continues immediately */ }
pinMode(interruptPin, INPUT_PULLUP); // FS300A is open-collector → use internal pull-up
attachInterrupt(digitalPinToInterrupt(interruptPin), FlowInterrupt, CHANGE); // Count both edges
Serial.println(F("FS300A flow monitor (pin D2, CHANGE mode)"));
Serial.println(F("Fields: Freq(Hz), Flow(L/min)"));
}
// ------------ Loop ------------
void loop() {
Frequency(); // compute once per sample window
}
// ------------ ISR ------------
void FlowInterrupt() {
// Keep ISR minimal: just increment the counter
pulse++;
}
// ------------ Frequency/Flow computation ------------
void Frequency() {
static unsigned long startMs = 0; // last computation time in ms
const unsigned long now = millis();
if (now - startMs < 1000UL) return; // run roughly once per second
const unsigned long elapsedMs = now - startMs;
startMs = now;
// Atomically snapshot and reset pulse count
noInterrupts();
uint32_t edges = pulse; // edges counted (both rising and falling)
pulse = 0;
interrupts();
// CHANGE mode counts both edges; actual pulses are edges / 2
const float pulses = (float)edges * 0.5f;
// Use actual elapsed time for accurate frequency
const float seconds = (float)elapsedMs * 0.001f;
frequency = (seconds > 0.0f) ? (pulses / seconds) : 0.0f;
// Flow rate in L/min
flowRate = frequency * factor;
PlotInfo();
}
// ------------ Printing ------------
void PlotInfo() {
// Avoid String concatenation to keep heap stable on AVR
Serial.print(F("Freq.: "));
Serial.print(frequency, 2);
Serial.print(F(" Hz, Flow: "));
Serial.print(flowRate, 3);
Serial.println(F(" L/min"));
}