Closed-loop turbo blowthrough carb project = fun

Hi folks. This is a project I’ve been putting off for years, and finally got started last week. Please keep in mind that about all I know about ‘C’ is that it’s the 3rd letter of the alphabet… and I’m sure that will be apparent in the bits of code I have so far. Feel free to point and laugh, as long as you explain why and how to fix it. :stuck_out_tongue_closed_eyes:

This is a contraption to control the AFR of a turbo blowthrough Holley carb’ed small block V8. The power valves in stock form are normally open (by a spring) and pulled closed by engine vacuum; as load increases and vacuum decays the spring pushes the valve off its seat and exposes an extra pair of fuel jets, richening the mixture. This doesn’t always work as expected when pressurized air is fed to the carb. If the main boosters are flowing before the PVs try to open, low pressure in the main well keeps them sucked shut and the spring is not strong enough to open them. Turbo engine runs lean and then expensive parts fall out the bottom. These PVs are modified, with the original spring flipped around to the other side of the valve and are now normally closed, until a positive pressure (from an outside source) pushes the valve off its seat against the spring pressure. This works well as long as the external pressure source is enough over boost pressure to open the valve (inside the carb, the boost pressure effectively becomes the new ambient pressure - the carb’s parts don’t have any way to distinguish between the two). The part that sucks is that the PV circuit has to be tuned with jetting just like the other circuits to get the right WOT/in-boost fuel mix, and controlling it with only a simple Hobbs switch or similar is a bit crude.

This project reads an array of stand-alone sensors: TPS, MAP, WBO2, and based on a combination of those sensor readings determines when to hit the PVs with the external pressure source. More than 30% throttle, and over 3PSI boost, and AFR higher than 12.5:1, the Arduino triggers the air solenoid and the power valves open, and the mixture gets richer. When AFR falls to 12.0:1, the solenoid turns off and the power valves close. This makes the PV jet area pretty much irrelevant as long as they’re big enough to flow more fuel than the desired minimum AFR. Much easier to poke some buttons and change the WOT AFR, right?

I have it working, mostly, on the bench. Uno, proto-screwshield, & 16x2 serial/i2c RGB LCD. I have a few points I’m stuck on that I’ll lay out later (some are mentioned in the comments) but for now, since I have no idea why what I’ve done so far works, I’d be eternally grateful if y’all could check my code and point out anything I’ve done horribly wrong before I go too much farther.

/*
Closed-loop power valve (PV) control for turbo/blower blowthrough Holley carbs

Example:
If TPS is above 30%, and MAP is above 3.5psi, and WBO2 is above 12.5:1, turn the PV solenoid ON
If TPS is above 30%, and MAP is above 3.5psi, and WBO2 is below 12.0:1, turn the PV solenoid OFF
PV is CLOSED unless all conditions are met

Carb's PVCR (power valve channel restrictors (an extra set of main jets)) should be sized to 
supply fuel for richer mix than the desired PV 'off' point - in other words, the lower bound for 
air/fuel mix should be controlled by when the Arduino turns the PV off, not by the PVCR area as usual.
*/

// include the library code:
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

// The shield uses the I2C SCL and SDA pins.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

int TPSPin = 0; //signal return from TPS
int MAPPin = 1; //signal return from MAP
int O2Pin = 2; //analog 0-5v output from WBO2 controller
int PVPin = 13; //output to control PV
int PVStatus = 0; //used to read whether PV is commanded ON or OFF

void setup() 
{
  lcd.begin(16, 2);  
  // Initialize input & output pins
  pinMode (TPSPin, INPUT);
  pinMode (MAPPin, INPUT);
  pinMode (O2Pin, INPUT);
  pinMode (PVPin, OUTPUT);
}

void loop ()
{    
  // Display TPS & MAP on first row
  int TPSValue = analogRead(TPSPin);
  int TPSOutput = map(TPSValue,0,1023,7,105); //values used for bench testing only, shows throttle position in %
  lcd.setCursor(0, 0);
  lcd.print("TPS");  
  lcd.setCursor(4, 0);
  lcd.print(TPSOutput); //used to display whole numbers only
  
  int MAPValue = analogRead(MAPPin);
  float MAPOutput = map(MAPValue,0,1023,-150,300); //not correct yet, the negative values need to display in/Hg, not PSI
  lcd.setCursor(6, 0);
  lcd.print("% MAP ");  
  lcd.setCursor(12, 0);
  lcd.print(MAPOutput / 10); //used to display to one digit after decimal (XX.X), does not work that way yet!
  
  //Display O2 & PV state on second row
  int O2Value = analogRead(O2Pin);
  float O2Output = map(O2Value,0,1023,735,2239); //MTX-L analog #1 used as example, 0-5v = 7.35:1-22.39:1
  lcd.setCursor(0, 1);
  lcd.print("AFR ");  
  lcd.setCursor(4, 1);
  lcd.print(O2Output / 100); //used to display 2 digits after decimal, works correctly
  
  int PVState = digitalRead(PVPin);
  lcd.setCursor(10, 1);
  lcd.print("PV ");  
  lcd.setCursor(13, 1);
  delay(150); //HALP! Delay makes the display easier to read, but sensors & PV output do not need a delay- fixable?
  
  // WBO2 hysteresis not implemented yet, no clue how to do that part!
  // threshold values configured to match how those readings appear on the display
  // If TPS is over 30% and MAP is over 3.5PSI, turn on the PV
  if ((TPSOutput >= 30) && (MAPOutput / 10.0 >= 3.5)) // && (O2Output / 100 something important should go here)
    {
      digitalWrite (PVPin, HIGH);
    }
  else {
      digitalWrite (PVPin, LOW);
    }
  //Display 
  PVStatus = digitalRead(PVPin);
  if (PVStatus == HIGH) {
  lcd.print(" ON"); // replace this with a 4th sensor (IAT? ECT?) and use backlight color alone to show PV state?
  lcd.setBacklight(WHITE); //LCD backlight color changes as well when PV is active!
  }
  else {
    lcd.print("OFF");
    lcd.setBacklight(TEAL);
  }
}

Hi, welcome to the forum.
The sketch is not bad, it is okay, but it can be made more beautiful.
You already mention the problems in the comments, that makes my job easy :wink:

You use the map function and convert that to a float.
That is okay, but it might not always be correct. The 'map' function is done with integers. If you need to do more calculations, you could write it in code with float numbers. If that needs 5 code lines instead of just one 'map()' function, that is no problem.

With this code, it is easy to make a mistake with the units. Perhaps you can add comments to tell what it is, "psi" or "percentage oxygen" and so on.
The "psi" doesn't even have a meaning to me, I'm used to "bar" and "kPa" :slight_smile:

You use the value '0' and '1' and so on for the analog pins. That is okay when used with analogRead, but using 'A0' and 'A1' in the sketch is preferred by most Arduino users.
I used '0' and '1' myself for an analog pin, but now I'm using 'A0', 'A1', and it makes the sketch better to read.

The Arduino can read a digital output pin. And it is okay to do so, but a software enginer doesn't like it. Instead of reading an output pin, you could use that PVStatus variable.

if ( ....
  PVStatus = HIGH;
else 
  PVStatus = LOW;

digitalWrite( ..., PVStatus);

if ( PVStatus == HIGH)
  ...

The delay(150) is okay. Reading the sensors a few times a second is no problem.. is it ?
You can read the sensors faster, and only update the display 2 to 20 times a second. You can use millis() to create this 2 to 20 times a second display update. Search for "blink without delay".

My global impression is that you can make your code more beautiful, if you are more careful when to use integer and float and how that is printed on the lcd.
When using data from sensors, I prefer to use 'float' variables in real units, not in 1/10 or 1/100 units. When you look at your sketch in 5 years, things will be easier when everything is in real units.

It is generally good practice to:
Declare you pin numbers as 'const int' so the compiler can warn you if you accidentally try to change the value.
Use the names A0-A5 , not 0-5, when talking about analog input pins. It makes your intention clearer.
DON'T use Pin 0 or Pin 1 for digital I/O. Those are the Serial pins and it is very handy for debugging to use them for Serial.

Thanks for the tips :blush:

On most of those issues (A0 vs 0, const int vs int), I've been back and forth (actually, been all over the place with just about all of it). Since I'm getting most of it as copied snippets of other folks' code, sometimes I see different conventions used and try both ways and if they both work the same I just move on to the next part. It's better when one way works but the other one doesn't... I've learned MUCH more from the stuff that didn't work.

On calculating the displayed values I tried both float and plain ol' int, what's used in that sketch version is what comes the closest to making the displayed numbers most usable - enough info, but not too much. It all works as it should except the MAP, I have the cursor set there to hang the unwanted extra digits off the far edge of the LCD. I'm sure there's an easy way to specify how many places after the decimal to show, just haven't fount it yet. (also, I hope this is plainly obvious, but I don't math good. Very occasionally I get the correct answer by accident, though)

Adding hysteresis to the O2's switching point may not be necessary or even helpful. The response time on the PV circuit is pretty slow since it's only exposing additional main jet area and not putting fuel into the airstream directly. There will be some carburetor-based hysteresis built in anyway.

If that lcd.print uses the Stream class, you can print a floating point with lcd.print( x, 2);

Hi, you may need to read many values of any of the sensors and average them to get a viable reading.
The O2 sensor is an example where you will need to average your value, also the type of O2 sensor will be important.
Early O2 had a sharp knee at the stoichiometric point for petrol combustion. this meant that apart from knowing where the correct mixture was, all you got out of the sensor was if it was too lean or tooo rich, not a definite figure.
The latest units have better linearity and can give you something representing AFR.

Tom..... :slight_smile:

Oh no, it's using a modern wideband controller, and the O2 input to the Arduino is one of the analog 0-5v aux outputs (there's a second analog output (unused here) that by default outputs 0-1v, to simulate a narrowband sensor).

I figured out the clumsiness I didn't realize was there in the 'PVStatus' section at the end. D'OH! Why didn't I see that from the start?

  • removed the int PVStatus = 0; line altogether
  • changed the end to:
lcd.setCursor(9, 1);
  lcd.print(" PV O");  
  delay(150);
  
  if ((TPSOutput >= 30) && (MAPOutput / 10.0 >= 3.5)) // && (O2Output / 100 >= 12.25)
    {
      digitalWrite (PVPin, HIGH);
      lcd.setCursor(14, 1);
      lcd.print("N ");
      lcd.setBacklight(RED);
    }
  else {
      digitalWrite (PVPin, LOW);
      lcd.setCursor(14, 1);
      lcd.print("FF");
      lcd.setBacklight(TEAL);
    }

It doesn't need to read PVStatus or PVPin or anything at all, it can just print the status & change the backlight all at once. (it only prints the 'N' in 'ON' and 'FF' in 'OFF', the first 'O' is always there since it never changes).

Here’s the whole thing in its current state. Finally got what I hope is a better method on reading the MAP sensor (the previous code was showing vacuum in -PSI instead of inHg). The backlight color changes based on the boost level. Added a simple on/off fuel pump control based on a ground signal from an oil pressure switch and it does a 5 second pump prime cycle at key-on before showing the main screen. And probably some other stuff.

/*
Closed-loop power valve (PV) control for turbo/blower blowthrough Holley carbs

Example:
If TPS is above 30%, and MAP is above 3.5psi, and WBO2 is above 12.5:1, turn the PV solenoid ON
PV is CLOSED unless all conditions are met

Carb's PVCR (power valve channel restrictors) should be sized to supply fuel for richer mix than 
the desired PV 'off' point - in other words, the lower bound for air/fuel mix should be controlled 
by when the Arduino turns the PV off, not by the PVCR area as usual.
*/

// include the library code:
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

// The shield uses the I2C SCL and SDA pins.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

const int TPSPin = A0; //signal return from TPS
const int MAPPin = A1; //signal return from MAP
const int O2Pin = A2; //analog 0-5v output from WBO2 controller
const int PVcontrol = 13; //output to control BRPV
const int FPcontrol = 12; //output to control fuel pump
const int FPenable = 2; //
int FPstate = 0;

void setup() 
{
  lcd.begin(16, 2);
    
  // Initialize input pins
  pinMode (TPSPin, INPUT);
  pinMode (MAPPin, INPUT);
  pinMode (O2Pin, INPUT);
  pinMode (FPenable, INPUT_PULLUP);

  // Initialize output pins
  pinMode (PVcontrol, OUTPUT);
  pinMode (FPcontrol, OUTPUT);

  // Stuff to do before starting main program
  digitalWrite (FPcontrol, HIGH);
  lcd.setBacklight(RED);  
  lcd.setCursor(0,0);
  lcd.print("Fuel pump prime:");
  delay(4500);
  lcd.setBacklight(GREEN);
  lcd.setCursor(0,1);  
  lcd.print("    ...OK       ");
  delay(500);
  digitalWrite (FPcontrol, LOW);
}

void loop ()
{    
  
  // Throttle Position Sensor
  int TPSValue = analogRead(TPSPin);
  int TPSOutput = map(TPSValue,0,1023,0,102); // adjust values to read 0% at idle, 100% at WOT
  lcd.setCursor(0,0);
  lcd.print("TPS");
  
      // sets display position, clears leftover bits when number of digits changes
      if (TPSOutput < 10)
      {
        lcd.setCursor(3,0);
        lcd.write(254);
        lcd.setCursor(4,0);
        lcd.write(254);
        lcd.setCursor(5,0);
        lcd.print(TPSOutput);
      }
      if ((TPSOutput > 10) && (TPSOutput < 100))
      {
        lcd.setCursor(3,0);
        lcd.write(254);
        lcd.setCursor(4,0);
        lcd.print(TPSOutput);
      }
      if (TPSOutput > 100)
      {
        lcd.setCursor(3,0);
        lcd.print(TPSOutput);
  }
      
  // Manifold Absolute Pressure sensor
  lcd.setCursor(6,0);
  lcd.print("% MAP");  

  int MAPValue = analogRead(MAPPin); //Reads the MAP sensor raw value on analog port 1
  float MAPOutput = (((MAPValue/(float)1023+0.00842)/.002421)*.145)-14.696; // Freescale 4-BAR MPXH6400
      
      // sets display position, clears orphaned bits when number of digits changes
      if ((MAPOutput * 2.036) < -10)
      {
        lcd.setCursor(11,0);
        lcd.print((MAPOutput * 2.036),1);
      }
      if (((MAPOutput * 2.036) > -10) && (MAPOutput < 0))
      {
        lcd.setCursor(11,0);
        lcd.write(254);
        lcd.setCursor(12,0);
        lcd.print((MAPOutput * 2.036),1);
      }
      if ((MAPOutput > 0) && (MAPOutput < 10))
      {
        lcd.setCursor(11,0);
        lcd.write(254);
        lcd.setCursor(12,0);
        lcd.write(254);
        lcd.setCursor(13,0);
        lcd.print(MAPOutput,1);
      }
      if (MAPOutput > 10)
      {
        lcd.setCursor(11,0);
        lcd.write(254);
        lcd.setCursor(12,0);
        lcd.print(MAPOutput,1);
      }
      
            //Boost level changes backlight color
          if (MAPOutput < 1)
          {
            lcd.setBacklight(GREEN);
          }
          if ((MAPOutput > 1) && (MAPOutput < 2.5))
          {
            lcd.setBacklight(YELLOW);
          }
          if (MAPOutput > 2.5)
          {
            lcd.setBacklight(RED);
  }
  
  // WBO2/UEGO
  int O2Value = analogRead(O2Pin);
  float O2Output = map(O2Value,0,1023,2239,735); //MTX-L analog #1 used as example, 0-5v = 7.35:1-22.39:1
  lcd.setCursor(0,1);
  lcd.print("AFR");  
  
      // sets display position, clears orphaned bits when number of digits changes
      if (O2Output < 1000)
      {
        lcd.setCursor(4,1);
        lcd.write(254);
        lcd.setCursor(5,1);
        lcd.print(O2Output/100);
      }
      if (O2Output > 1000)
      {
        lcd.setCursor(4,1);
        lcd.print(O2Output/100);
  }
      
  // Power valve control & status display
  lcd.setCursor(10,1);
  lcd.print("PV O");
  delay(150);
  
  // threshold values configured to match how those readings appear on the display
  // If TPS is over __% and MAP is over __PSI and O2 is __.__:1 or leaner, turn on the PV
  if ((TPSOutput >= 27) && (MAPOutput >= 1.8) && (O2Output/100 >= 12.45))
    {
      digitalWrite (PVcontrol, HIGH);
      lcd.setCursor(14,1);
      lcd.print("N ");
    }
  else {
      digitalWrite (PVcontrol, LOW);
      lcd.setCursor(14,1);
      lcd.print("FF");
  }
  
  // Fuel pump control from oil pressure switch: ground = engine running, open = engine stopped
  // To-do when I get a whole lot smarter: PWM control of fuel pump speed based on MAP sensor
  FPstate = digitalRead(FPenable);
  if (FPstate == LOW) {
      digitalWrite (FPcontrol, HIGH);
      }
  else  {
      digitalWrite (FPcontrol, LOW);
      }
      
}

Hoping to add PWM fuel pump speed control, intake air & coolant temp sensors (with fan control) in the future… which means this will all have to move over to a Mega board & bigger LCD.

I'm curious to know what your "PVPin" is actually controlling. Obviously it's something to fill in for the shortcomings of the PV in the carb, but what is the physical device that you are using?

A 3-port pneumatic solenoid, set up so that the output line vents when the solenoid is off/closed.

The stock Holley power valve (Holley Power Valves - JEGS High Performance) is normally open, by a spring, and vacuum sucks it closed. These are modified with the spring moved around to the other side of the pintle so they're normally closed, and applying some external pressure opens them. Pressure can be an air pump, CO2 bottle (lots of race cars already have that to run other things), or even the pre-turbine exhaust backpressure, since that's usually at least nearly double the boost pressure.

The reason the stock valve setup doesn't always open when it should is on some setups, it's possible to get the main boosters flowing before the PV opens, and since the internals of the carb are referenced to boost pressure, the pressure differential in there isn't always enough to let the spring overcome the suction created by the restriction of the main jets, and the valve stays closed when it shouldn't be. The stock valves can even work fine if you drive it one way (go straight to WOT, which opens the PV before the mains are flowing), but not open at all if you drive it another way (roll into it from ~3000RPM).

All that aside, who wouldn't want a carburetor where you can change the mixture with a few buttons?

Hi cat_hearder, glad to see your project is moving along and that you are getting help from some of the finest members of this forum!

I have couple little things that may have been mentioned already but, here goes.

I noticed that you print to the LCD on every loop. There are a few things that only need printed once unless the LCD gets cleared or changed drastically. One example is that you print the letters "AFR" on every loop even though they do not get changed or cleared. You could print "AFR" at the end of setup and only print the changing variables during the loops.

Other examples are similar like printing the letters TPS , MAP, and PV. LCD printing can take up a lot of time that could be used by the Arduino for other tasks.

The line that I am speaking of here:

lcd.print("AFR");

Great job so far,
Mark

Something else that could help would be to check to see if your variables have changed since the last loop before printing to the LCD. Notice, that I created a variable called OldMAPOutput. Here is an example in sudo code:

 // check to see if MapOutput variable has changed
  if (MAPOutput != OldMAPOutput){
       OldMAPOutput = MAPOutput;  // store the latest reading
      
        //If you have made it to here, MAPOutput has changed
        //Print to the LCD
  
      }

Here is a code snippet to help you with your PVControl using PWM. You will have to decide how to apply it to your application but, it should give you a direction to go. I just guessed on some numbers for the example.

    // Check MAPOutput and TPSOutput values to decide what value to make FPcontrol. 
  if ((MAPOutput <= YourNumber) && TPSOutput <= AnotherNumber)
  {
    analogWrite(FPcontrol, 0);  // analogWrite values from 0 to 255
  }
  else if ((MAPOutput >= YourNumber) && TPSOutput >= AnotherNumber)
  {
    analogWrite(FPcontrol, 100);
  }
  else if ((MAPOutput >= YourNumber) && TPSOutput >= AnotherNumber)
  {
    analogWrite(FPcontrol, 180);
  }
  else
  {
    analogWrite(FPcontrol, 255);
  }

If I didn’t mention it before, I am a Novice, so beware. :slight_smile:

I played with the fuel pump junk a little last night and came up with something that works a little different. I think it’s all covered in the comments…

// Fuel pump control 
    // engine running/oil pressure switch closed = FPenable pin grounded, FPstate=LOW
    // engine stopped/oil pressure switch open = FPenable pin open circuit, FPstate=HIGH
  int FPcontrol = map(TPSvalue, 0,523,76,255); //76 is about 30% for minimum pump speed
  FPstate = digitalRead(FPenable);
  if (FPstate == HIGH)  {
      analogWrite (FPoutput,0);
      }
  else if (MAPvalue >= 243)  {  // about 0 PSI
      analogWrite (FPoutput,255);
      }
  else if (TPSvalue >= 508)  {  // about 50% throttle
      analogWrite (FPoutput,255);
      }
  else  {  // otherwise, pump speed is proportional to throttle position
      analogWrite (FPoutput,FPcontrol);
      }

edit: changed teh second if to an else if… I SWEAR it worked right without it, and then suddenly it didn’t (ungrounding the FPenable pin would no longer turn off the pump). Tore it all apart and changed everything, still wouldn’t work, then I pasted back in the original code and added the ‘else’ and it went back to working like it did before. Honestly!

I cannot for the life of me figure out how to make it read the FPenable pin directly, without adding the FPstate for it to read instead... what's the trick there? I know it doesn't/shouldn't need to read the FPstate that's reading the FPenable pin, I just don't know how to do it without breaking everything else.

Something that I am not sure if you know, this bit of code will only act on the first "true" statement.

 if (FPstate == HIGH)  {
      analogWrite (FPoutput,0);
      }
  else if (MAPvalue >= 243)  {  // about 0 PSI
      analogWrite (FPoutput,255);
      }
  else if (TPSvalue >= 508)  {  // about 50% throttle
      analogWrite (FPoutput,255);
      }
  else  {  // otherwise, pump speed is proportional to throttle position
      analogWrite (FPoutput,FPcontrol);
      }

Basically, If FPstate is HIGH, the code will not check MAPvalue or TPS. I am not sure if you meant for that to happen.

I cannot for the life of me figure out how to make it read the FPenable pin directly

Here is how you can put a digitalRead in an "if" statement.

if (digitalRead(FPenable) == LOW) {
      digitalWrite (FPcontrol, HIGH);
      }
      
      if (digitalRead(FPenable) == HIGH) {
      digitalWrite (FPcontrol, LOW);
      }

I think I would keep it the way you have it in your posted code because it is probably faster, and the if statements are so quick that you will not see an improvement.

Yes, at least that's how it works on the bench. If the enable pin is no longer grounded, the pump has to turn off no matter what the other inputs are.

Speed isn't an issue really, since it needs a delay to make the display readable, and besides the response will be slow since it's not injecting fuel directly but just enabling a second set of main jets. I expect a complete on-off-on cycle will take some large portion of a second.

I have my MAP sensors now and have tweaked the numbers to get it showing actual atmospheric pressure as 0.0, but I still don't trust the formula I'm using (stolen from someone else's project, and I have no idea if they did it right). It converts 0-1023 to voltage. Converts voltage to kPa. Converts kPa to PSI. Then if it's less than 0PSI, converts to vacuum in inHg. Blech.

4-BAR (MPXH6400A) MAP sensor completed, inside a gutted GM housing:

Very interesting!

Take a look at this Honeywell link and see if these are similar.

I would say no - 'uncompensated and unamplified' is probably an advantage for some applications, but too much work for this 'specially when the Freescale sensors already do that stuff internally.

4-BAR: http://www.digikey.com/product-detail/en/MPXH6400AC6U/MPXH6400AC6U-ND/1168412
breakout board for above: SMT Breakout PCB for SOIC-8, MSOP-8 or TSSOP-8 - 6 Pack! : ID 1212 : $2.95 : Adafruit Industries, Unique & fun DIY electronics and kits

2.5-BAR: http://www.digikey.com/product-detail/en/MPX4250AP/MPX4250AP-ND/464053

Connecting a hose to the MPXH6400 is not exactly straightforward. The nipple is claimed to be 1/8", but measures only .119" OD, it's very short, and not barbed at all. That's why I chose to stick it inside its own little sealed box like that.