Pump speed using Flow meter

Hi folks.

I hope I get the format correct, 1st time using the forum and I'm following the guide as best as possible.
I've a college project where I'm trying to control the speed of an inlet pump by the flow rate of the outlet pump. Outlet pump is controlled with a pot. each 24v pump is controlled via Mosfet PWM drivers capable of 30v. Outlet pump is 750L/hr and inlet pump is 1100L/hr. Flow meters are 0 - 60L/min calibration factor 7.8, pulse per litre 468. The issue I have is the inlet pump speed won't vary regardless of what speed the outlet pump is running at. In the code you'll notice some of the mapping figures are different than expected, I've been changing things looking for answers.

Thanks in advance,
Jay


```cpp
#include <LiquidCrystal.h>


//// Pin definitions ////

  LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

//Inputs
  int outletFlowMeter = 2;   //This is an interupt input pin on the Arduino
  volatile float outflowRate;    //This is the value we intend to calculate.
  volatile long outletFlowcount; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.
 
  int inletFlowMeter = 3;    //This is an interupt input pin on the Arduino
  volatile float inflowRate;    
  volatile long inletFlowcount;

  unsigned long lastTime;     // Using internal timing for flow calculations

  const float calibrationFactor = 7.8;   // Calibration factor for the flow meters
  const float pulsesPerLiter = 468.0;    // Number of pulses per liter

  int outPumpLevelControl = 7;   //Outlet low level and Inlet high level limit switches wired in series.
  int inPumpLevelControl = 4;    //Inlet low level and Outlet high level limit switches wired in series.
  int outletPot = A1;    //Speed control for outlet pump.
  int temperatureSensor = A2;    //Inlet water temp.

//Outputs
  int outletPump = 5;     //PWM pump speed control
  int inletPump = 6;      //PWM pump speed control


void setup() 
{
  Serial.begin(9600);   //Start serial monitor
  lcd.begin(16, 4);     //Start LCD display

  pinMode(outletFlowMeter, INPUT);
  pinMode(inletFlowMeter, INPUT);
  pinMode(outPumpLevelControl, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(inPumpLevelControl, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(outletPot, INPUT);
  pinMode(temperatureSensor, INPUT);
  pinMode(inletPump, OUTPUT);
  pinMode(outletPump, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(outletFlowMeter), outletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge
  attachInterrupt(digitalPinToInterrupt(inletFlowMeter), inletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge


  //////System Check//////

  // Purge pumps//
  
      analogWrite(outletPump, 10);
      analogWrite(inletPump, 10);

        lcd.clear();
        lcd.setCursor(1, 1);
        lcd.print("Out Pump Purge");
        lcd.setCursor(1, 2);
        lcd.print("In Pump Purge");
  
          delay(5000);

            analogWrite(outletPump, 0);
            analogWrite(inletPump, 0);
  


              lcd.clear();
              lcd.setCursor(1, 1);
              lcd.print("System Ready");
              delay(5000);
              lcd.clear();

}

void loop() 
{

////// Outlet Pump //////

  int pot = analogRead(outletPot); //read potentiometer (0-1023)
  int outSpeed = map(pot, 0, 1023, 0, 127.5);  // convert to 0-255
  int outpercentage = map(outSpeed, 0, 127.5, 0, 100);      // PWM vaue mapped to %
    
    digitalRead(outPumpLevelControl);
    if(outPumpLevelControl, HIGH)
    {
      analogRead(outletPot);
      analogWrite(outletPump, outSpeed);
    }
        lcd.setCursor(0,0);
        lcd.print("Out Speed   ");
        lcd.print(outpercentage);
        lcd.print("%");


        lcd.setCursor(0,1);
        lcd.print("Out   ");
        lcd.print(outflowRate);
        lcd.print(" L/min"); 
    

////// Outlet Pump Alarm//////

    if(outPumpLevelControl, LOW)
    {
      analogWrite(outletPump, 0);
  
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.scrollDisplayLeft();
        lcd.print("Outlet Pump Alarm - Check Water Levels");
    }

//////Flow calculations//////
outletFlowcount = 0;
inletFlowcount = 0;

interrupts();
delay(2000);

  outflowRate = 2.1368 * outletFlowcount / 1000 * 30; //2.1368 is amount of flow in ml/pulse//
  inflowRate = 2.1368 * inletFlowcount / 1000 * 30;
    
noInterrupts();

          Serial.print("Outlet Flow ");
          Serial.print(outflowRate);
          Serial.println(" L/min");

          Serial.print("Inlet Flow ");
          Serial.print(inflowRate);
          Serial.println(" L/min");

//////Inlet Pump//////

  int inpercentage = map(inflowRate, 0, 13.5, 0, 100);      // 13.5 L/min is maximum output of Inlet Pump
  int inSpeed = map(outletFlowcount, 0, 4212, 0, 255);      // 4212 is the amount of pulses for 9L/min,,,,,,maximum flow of outlet pump 

    digitalRead(inPumpLevelControl);
    if(inPumpLevelControl, HIGH)
    { 
      analogRead(inSpeed);
      analogWrite(inletPump, inSpeed);
    }
    
        lcd.setCursor(0,2);
        lcd.print("In Speed    ");
        lcd.print(inpercentage);
        lcd.print("%");


        lcd.setCursor(0,3);
        lcd.print("In    ");
        lcd.print(inflowRate);
        lcd.print(" L/min");
    

// Inlet Pump Alarms

    if(inPumpLevelControl, LOW) 
    {
      analogWrite(inletPump, 0);
  
        lcd.clear();
        lcd.setCursor(0,3);
        lcd.scrollDisplayLeft();
        lcd.print("Inlet Pump Alarm - Check Water Levels");
    } 
}

//////Functions//////

void outletFlowPulseIncrement() 
{
  outletFlowcount++;
}
void inletFlowPulseIncrement() 
{
  inletFlowcount++;
}

map only deals with integers, not floating point numbers

What do you expect those statements to do? You are reading the pin and then throwing away the results. Your if() statement will alway be true.

It appears you need to learn a bit of C/C++ just like we all did.

Maybe play around with all the examples that come with the IDE...

Always show us a good schematic of your proposed circuit.
Show us good images of your ‘actual’ wiring.
Give links to components.

  • Avoid using delay( ) as it blocks code execution.

If the switches are wired in series, why do you have 2 inputs?
Post a wiring diagram.

Please tell us you can VARY the speed of the input pump. So the problem is only computing the correct speed value.

yes, I can vary the speed of the outlet pump with the potentiometer

A set for each of the 2 pumps

If either of the limit switches are open how would it be true?

And yes I do need to learn more about C++ but I've never done any coding until January, its a college project and time to learn is my enemy. With all due respect I wouldn't be on here if I had the answers.

I was running it without the delay but the flow rate display on the LCD was unreadable because it was changing constantly

  • Inputs D4 and D7 are not wired properly.

  • Update the schematic showing how the motors are actually wired.
    As you show, a GPIO cannot be connected to a motor.

If the flow rate is constantly changing, either your calculation of the rate is flawed or there is something wrong with your circuitry. Is the flow rate constant with no flow?

Two pumps in series will never work unless the first supplies vastly more than the requirement of the second.
If insufficient, all you will end up with is cavitation on the second.
This can be avoided by the use of a sufficiently sized "ballast tank".

Fluid dynamics is a wonderfully complex subject made more so because fluid has density and is hard to get moving and equally hard to stop moving.

Hi Larry,
Sorry, the schematic doesn't show the PWM controlled relays, I used Fritzing and its limited with available components. Pins 5 and 6 are connected to the PWM terminal of each of the 2 relays, pumps are wired through the load side from a 24v power supply. I have the 2 pumps running now, outlet pump speed controlled by the pot and the inlet pump speed varies according to the outlet speed.

#include <LiquidCrystal.h>


//// Pin definitions ////

  LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

//Inputs
   
  int outletFlowMeter = 2;   //This is an interupt input pin on the Arduino
  int outflowRate;    //This is the value we intend to calculate.
  volatile long outletFlowcount; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.
 
  int inletFlowMeter = 3;    //This is an interupt input pin on the Arduino
  int inflowRate;    
  volatile long inletFlowcount;

  unsigned long lastTime;     // Using internal timing for flow calculations

  const float calibrationFactor = 7.8;   // Calibration factor for the flow meters
  const float pulsesPerLiter = 468.0;    // Number of pulses per liter

  int outPumpLevelControl = 7;   //Outlet low level and Inlet high level limit switches wired in series.
  int inPumpLevelControl = 4;    //Inlet low level and Outlet high level limit switches wired in series.
  int outletPot = A1;    //Speed control for outlet pump.
  int temperatureSensor = A2;    //Inlet water temp.

  int outlimitValue;
  int inlimitValue;

//Outputs
  int outletPump = 5;     //PWM pump speed control
  int inletPump = 6;      //PWM pump speed control

  // Set initial speeds for both pumps
  int outSpeed = 0;
  int inSpeed = 0;

void setup() 
{
  Serial.begin(9600);   //Start serial monitor
  lcd.begin(16, 4);     //Start LCD display

  pinMode(outletFlowMeter, INPUT);
  pinMode(inletFlowMeter, INPUT);
  pinMode(outPumpLevelControl, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(inPumpLevelControl, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(outletPot, INPUT);
  pinMode(temperatureSensor, INPUT);
  pinMode(inletPump, OUTPUT);
  pinMode(outletPump, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(outletFlowMeter), outletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge
  attachInterrupt(digitalPinToInterrupt(inletFlowMeter), inletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge


  //////System Check//////

  // Purge pumps//
  
      analogWrite(outletPump, 10);
      analogWrite(inletPump, 10);

        lcd.clear();
        lcd.setCursor(1, 1);
        lcd.print("Out Pump Purge");
        lcd.setCursor(1, 2);
        lcd.print("In Pump Purge");
  
          delay(5000);

            analogWrite(outletPump, 0);
            analogWrite(inletPump, 0);
  


              lcd.clear();
              lcd.setCursor(1, 1);
              lcd.print("System Ready");
              delay(5000);
              lcd.clear();

}

void loop() 
{

////// Outlet Pump //////

  int pot = analogRead(outletPot); //read potentiometer (0-1023)
  int outSpeed = map(pot, 0, 1023, 0, 255);  // convert to 0-255
  int outpercentage = map(outSpeed, 0, 255, 0, 100);      // PWM vaue mapped to %
    
  outlimitValue = digitalRead(outPumpLevelControl);
    if(outlimitValue == HIGH)
    {
      analogRead(outletPot);
      analogWrite(outletPump, outSpeed);
    }
        lcd.setCursor(0,0);
        lcd.print("Out Speed   ");
        lcd.print(outpercentage);
        lcd.print("%");


        lcd.setCursor(0,1);
        lcd.print("Out   ");
        lcd.print(outflowRate);
        lcd.print(" mL"); 
    

////// Outlet Pump Alarm//////

    if(outlimitValue == LOW)
    {
      analogWrite(outletPump, 0);
  
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.scrollDisplayLeft();
        lcd.print("Outlet Pump Alarm - Check Water Levels");
    }

//////Flow calculations//////
outletFlowcount = 0;
inletFlowcount = 0;

interrupts();
delay(1000);

  outflowRate = 2.1368 * outletFlowcount; //2.1368 is amount of flow in ml/pulse//
  inflowRate = 2.1368 * inletFlowcount;
    
noInterrupts();

          Serial.print("Outlet Flow ");
          Serial.print(outflowRate);
          Serial.println(" mL");

          Serial.print("Inlet Flow ");
          Serial.print(inflowRate);
          Serial.println(" mL");

//////Inlet Pump//////

  int inpercentage = map(inSpeed, 0, 255, 0, 100);      // 13.5 L/min is maximum output of Inlet Pump 

    inlimitValue = digitalRead(inPumpLevelControl);
    if(inlimitValue == HIGH)
    {

      if(outSpeed > inSpeed)
      {
        inSpeed+=10;
       
      analogRead(inSpeed);
      analogWrite(inletPump, inSpeed);
      }
        else if(outSpeed < inSpeed)
        {
          inSpeed-=10;
       
            analogRead(inSpeed);
            analogWrite(inletPump, inSpeed);
        }
          if(outSpeed <=10)
          {
            analogWrite(inletPump, 0);
          }
    }
    
        lcd.setCursor(0,2);
        lcd.print("In Speed    ");
        lcd.print(inpercentage);
        lcd.print("%");


        lcd.setCursor(0,3);
        lcd.print("In    ");
        lcd.print(inflowRate);
        lcd.print(" mL");
    

// Inlet Pump Alarms

    if(inlimitValue == LOW) 
    {
      analogWrite(inletPump, 0);
  
        lcd.clear();
        lcd.setCursor(0,3);
        lcd.scrollDisplayLeft();
        lcd.print("Inlet Pump Alarm - Check Water Levels");
    } 
}

//////Functions//////

void outletFlowPulseIncrement() 
{
  outletFlowcount++;
}
void inletFlowPulseIncrement() 
{
  inletFlowcount++;
}

Thats the modified code. But as highlighted in a previous post by blh64Faraday about the
digitalRead(outPumpLevelControl);
if(outPumpLevelControl, HIGH)
{

I changed it to
outlimitValue = digitalRead(outPumpLevelControl);
if(outlimitValue == HIGH)
{
but it still has no bearing on the pump running. Any ideas where I'm gone wrong?

Thanks


You don't want to have interrupts turned off for most of your program. You want to briefly turn them off to use the volatile counters and then turn them back on.

Something like this cleans up the flow of your logic

#include <LiquidCrystal.h>


//// Pin definitions ////

LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

//Inputs

const int outletFlowMeterPin = 2;   //This is an interupt input pin on the Arduino
int outflowRate;    //This is the value we intend to calculate.
volatile unsigned long outletFlowcount; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.

const int inletFlowMeterPin = 3;    //This is an interupt input pin on the Arduino
int inflowRate;
volatile unsigned long inletFlowcount;

unsigned long lastTime;     // Using internal timing for flow calculations
const unsigned long updateInterval = 1000UL;    // update every second

const float calibrationFactor = 7.8;   // Calibration factor for the flow meters
const float pulsesPerLiter = 468.0;    // Number of pulses per liter

const int outPumpLevelControlPin = 7;   //Outlet low level and Inlet high level limit switches wired in series.
const int inPumpLevelControlPin = 4;    //Inlet low level and Outlet high level limit switches wired in series.
const int outletPotPin = A1;            //Speed control for outlet pump.
const int temperatureSensortPin = A2;   //Inlet water temp.

//Outputs
const int outletPumptPin = 5;     //PWM pump speed control
const int inletPumptPin = 6;      //PWM pump speed control

// Set initial speeds for both pumps
int outSpeed = 0;
int inSpeed = 0;

void setup()
{
  Serial.begin(9600);   //Start serial monitor
  lcd.begin(16, 4);     //Start LCD display

  pinMode(outletFlowMeterPin, INPUT);
  pinMode(inletFlowMeterPin, INPUT);
  pinMode(outPumpLevelControlPin, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(inPumpLevelControlPin, INPUT_PULLUP); //PULLUP to activate internal resistor
  pinMode(outletPotPin, INPUT);
  pinMode(temperatureSensortPin, INPUT);
  pinMode(inletPumptPin, OUTPUT);
  pinMode(outletPumptPin, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(outletFlowMeterPin), outletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge
  attachInterrupt(digitalPinToInterrupt(inletFlowMeterPin), inletFlowPulseIncrement, FALLING); // Interrupt for counting pulses, falling edge


  //////System Check//////

  // Purge pumps//

  analogWrite(outletPumptPin, 10);
  analogWrite(inletPumptPin, 10);

  lcd.clear();
  lcd.setCursor(1, 1);
  lcd.print("Out Pump Purge");
  lcd.setCursor(1, 2);
  lcd.print("In Pump Purge");

  delay(5000);

  analogWrite(outletPumptPin, 0);
  analogWrite(inletPumptPin, 0);

  lcd.clear();
  lcd.setCursor(1, 1);
  lcd.print("System Ready");
  delay(5000);
  lcd.clear();
}

void loop()
{

  ////// Outlet Pump //////

  int pot = analogRead(outletPotPin); //read potentiometer (0-1023)

  outSpeed = map(pot, 0, 1023, 0, 255);  // convert to 0-255
  if (outSpeed <= 10) outSpeed = 0;

  int outpercentage = map(outSpeed, 0, 255, 0, 100);      // PWM vaue mapped to %

  int outlimitValue = digitalRead(outPumpLevelControlPin);

  if (outlimitValue == HIGH) {
    // water level okay

    lcd.setCursor(0, 0);
    lcd.print("Out Speed   ");
    lcd.print(outpercentage);
    lcd.print("%");

    lcd.setCursor(0, 1);
    lcd.print("Out   ");
    lcd.print(outflowRate);
    lcd.print(" mL");
  }
  else {
    ////// Outlet Pump Alarm//////

    outSpeed = 0;

    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.scrollDisplayLeft();
    lcd.print("Outlet Pump Alarm - Check Water Levels");
  }

  analogWrite(outletPumptPin, outSpeed);

  //////Flow calculations//////

  if ( millis() - lastTime >= updateInterval )
  {
    noInterrupts();
    outflowRate = 2.1368 * outletFlowcount; //2.1368 is amount of flow in ml/pulse//
    inflowRate = 2.1368 * inletFlowcount;
    outletFlowcount = 0;
    inletFlowcount = 0;

    interrupts();

    Serial.print("Outlet Flow ");
    Serial.print(outflowRate);
    Serial.println(" mL");

    Serial.print("Inlet Flow ");
    Serial.print(inflowRate);
    Serial.println(" mL");

    lastTime = millis();
  }

  //////Inlet Pump//////

  int inpercentage = map(inSpeed, 0, 255, 0, 100);      // 13.5 L/min is maximum output of Inlet Pump

  int inlimitValue = digitalRead(inPumpLevelControlPin);

  if (inlimitValue == HIGH) {
    // water level okay
    if (outSpeed > inSpeed) {
      inSpeed += 10;
      if ( inSpeed > 255 ) inSpeed = 255;
    }
    else if (outSpeed < inSpeed) {
      inSpeed -= 10;
      if ( inSpeed < 0 )inSpeed = 0;
    }
  }
  else {
    // Inlet Pump Alarms
    inSpeed = 0;

    lcd.clear();
    lcd.setCursor(0, 3);
    lcd.scrollDisplayLeft();
    lcd.print("Inlet Pump Alarm - Check Water Levels");
  }

  analogWrite(inletPumptPin, inSpeed);

  lcd.setCursor(0, 2);
  lcd.print("In Speed    ");
  lcd.print(inpercentage);
  lcd.print("%");

  lcd.setCursor(0, 3);
  lcd.print("In    ");
  lcd.print(inflowRate);
  lcd.print(" mL");
}

//////Functions//////

void outletFlowPulseIncrement()
{
  outletFlowcount++;
}
void inletFlowPulseIncrement()
{
  inletFlowcount++;
}

Thanks very much for that blh64Faraday

I'll run it and see.

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