Arduino Fuel Consumption Tracker with YF-S201 Flow Sensor

Hi Arduino community,

I’m building a fuel consumption tracker using an Arduino Nano and a YF-S201 flow sensor to measure real-time fuel usage for a car project. It calculates liters per 100 km, displays it on a 16x2 LCD for eco-driving, and logs data to an SD card for trip analysis.

Here’s a basic sketch to read the flow sensor and show fuel usage:

// Fuel Consumption Tracker
#include <LiquidCrystal.h>
#define FLOW_SENSOR_PIN 2
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
volatile int flowPulses = 0;
float litersPerPulse = 0.0001; // YF-S201 calibration
unsigned long lastTime = 0;

void countPulses() {
  flowPulses++;
}

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(FLOW_SENSOR_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN), countPulses, RISING);
  lcd.print("Fuel Tracker");
}

void loop() {
  unsigned long currentTime = millis();
  if (currentTime - lastTime >= 1000) {
    float liters = flowPulses * litersPerPulse;
    float lPer100km = liters > 0 ? (liters * 1000) / 10 : 0; // Simplified
    lcd.setCursor(0, 1);
    lcd.print("L/100km: ");
    lcd.print(lPer100km);
    Serial.println(liters);
    flowPulses = 0;
    lastTime = currentTime;
  }
}

To calibrate the sensor, I’ve been using a fuel calculator at kalkulatorpaliwa.com.pl to cross-check readings against trip distances, which has been really helpful. A few questions:

  1. How do you filter noise in flow sensor readings? I’m getting occasional pulse spikes.

  2. Has anyone integrated a GPS module (like NEO-6M) for precise distance tracking?

  3. What’s the best SD card logging format for long-term data to avoid filling it?

I’d love feedback from anyone who’s worked on similar projects. Any ideas for adding a real-time eco-driving score display?

Thanks!

It depends on the sensor. Please post the datasheet.
What kind of noise are You talking about?

Yes.

Please define good, better, the best!

A single board micro computer was built 35 years ago and it was used during 10 years. It showed speed and fuel data.

This is not the way to read "flowPulses" when an interrupt is involved.

Automotive has one of the worst electrical environments. Here is some information that may help:
Valuable Resources for Automotive Electronics:

  1. STMicroelectronics Application Note AN2689:
    This application note provides guidelines on protecting automotive electronics from electrical hazards, focusing on design and component selection. Reading this will greatly enhance your understanding of automotive circuit protection.
    Read AN2689
  2. Analog Devices: Automotive Electronics Design:
    This article distills key insights into designing automotive electronics, offering practical advice for engineers.
    Read the article
  3. Diodes Incorporated: Transient Voltage Suppression in Automotive:
    Learn about techniques to protect automotive circuits from transient voltage, which is critical for ensuring reliable operation in harsh conditions.
    Read the article
  4. AEC-100 Standards Webinar:
    This webinar from Monolithic Power Systems provides a detailed overview of AEC standards, essential for understanding automotive electronics requirements.
    Watch the webinar
  5. Understanding Automotive Electronics, An Engineering Perspective by William B. Ribbens:
    This comprehensive book offers an in-depth look into automotive electronics from an engineering perspective, making it an invaluable resource.
    Access the book
  6. Check this for OBD ISO9141 Code Meaning & How To Fix

These resources should provide a start for a strong foundation for anyone involved in automotive electronics design. If you need further help or more resources, feel free to ask!

As @Railroader says, that is not a safe way to read the variable that's updated by the interrupt function.

Change it like this:

  if (currentTime - lastTime >= 1000) {
    int flowPulsesNow;
    noInterrupts();
    flowPulsesNow = flowPulses;
    flowPulses = 0;
    interrupts();
    float liters = flowPulsesNow * litersPerPulse;
    float lPer100km = liters > 0 ? (liters * 1000) / 10 : 0; // Simplified
    lcd.setCursor(0, 1);
    lcd.print("L/100km: ");
    lcd.print(lPer100km);
    Serial.println(liters);
    lastTime = currentTime;

Even if this does not appear to fix your problem, keep this change.

There are many types of Nano these days, with different designs and capabilities, so please be more precise.