Diy boat fuel consumption

this is what i have rn, i couldn't find a 1k resistor so i put a 1.5k and im getting no output with the pull down wired

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address and size (0x27 for a common 16x2 display)

volatile unsigned long pulseCountPin2 = 0;  // Initialize pulse count variable for pin 2 (P)
volatile unsigned long pulseCountPin3 = 0;  // Initialize pulse count variable for pin 3 (S)
unsigned long previousMillis = 0;      // Initialize previous time
unsigned long interval = 1000;         // Interval to calculate pulses per second
float microlitersPerPulse = 452.0;     // Microliters per pulse
float totalGallonsPin2 = 0.0;         // Total gallons flowed for pin 2 (P)
float totalGallonsPin3 = 0.0;         // Total gallons flowed for pin 3 (S)
float gallonsPerHourPin2 = 0.0;       // Flow rate in GPH for pin 2 (P)
float gallonsPerHourPin3 = 0.0;       // Flow rate in GPH for pin 3 (S)
float rollingAveragePin2[10] = {0};   // Array to store the last 10 flow rate values for pin 2 (P)
float rollingAveragePin3[10] = {0};   // Array to store the last 10 flow rate values for pin 3 (S)
int currentIndexPin2 = 0;             // Index to keep track of the current value for pin 2 (P)
int currentIndexPin3 = 0;             // Index to keep track of the current value for pin 3 (S)

void setup() {
  lcd.init();        // Initialize the LCD
  lcd.backlight();   // Turn on the backlight
  lcd.setCursor(0, 0);
  lcd.print("P GPH: 0.00");
  lcd.setCursor(0, 1);
  lcd.print("S GPH: 0.00");

  Serial.begin(9600);                  // Initialize serial communication
  attachInterrupt(digitalPinToInterrupt(2), countPulsePin2, RISING); // Attach an interrupt to pin 2 (P)
  attachInterrupt(digitalPinToInterrupt(3), countPulsePin3, RISING); // Attach an interrupt to pin 3 (S)
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // Calculate pulses per second for both pins
    float pulsesPerSecondPin2 = (float)pulseCountPin2 / (float)interval * 1000.0;
    float pulsesPerSecondPin3 = (float)pulseCountPin3 / (float)interval * 1000.0;

    // Calculate gallons per hour for both pins
    gallonsPerHourPin2 = (pulsesPerSecondPin2 * microlitersPerPulse * 0.000264172052) * 3600.0;
    gallonsPerHourPin3 = (pulsesPerSecondPin3 * microlitersPerPulse * 0.000264172052) * 3600.0;

    // Update the rolling average arrays for both pins
    rollingAveragePin2[currentIndexPin2] = gallonsPerHourPin2;
    rollingAveragePin3[currentIndexPin3] = gallonsPerHourPin3;

    // Calculate the rolling averages for both pins
    float sumPin2 = 0.0;
    float sumPin3 = 0.0;
    for (int i = 0; i < 10; i++) {
      sumPin2 += rollingAveragePin2[i];
      sumPin3 += rollingAveragePin3[i];
    }
    float averageGPHPin2 = sumPin2 / 10.0;
    float averageGPHPin3 = sumPin3 / 10.0;

    // Update the total gallons for both pins
    totalGallonsPin2 += (gallonsPerHourPin2 / 3600.0);
    totalGallonsPin3 += (gallonsPerHourPin3 / 3600.0);

    // Display on the LCD
    lcd.setCursor(0, 0);
    lcd.print("P GPH:    "); // Clear the previous value
    lcd.setCursor(7, 0);
    lcd.print(averageGPHPin2, 2); // Display with 2 decimal places

    lcd.setCursor(0, 1);
    lcd.print("S GPH:    "); // Clear the previous value
    lcd.setCursor(7, 1);
    lcd.print(averageGPHPin3, 2); // Display with 2 decimal places

    // Reset pulse counts and update the previous time
   noInterrupts();
   pulseCountPin2 = 0;
   pulseCountPin3 = 0;
   interrupts();
    previousMillis = currentMillis;

    // Update the current indices for the rolling average arrays
    currentIndexPin2 = (currentIndexPin2 + 1) % 10;
    currentIndexPin3 = (currentIndexPin3 + 1) % 10;
  }
}

void countPulsePin2() {
  // This function is called whenever a pulse is detected on pin 2 (P)
  pulseCountPin2++;
}

void countPulsePin3() {
  // This function is called whenever a pulse is detected on pin 3 (S)
  pulseCountPin3++;
}

That's because you are bringing the signal straight to ground with that green wire. Wire it like the image here.

Screenshot 2023-11-12 at 7.13.44 PM

(I can't draw for sh!t lol.)

1 Like

like this? because the numbers are still way off
also remembered i can turn off the back light

ok, good, now you just need to fix the flow rate calculation.

assuming the code is right it should be calibrated, these flow sensors came out of a dialysis machine so i would imagine the sticker on the back is right

If you still have the 10k resistor, try putting that on and see if the values change.

ok so the data sheet says 0.46mL/P already have the number of pulses in one second which is countPulsePin2 and 3.

So the calculation should now be pulseCountPin2 * microlitersPerPulse * 0.000264172052 * 3600

10k and they didnt change and the numbers are on the back
i just split the difference at 454 ul

Hi,
Are you sucking or blowing through the sensor?

Tom.. :grinning: :+1: :coffee: :australia:

this current setup is pushing but the boat will be pulling

Try changing the calculation and see if that maybe gets closer to what you are expecting.

pulseCountPin2 * microlitersPerPulse * 0.000264172052 * 3600

Fine, but be warned, pulling can produce cavitation, and that can effect readings.
You have got all the air out of the system?

Are you also measuring flow by measuring the actual volume of water pumped, not machine calculated?
Eg, stopwatch and measuring cylinder.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

im not too worried about air in the system because it will be filled 24/7 and i have not sanity checked with a timed measure yet but i will after i eat dinner

After some fine-tuning and testing, I got it all working. I know P and S GPH are off, but they fluctuate a bit, and I'm fine with that.

I ordered an Arduino Nano and a proto board. I'm going to make an enclosure and test it on an old truck I have. I'll make sure the sensor is gas-rated 1000% before I put it in the boat.

If anyone sees anything wrong, let me know; I'm still kind of winging it.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

volatile unsigned long pulseCountPin2 = 0;
volatile unsigned long pulseCountPin3 = 0;
unsigned long previousMillis = 0;
unsigned long lcdUpdateMillis = 0;
unsigned long interval = 1000; // Update every 1000 milliseconds
float millilitersPerPulseP = 0.5; // Port side sensor (pin 2)
float millilitersPerPulseS = 0.485; // Starboard side sensor (pin 3)
float totalGallonsPin2 = 0.0;
float totalGallonsPin3 = 0.0;
float gallonsPerHourPin2 = 0.0;
float gallonsPerHourPin3 = 0.0;
float rollingAveragePin2[10] = {0};
float rollingAveragePin3[10] = {0};
int currentIndexPin2 = 0;
int currentIndexPin3 = 0;

// Constants
const int LCD_UPDATE_INTERVAL = 200;
const int ROLLING_AVERAGE_SIZE = 10;
const int REMAINING_GALLONS_THRESHOLD = 120;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("P GPH:       ");
  lcd.setCursor(0, 1);
  lcd.print("S GPH:       ");
  lcd.setCursor(0, 2);
  lcd.print("Total P:     ");
  lcd.setCursor(0, 3);
  lcd.print("Total S:     ");

  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), countPulsePin2, RISING);
  attachInterrupt(digitalPinToInterrupt(3), countPulsePin3, RISING);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    float pulsesPerSecondPin2 = (float)pulseCountPin2 / (float)interval * 1000.0;
    float pulsesPerSecondPin3 = (float)pulseCountPin3 / (float)interval * 1000.0;

    gallonsPerHourPin2 = (pulsesPerSecondPin2 * millilitersPerPulseP * 0.000264172052) * 3600.0;
    gallonsPerHourPin3 = (pulsesPerSecondPin3 * millilitersPerPulseS * 0.000264172052) * 3600.0;

    rollingAveragePin2[currentIndexPin2] = gallonsPerHourPin2;
    rollingAveragePin3[currentIndexPin3] = gallonsPerHourPin3;

    float sumPin2 = 0.0;
    float sumPin3 = 0.0;
    for (int i = 0; i < ROLLING_AVERAGE_SIZE; i++) {
      sumPin2 += rollingAveragePin2[i];
      sumPin3 += rollingAveragePin3[i];
    }
    float averageGPHPin2 = sumPin2 / ROLLING_AVERAGE_SIZE;
    float averageGPHPin3 = sumPin3 / ROLLING_AVERAGE_SIZE;

    totalGallonsPin2 += (gallonsPerHourPin2 / 3600.0);
    totalGallonsPin3 += (gallonsPerHourPin3 / 3600.0);

    // Only update LCD if a certain time has passed since the last update
    if (currentMillis - lcdUpdateMillis >= LCD_UPDATE_INTERVAL) {
      // "P GPH" and "S GPH" values are not updated
      lcd.setCursor(7, 0);
      lcd.print(String(averageGPHPin2, 2));

      lcd.setCursor(7, 1);
      lcd.print(String(averageGPHPin3, 2));

      lcd.setCursor(0, 2);
      lcd.print("TB: " + String(totalGallonsPin2 + totalGallonsPin3));

      lcd.setCursor(0, 3);
      lcd.print("Rem: " + String(REMAINING_GALLONS_THRESHOLD - (totalGallonsPin2 + totalGallonsPin3)));

      lcdUpdateMillis = currentMillis;
    }

    pulseCountPin2 = 0;
    pulseCountPin3 = 0;
    previousMillis = currentMillis;

    currentIndexPin2 = (currentIndexPin2 + 1) % ROLLING_AVERAGE_SIZE;
    currentIndexPin3 = (currentIndexPin3 + 1) % ROLLING_AVERAGE_SIZE;
  }
}

void countPulsePin2() {
  pulseCountPin2++;
}

void countPulsePin3() {
  pulseCountPin3++;
}

void updateLCD(int col, int row, float value) {
  lcd.setCursor(col, row);
  lcd.print(String(value, 2));
}

void updateLCD(int col, int row, String value) {
  lcd.setCursor(col, row);
  lcd.print("                    "); // Clear previous value
  lcd.setCursor(col, row);
  lcd.print(value);
}


more testing and tweaking and now im waiting on that proto board, the only problem i have is if the GPH's go under 10 they have a small floating point error or something but not too big of a deal

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Constants
const int ROLLING_AVERAGE_SIZE = 60; // Size of the rolling average arrays (seconds to average gph)

LiquidCrystal_I2C lcd(0x27, 20, 4);

volatile unsigned long pulseCountPin2 = 0;
volatile unsigned long pulseCountPin3 = 0;
unsigned long previousMillis = 0;
unsigned long lcdUpdateMillis = 0;
unsigned long interval = 1000; // Update every 1000 milliseconds
float millilitersPerPulseP = 0.5; // Port side sensor (pin 2) ml per pulse
float millilitersPerPulseS = 0.49; // Starboard side sensor (pin 3) ml per pulse
float totalGallonsPin2 = 0.0;
float totalGallonsPin3 = 0.0;
float gallonsPerHourPin2 = 0.0;
float gallonsPerHourPin3 = 0.0;
float rollingAveragePin2[ROLLING_AVERAGE_SIZE] = {0}; // Use the constant here
float rollingAveragePin3[ROLLING_AVERAGE_SIZE] = {0}; // Use the constant here
int currentIndexPin2 = 0;
int currentIndexPin3 = 0;



void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("P GPH:       "); // print port side gph
  lcd.setCursor(0, 1);
  lcd.print("S GPH:       "); // print starboard side gph
  lcd.setCursor(0, 2);
  lcd.print("T GPH:     "); // print combined gph
  lcd.setCursor(0, 3);
  lcd.print("Total:     "); // print total burned

  attachInterrupt(digitalPinToInterrupt(2), countPulsePin2, RISING);
  attachInterrupt(digitalPinToInterrupt(3), countPulsePin3, RISING);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    float pulsesPerSecondPin2 = (float)pulseCountPin2 / (float)interval * 1000.0;
    float pulsesPerSecondPin3 = (float)pulseCountPin3 / (float)interval * 1000.0;

    gallonsPerHourPin2 = (pulsesPerSecondPin2 * millilitersPerPulseP * 0.000264172052) * 3600.0;
    gallonsPerHourPin3 = (pulsesPerSecondPin3 * millilitersPerPulseS * 0.000264172052) * 3600.0;

    rollingAveragePin2[currentIndexPin2] = gallonsPerHourPin2;
    rollingAveragePin3[currentIndexPin3] = gallonsPerHourPin3;

    float sumPin2 = 0.0;
    float sumPin3 = 0.0;
    for (int i = 0; i < ROLLING_AVERAGE_SIZE; i++) {
      sumPin2 += rollingAveragePin2[i];
      sumPin3 += rollingAveragePin3[i];
    }
    float averageGPHPin2 = sumPin2 / ROLLING_AVERAGE_SIZE;
    float averageGPHPin3 = sumPin3 / ROLLING_AVERAGE_SIZE;

    totalGallonsPin2 += (gallonsPerHourPin2 / 3600.0);
    totalGallonsPin3 += (gallonsPerHourPin3 / 3600.0);

    // Only update LCD if a certain time has passed since the last update
    if (currentMillis - lcdUpdateMillis >= 1000) {
      lcd.setCursor(7, 0);
      lcd.print(String(round(averageGPHPin2 * 100.0) / 100.0, 2));
      lcd.setCursor(7, 1);
      lcd.print(String(round(averageGPHPin3 * 100.0) / 100.0, 2));
      lcd.setCursor(0, 2);
      lcd.print("T GPH: " + String(round((averageGPHPin2 + averageGPHPin3) * 100.0) / 100.0, 2));
      lcd.setCursor(0, 3);
      lcd.print("Total: " + String(totalGallonsPin2 + totalGallonsPin3));

      lcdUpdateMillis = currentMillis;
    }

    pulseCountPin2 = 0;
    pulseCountPin3 = 0;
    previousMillis = currentMillis;

    currentIndexPin2 = (currentIndexPin2 + 1) % ROLLING_AVERAGE_SIZE;
    currentIndexPin3 = (currentIndexPin3 + 1) % ROLLING_AVERAGE_SIZE;
  }
}

void countPulsePin2() {
  pulseCountPin2++;
}

void countPulsePin3() {
  pulseCountPin3++;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.