Arduino Uno Fuel Pump Controller. Constrain, or If Statement?

Here is my current project, at heart it is an Arduino Uno. I am currently using a single analog input, but I am planning to use multiple inputs after I get the controller to operate with the single input. The analog input I am using is a fuel pressure sensor. My uno is interpreting this voltage and displaying it as a pressure on my 16x2 lcd. I have a DC brushless fuel pump that accepts a PWM input to control its speed. I have a program written to control this fuel pump speed with the map function. It also prints the current duty cycle of the PWM output to my LCD. The issue that I am running into is that I need to keep the fuel pressure at a constant reading, while being able to increase or decrease the PWM signal to gain more flow from the fuel pump during high demand. There will be a fuel pressure regulator on the fuel system to keep the fuel pressure from rising too high. The duty cycle cannot drop below 20% or the pump will turn off. Here is broken down detail of how I want to program either the constrain or if statement to keep the pump running fast enough. Of course I will have to interpret the voltage readings once I get the fuel pressure sensor calibrated correctly. 43 psi is roughly 2.5 volts.

Fuel Pressure Duty Cycle
44 psi 30%
43.5 psi 40%
43 psi 50%
42.5 psi 75%
42 psi 100%

Once I get this working correctly then I will add another pressure sensor that will read manifold pressure and when it rises to 2 psi of boost (turbo car), I will have it write the pin to high (100%), to prevent a loss of fuel under boost conditions. I have tried several variations of constrain but I have yet to get it to function how I want it to. Please give me some insite as to how I should program this. Here is a copy of my current program, there is no constrain in these programs I did not save them due to the lack of function.
Thanks in advance. Aaron

#include <LiquidCrystal.h>

 const int numRows= 2;
 const int numCols= 16;
 int sensorPin = A0;
 const int ledPin= 6;
 int sensorValue = 0;

//initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

 void setup()
 {
 Serial.begin(9600);
 lcd.begin(numCols, numRows);
 lcd.print("Fuelab Prodigy");
 lcd.setCursor(0,2);
 lcd.print("Pump Controller");
 delay(2000);
 lcd.clear();
 analogWrite(ledPin, 255);
 delay(8000);
 
 
 }

 void loop()
 {
  
  sensorValue = analogRead(sensorPin);
  delay(500);
  int val = analogRead(0);
  Serial.println(val);
  delay(1);
  val = map(val, 0, 1023, 255, 0);
  analogWrite(ledPin, val);
  lcd.clear();
  int pressure = sensorValue;
  pressure = map(sensorValue, 0, 1023, 0, 90);
  lcd.print(pressure);
  lcd.setCursor(3,0);
  lcd.print("PSI");
  lcd.setCursor(0,1);
  int pump = val;
  pump = map(val, 0, 255, 0, 100);
  lcd.print(pump);
  lcd.setCursor(3,1);
  lcd.print("% Duty Cycle");
  }
  sensorValue = analogRead(sensorPin);

Did you really get out a catalog, and order a sensor? Meaningful names ARE important.

  int val = analogRead(0);

Why are you now using the number of the pin, instead of the name you assigned to it? Why are you storing the reading in a different variable?

I gave up, after this, trying to figure out what you are doing. You have one sensor connected to one pin, yet you seem to think that you have two different uses for that one sensor.

The code looks as if it has been chopped about and I don't know which parts work.

Write a sketch that just reads the analog input value and prints it. Does it return sensible values corresponding to the actual fuel pressure? What is the relationship between the input value and the fuel pressure?

PaulS, I corrected the error with the SensorPin, I hadn't realized that I had input it that way.
I apologize if the code isn't written correctly, this is my first arduino project. Any help that you guys can provide I would greatly appreciate. Constructive criticism is welcome, I would rather know that I did something wrong.
PeterH, This current set of code works just fine. It will read and write the correct values. I just need to figure out a set of code that will keep pressure within a set reading. (The PWM output directly effects the analog input with this controller). It is a simple circuit at this point, I am using a POT to act as the pressure sensor to test the system. As I lower the input voltage with the POT, the PWM output will rise to speed up the pump.
Again Thanks for any help you can provide.
Here is a simple version of my code, It seems like I have repeated a few things that I didn't need too.

 int sensorPin = A0;
 const int ledPin= 6;
 int sensorValue = 0;


 void setup()
 {
 Serial.begin(9600);
//Turns the pump on high to prime the system 
 analogWrite(ledPin, 255);
 delay(8000);
 
 
 }

 void loop()
 {
  
  sensorValue = analogRead(sensorPin);
  delay(500);
  int val = analogRead(sensorPin);
  Serial.println(val);
  delay(1);
  val = map(val, 0, 1023, 255, 0);
  analogWrite(ledPin, val);
  lcd.clear();
  int pressure = sensorValue;
  pressure = map(sensorValue, 0, 1023, 0, 90);
  int pump = val;
  pump = map(val, 0, 255, 0, 100);
  }

LS_Mustang:
This current set of code works just fine

It might work, but I'd dispute the 'just fine' part.

You are reading the analog pin twice and saving the result in different variables. Pick one to keep and get rid of the other. Also, if you haven't already done it, print out the raw values you're getting from the analog read, confirm that they change sensibly according to the pressure, and tell us what the relationship is between pressure and the analog value.

Okay I think I got the issue with reading two of the same value figured out, The sensor I am using is an AEM electronics 100 psi sensor. There is a graph of the fuel pressure readings compared to voltage readings. The readings that I am getting are spot on with this chart. The sensor seems to read very consistent across the entire scale of pressures.

int sensorPin = A0;
 const int ledPin= 6;


 void setup()
 {
 Serial.begin(9600);
//Turns the pump on high to prime the system 
 analogWrite(ledPin, 255);
 delay(8000);
 
 
 }

 void loop()
 {
  
  sensorValue = analogRead(sensorPin);
  delay(500);
  int val = analogRead(sensorPin);
  Serial.println(val);
  delay(1);
  val = map(val, 0, 1023, 255, 0);
  analogWrite(ledPin, val);
  lcd.clear();
  int pressure = sensorValue;
  pressure = map(sensorValue, 0, 1023, 0, 90);
  int pump = val;
  pump = map(val, 0, 255, 0, 100);
  }

That code doesn't look any better than the previous version. What's happening on lines 18 and 20?

Based on the chart you posted, the conversion from the analog reading to PSI should be simple:

// 0.5V corresponds to an analog input value of 102
// 4.5V corresponds to an analog input value of 920
int sensorValue = analogRead(sensorPin);
int sensorPsi = map(sensorValue, 102, 920, 0, 100); // 0.5V=0PSI, 4.5v=100PSI

Calculating the pump PWM according to your algorithm needs similar code:

// 42 PSI corresponds to 2.18V which corresponds to an analog input value of 446
// 44 PSI corresponds to 2.26V which corresponds to an analog input value of 462
// 30% duty cycle corresponds to an analogWrite value of 76
// 100% duty cycle corresponds to an analogWrite value of 255
int pumpPwm = map(sensorValue, 446, 462, 76, 255);

// constrain the pump PWM to be in the range 0 .. 255
pumpPwm = constrain(pumpPwm, 0, 255);

Peter, Thanks for all your help so far.
I’m sure my code is horrible, I have not been working with Arduino very long. I am trying to learn as I go, and you have defiantly helped me. I forgot to remove part of the lcd programming I think that may have been what you were asking about on lines 18 - 19. I have written a new version of the code with the help that you have given me. I hope that it is written correctly. I do not have my Arduino here with me at the moment so I cannot test it yet. If you see anything that I messed up please let me know so I can try to fix it. I am not sure that I need to use (int) in front of all of the items that I am using it on.

#include <LiquidCrystal.h>

 const int numRows= 2;
 const int numCols= 16;
 int sensorPin = A0;
 const int pumpPWM 6;

//initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

 void setup()
 {
 Serial.begin(9600);
 lcd.begin(numCols, numRows);
 lcd.print("Fuelab Prodigy");
 lcd.setCursor(0,2);
 lcd.print("Pump Controller");
 delay(2000);
 lcd.clear();
 analogWrite(pumpPWM, 255);
 delay(8000);
 
 
 }

 void loop()
 {
  int sensorValue = analogRead(sensorPin);
  delay(500);
  Serial.println(sensorVal);
  delay(1);
  int pumpSpeed = map(sensorValue, 446, 462, 76, 255);
  analogWrite(pumpPWM, pumpSpeed);
  int pumpPWM = constrain(pumpPWM, 0, 255);
  lcd.clear();
  int pressure = map(sensorValue, 102, 920, 0, 100);
  lcd.print(pressure);
  lcd.setCursor(3,0);
  lcd.print("PSI");
  lcd.setCursor(0,1);
  int pump = map(sensorValue, 0, 255, 0, 100);
  lcd.print(pump);
  lcd.setCursor(3,1);
  lcd.print("% Duty Cycle");
  }




[b]Simple version[/b]



 int sensorPin = A0;
 const int pumpPWM 6;

 void setup()
 {
 Serial.begin(9600);
  analogWrite(pumpPWM, 255);
 delay(8000);
 
 
 }

 void loop()
 {
  int sensorValue = analogRead(sensorPin);
  delay(500);
  Serial.println(sensorVal);
  delay(1);
  int pumpSpeed = map(sensorValue, 446, 462, 76, 255);
  analogWrite(pumpPWM, pumpSpeed);
  int pumpPWM = constrain(pumpPWM, 0, 255);
  int pressure = map(sensorValue, 102, 920, 0, 100);
  int pump = map(sensorValue, 0, 255, 0, 100);
  }

Defiant help is always useful.

I assume that the delay(500) is to prevent LCD flicker and to make the serial output easier to read. Why do you also have a delay(1) though?

No, lines 18 and 20 were where you read the same analog input twice, into different variables.

You should constrain the pump PWM output value before you output it, not after.

The name 'pumpPWM' is misleading IMO because it actually holds a pin number, not a PWM value. Perhaps pumpPwmPin would be clearer?

I suggest putting the delay at the end of the loop (if you need one), so that your sketch responds to fuel pressure changes promptly rather than always using stale data. In the final solution, I suggest you design it so that it doesn't need a delay and controls the pump as quickly as it can. To do that you would run the control logic at every loop iteration, and update the display on a timed basis. The 'blink without delay' example sketch demonstrates how to execute code on a timed basis.

I suspect you will want to add some smoothing to the analog input value since fuel pressure it likely to have a lot of noise. An exponential decaying average would work well in this situation.

Well that was supposed to say definitely, not defiantly. I have corrected a few more things and I am working on the smoothing of the input data, I am unsure about how to use a delay to prevent the use of stale data. I also changed the name of the pumpPWM, it is clearer when it is named as a pin. I also moved the pump constrain above the write code. I removed that delay of one, that was an old line of code that I forgot to remove, I had another line being printed on my lcd but I removed it.

#include <LiquidCrystal.h>

 const int numRows = 2;
 const int numCols = 16;
 int sensorPin = A0;
 const int pumpPWMpin = 6;
 const int numReadings = 10;

 int readings[numReadings];      // the readings from the analog input
 int index = 0;                  // the index of the current reading
 int total = 0;                  // the running total
 int average = 0;                // the average




//initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

 void setup()
 {
 Serial.begin(9600);
 for (int thisReading = 0; thisReading < numReadings; thisReading++)
     readings[thisReading] = 0;
 lcd.begin(numCols, numRows);
 lcd.print("Fuelab Prodigy");
 lcd.setCursor(0,2);
 lcd.print("Pump Controller");
 delay(2000);
 lcd.clear();
 analogWrite(pumpPWMpin, 255);
 delay(8000);
 
 
 }

 void loop()
 {
   // subtract the last reading:
   total= total - readings[index];         
   // read from the sensor:  
   readings[index] = analogRead(sensorPin); 
   // add the reading to the total:
   total= total + readings[index];       
   // advance to the next position in the array:  
   index = index + 1;                    

   // if we're at the end of the array...
   if (index >= numReadings)              
     // ...wrap around to the beginning: 
     index = 0;                           

   // calculate the average:
   average = total / numReadings;         
   // send it to the computer as ASCII digits
   Serial.println(average);   
   delay(1);        // delay in between reads for stability            
  int sensorValue = (average);
  int pumpSpeed = map(sensorValue, 446, 462, 76, 255);
  int pumpPWMpin = constrain(pumpPWMpin, 76, 255);
  analogWrite(pumpPWMpin, pumpSpeed);
  lcd.clear();
  int pressure = map(sensorValue, 102, 920, 0, 100);
  lcd.print(pressure);
  lcd.setCursor(3,0);
  lcd.print("PSI");
  lcd.setCursor(0,1);
  int pump = map(sensorValue, 0, 255, 0, 100);
  lcd.print(pump);
  lcd.setCursor(3,1);
  lcd.print("% Duty Cycle");
  }

Do you see a problem here?

  int pumpSpeed = map(sensorValue, 446, 462, 76, 255);
  int pumpPWMpin = constrain(pumpPWMpin, 76, 255);
  analogWrite(pumpPWMpin, pumpSpeed);

Ohhh, yes I do. Constrain should be 0,255 not 76 255.

Hi, No, which is the variable and which is the pin ID?

i

int pumpSpeed = map(sensorValue, 446, 462, 76, 255);
int pumpPWMpin = constrain(pumpPWMpin, 76, 255);
analogWrite(pumpPWMpin, pumpSpeed);

You are constraining the pin ID not the pumpSpeed.

Tom...... :slight_smile:
PS, leave the 76, 255 so that you won't stall the pump.