Jump to content

Welcome To Mopar1973Man.Com LLC

We are privately owned, with access to a professional Diesel Mechanic, who can provide additional support for Dodge Ram Cummins Diesel vehicles. Many detailed information is FREE and available to read. However, in order to interact directly with our Diesel Mechanic, Michael, by phone, via zoom, or as the web-based option, Subscription Plans are offered that will enable these and other features.  Go to the Subscription Page and Select a desired plan. At any time you wish to cancel the Subscription, click Subscription Page, select the 'Cancel' button, and it will be canceled. For your convenience, all subscriptions are on auto-renewal.

Posted

You can find the article for this build here 


 
First I need to give credit where it is due and reconize Farm828 and other on CumminsForum in this Thread

Also I need to give major credit to Hakcenter from lilbb.com and his code and use of turbo RPM to calculate vane position.  
 
I am currently working on getting my 351ve conrolled using a arduino uno and sparkfun canbus shield along with some other basic parts/sensors
 
Here are the list of parts that are used.  you can void the code to use one or all of the sensors, but this list is for everything.
 
Parts: for controlling the he351 with boost and drive pressure 
Arduino uno: https://www.sparkfun.com/products/11021$25
Canbus Shield:  https://www.sparkfun.com/products/10039$40
Exhaust/boost sensor 0-100 psi:  http://www.auberins.com/index.php?main_page=product_info&cPath=5_23&products_id=271x2 if you want to control the turbo on both exhaust and boost.  $56 a piece
Potentiometer push pull 10k linear: http://www.ebay.com/itm/POTENTIOMETER-PUSH-PULL-SWITCH-POT-GUITAR-10K-LIN-SPLIT-SHAFT-LINEAR-V164L4-/271184505955?pt=LH_DefaultDomain_3&hash=item3f23db2c63 $5
Momentary on button switch: havent picked one up yet that I like.  Currently using a computer button.
Wire: 16-20 gauge should be fine 100' should be enough
Connectors: I used DT06-12SA and DT06-12PA along with all hardware, ebay link
 

Parts: for controlling based on turbo shaft RPMS are a little more indepth.  If you want to do that please visit lilbb.com and look over his setup and his parts list.  He makes a shield that can control the turbo based on rpms.  

in short you will need some resistors and a 9924 chip to count shaft speed.

 
Software:
You will need to download the Arduino program: http://arduino.cc/en/Main/Software
Download the Canbus library: https://www.dropbox.com/s/sldwefec5ybf04t/CANLibrarymaster.zip?dl=0 (thanks to Farm828)
download the LCD Library: https://www.dropbox.com/s/j4n35dhbl5wth8e/NewliquidCrystal.zip?dl=0
Basic Code downloaded here: https://www.dropbox.com/s/0wyvudbymjl0yg3/HE351VE_Control.ino?dl=0 (thanks to Farm828)
 
You can edit the code by voiding the sensors "//" you are using in the right section, defined.
 
 
 
My goals in short are:  //updated 3/4/15
 
1. Boost to drive ratio of up to 2:1 until 30 psi is hit, then the veins will manage
2. Fast spool and near smokeless 400-450hp
3. When enabled, Potentionmeter that controls the veins manually until higher throttle input is sensed it will also try and manage DP is need be
4. Exhaust brake controlled by a momentary switch on the shifter select
5. Display sensor values on a simple serial LCD screen in cab.
 
 
 
I am currently running DFI 7x.009 injectors so your boostmaps in the below code may differ.  You can copy and past the below into an arduino window and have it work.  
 
 
 
 
 
current code for Boost/Drive controlled HE351ve  If you choose to run in boost/drive controller mode you need to understand that it is VERY easy to over speed the turbo.  I would highly recommend you use shaft speed.

/*This code is to help get you started controlling your
HE351VE Variable Geometry Turbo. The whole program is
controlled through void loop(). This is where you can
add your own code or uncomment different sections of code
that I have put together. This is covered by the GNU License*/

#include <SPI.h>
#include <can.h>
#include <Wire.h>  
#include <LiquidCrystal_I2C.h>
#include <Timer.h>

// Defines for setting up the CAN Bus
#define mode NORMAL // define CAN mode
#define bitrate 250 // define CAN speed (bitrate)
MCP CAN1(10);       //Create CAN Channel
//J1939 message;    // Create message object to use J1939 message structure
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

// Timers
Timer t1;
Timer t2;
unsigned int timer = 0;
byte adc_roll_over = 0;

// Pin Assignments on UNO
#define BoostPressurePin A0
#define ExhaustPressurePin A1
#define PotentiometerPin A2
#define ThrottlePositionPin A3
#define Switch 2
#define EBSwitch 9

#define NumEntries 14 // if using the entire boost map
// The first number is the boost sensor reading, and the second number is the desired vein position
// remember usable vien position range from 140-960
int BoostMap[NumEntries][2] = {{10,235},{11.5,250},{13,265},{14.5,280},
{16,295},{17.5,310},{19,325},{20.5,340},{22,355},{23.5,370},{25,385},{26.5,400},
{28,415},{29.5,430}};  // DPManage takes care of the veins after 30psi.  

#define NumEntriesPerf 14 // boost map for high performance
int BoostMapPerf[NumEntriesPerf][2] = {{1,275},{3,285},{4,295},{9,305},{16,315},{17.5,325},{19,335},{20.5,345},{22,355},{23.5,365},{25,375},{26.5,385},
{28,400},{29.5,430}};

#define NumEntriesDD 14 // boost map for high performance
int BoostMapDD[NumEntriesDD][2] = {{10,300},{11.5,310},{13,320},{14.5,330},
{16,340},{17.5,350},{19,360},{20.5,370},{22,380},{23.5,390},{25,400},{26.5,410},
{28,420},{29.5,430}};

#define NumEntriesMpg 3 // boost map for high mileage
int BoostMapMpg[NumEntriesMpg][2] = {{10,400},{20,415},{29.5,430}};

/*
 * Turbo Size (cm^2) vs Position
 *  25  24  23  22  21  20  19  18  17  16  15  14
 * 960 918 876 835 793 751 709 667 625 584 542 500
 *  13  12  11  10  9   8   7   6   5   4    3
 * 458 416 375 333 291 249 207 165 124  82  40
 */


// Variables to read sensors
int MaxExhaustPressure = 50; //Set desired max exhuast back pressure
int MaxEBPressure = 45; //set desired max EB Drive Pressure
int ExPrsBuffer = 10; //set the point at which the system starts to manage IE: maxehaustpressure - exprsbuffer
byte EBCalibrate = 2;
int PotentiometerValue = 0;
int ExhaustPressure = 0;
int BoostPressure = 0;
int ThrottlePosition = 0;
boolean SwitchPosition = false;
boolean EBSwitchPosition = false;

// Value to Send Position
int DesiredPosition = 0;
 
// Variables to use within Code
int JumpSize = 50;
int MinVeinPos = 235;
 
// Variables for LCD
int Line1Last = 0;
char BoostMapMode = 'D';
  
// Exhaustpressure Average variables
const byte ExtnumReadings = 4;            // number of reads to do.
unsigned int Extreadings[ExtnumReadings]; // the readings from the analog input
byte Extindex = 0;                        // the index of the current reading
unsigned int Exttotal = 0;                // the running total
unsigned int Extaverage = 0;              // the average
  
//  Boostpressure Average variables
const byte BstnumReadings = 4;            // number of reads to do.
unsigned int Bstreadings[BstnumReadings]; // the readings from the analog input
byte Bstindex = 0;                        // the index of the current reading
unsigned int Bsttotal = 0;                // the running total
unsigned int Bstaverage = 0;              // the average

//  Throttle Average variables
const byte ThrnumReadings = 4;            // number of reads to do.
unsigned int Thrreadings[ThrnumReadings]; // the readings from the analog input
byte Thrindex = 0;                        // the index of the current reading
unsigned int Thrtotal = 0;                // the running total
unsigned int Thraverage = 0;              // the average

////////////////////////////will run once at startup//////////////////////////
void setup() {
  // Initialize Serial communications with computer to use serial monitor
  Serial.begin(115200);
  lcd.begin(20,4);         // initialize the lcd for 20 chars 4 lines and turn on backlight
  // Set CAN mode and speed
  CAN1.begin(mode, bitrate);
  
  // Setup Timers
  t1.every(2, SendTurboPosition);
  t2.every(1, keep_time);
 
  // Setup Switch
  pinMode(Switch, INPUT_PULLUP); //configure switch to use internal pullup resistor
  pinMode(EBSwitch, INPUT_PULLUP); //configure EBswitch to use internal pullup resistor
  //Running exhaust average
  for (int ExtthisReading = 0; ExtthisReading < ExtnumReadings; ExtthisReading++) {
    Extreadings[ExtthisReading] = 0;
  }
  //Running Boost averag
  for (int BstthisReading = 0; BstthisReading < BstnumReadings; BstthisReading++) {
    Bstreadings[BstthisReading] = 0;
  }
  //Running Throttle averag
  for (int ThrthisReading = 0; ThrthisReading < ThrnumReadings; ThrthisReading++) {
    Thrreadings[ThrthisReading] = 0;
  }
  
//-------- Write characters on the display ----------------
// NOTE: Cursor Position: CHAR, LINE) start at 0  
  lcd.setCursor(2,0); //Start at character 4 on line 0
  lcd.print("Starting HE351VE");
  lcd.setCursor(5,1);
  lcd.print("Controller");
  lcd.setCursor(4,2);
  lcd.print("Will Display ");
  lcd.setCursor(0,3);  
  lcd.print("Boost,Drive,Position");
  delay(4000);
  lcd.clear();
  lcd.setCursor(4,0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6,1);
  lcd.print("Position");
  lcd.setCursor(3,3);
  lcd.print("Wait To Start!");
  delay(500);
  lcd.clear();
  DesiredPosition = 140;
  SendTurboPosition();
  lcd.clear();
  lcd.setCursor(4,0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6,1);
  lcd.print("Position");
  lcd.setCursor(3,3);
  lcd.print("Wait To Start!");
  delay(500);
  DesiredPosition = 140;
  SendTurboPosition();
  lcd.clear();
  lcd.setCursor(4,0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6,1);
  lcd.print("Position");
  lcd.setCursor(3,3);
  lcd.print("Wait To Start!");
  delay(500);
  DesiredPosition = 140;
  SendTurboPosition();
  lcd.clear();
  lcd.setCursor(4,0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6,1);
  lcd.print("Position");
  lcd.setCursor(3,3);
  lcd.print("Wait To Start!");
  delay(500);
  lcd.clear();
  lcd.setCursor(8,2);
  lcd.print("Done!");
  delay(1000);
  lcd.clear();
}

//////////////////////////// Main loops that choices what to do.//////////////
void loop() {
  // Update Timers
  t1.update();
  t2.update();

       if (SwitchPosition == HIGH && EBSwitchPosition == HIGH && BoostPressure >= 30) { DPManage (); } //run the veins based on drive pressure after 30psi boost.  
  else if (SwitchPosition != HIGH ) { PotManage (); } //vein position is pot value if throttle is under %30.  Set the throttle value to be above cruising tps. && ThrottlePosition < 30
  else if (EBSwitchPosition != HIGH && SwitchPosition == HIGH && ThrottlePosition < 5 ) { EBManage (); } //If below %1.5 then engage Exhaust brake and regulate the exhaust pressure.
  else { PosManage ();}  //set vein position based on boostmap 
}

////////////////////////////Read Sensors//////////////////////////////////////
//Define the sensor type and range. (Namefromabove, 0v, 5v, 0v=minpos,5v=maxposition)

int ReadBoostPressure() {                                 // Works good but seems to be slower.
  Bstindex++;                                // advance to the next position in the array:
  if (Bstindex >= BstnumReadings) { Bstindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Bstreadings[Bstindex] = analogRead(BoostPressurePin);   // read from the sensor:
                                                          // add the reading to the total:
  Bsttotal = Bstreadings[0] + Bstreadings[1] + Bstreadings[2] + Bstreadings[3];
  Bstaverage = Bsttotal >> 2; // / BstnumReadings;        // calculate the average:
  return map( Bstaverage, 80, 920, 0, 100);               // Last two values are the psi range of the chosen sensor
}

int ReadExhaustPressure() {                               // Works good but seems to be slower.
  Extindex++;                                             // advance to the next position in the array:
  if (Extindex >= ExtnumReadings) { Extindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Extreadings[Extindex] = analogRead(ExhaustPressurePin); // read from the sensor:
                                                          // add the reading to the total:
  Exttotal = Extreadings[0] + Extreadings[1] + Extreadings[2] + Extreadings[3];
  Extaverage = Exttotal >> 2; // / ExtnumReadings;        // calculate the average:
  return map(Extaverage, 83, 920, 0, 100);                // Last two values are the psi range of the chosen sensor
}

//int ReadThrottlePosition() {
//  analogRead(ThrottlePositionPin);
//  int ThrottleVal = analogRead(ThrottlePositionPin);              //(tmp + analogRead( PotentiometerPin )) / 2;
//  return map(ThrottleVal, 86, 760, 0, 100);                  // Last two values are the psi range of the chosen sensor
//}
int ReadThrottlePosition() {
  Thrindex++;                                             // advance to the next position in the array:
  if (Thrindex >= ThrnumReadings) { Thrindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Thrreadings[Thrindex] = analogRead(ThrottlePositionPin); // read from the sensor:
                                                          // add the reading to the total:
  Thrtotal = Thrreadings[0] + Thrreadings[1] + Thrreadings[2] + Thrreadings[3];
  Thraverage = Thrtotal >> 2; // / ExtnumReadings;        // calculate the average:
  return map(Thraverage, 86, 760, 0, 100);     // Last two values are the psi range of the chosen sensor
}
int ReadPotentiometer(){
  analogRead(PotentiometerPin);
  int PotVal = analogRead(PotentiometerPin);              //(tmp + analogRead( PotentiometerPin )) / 2;
  return map(PotVal, 0, 1023, 0, 1000);                    // read the value from the sensor
}

/////////////////////////////POS Manage////////////////////////////////////////
//Manages Boost map position in an effort to prevent Barking when letting off the throttle.
void PosManage() {
  if ( PotentiometerValue < 25 ){ DesiredPosition = BoostVeinPosCalcDD(BoostPressure); BoostMapMode = 'P'; }  //if pot is set to below 25 then the boostmap it looks at is boostveinposcalcPerf
  else if ( PotentiometerValue > 980){ DesiredPosition = BoostVeinPosCalcPerf(BoostPressure);  BoostMapMode = 'E';}
  else { DesiredPosition = BoostVeinPosCalcMpg(BoostPressure);  BoostMapMode = 'D';}
}

/////////////////////////////DP Manage////////////////////////////////////////
//Manages DP to try and stay at or below 50psi drive while above 30psi boost.  veins will stay between 445 and 970 position
void DPManage() {
  int Difference = (ExhaustPressure - MaxExhaustPressure); //set a buffer make sure max ex press doesn't get hit.
 
  Difference = (Difference / EBCalibrate);                 // I used / rather than * as the * ended up applying too fast. the turbo was "snapping" open and closed
  DesiredPosition += max(Difference, - 3);                //This way it doesn't close the veins to fast
  DesiredPosition = constrain(DesiredPosition, 430, 970);
}

/////////////////////////////EB Manage////////////////////////////////////////
//Manages the apply of the EB
void EBManage() {
  int Difference = (ExhaustPressure - MaxEBPressure); //set a buffer make sure max ex press doesn't get hit.
 
  Difference = (Difference / EBCalibrate);                 // I used / rather than * as the * ended up applying too fast. the turbo was "snapping" open and closed
  DesiredPosition += max(Difference, - 7);              //This way it doesn't close the veins to fast
  DesiredPosition = constrain(DesiredPosition, 15, 235);
}

////////////////////////////Pot Manage////////////////////////////////////////
//Ensure Pot doesn't cause Drive pressure to go over the maxexhaustpressure **look at more

void PotManage() {
 int Rate = 11;                                                    // added to make ManageRate grow as exhaust pressure rises to max and above.
 int PotBuff = 10;                                                 //amount to buffer the vein position before maxexhaust is reached when in pot mode
 int ManageRate = ((ExhaustPressure - MaxExhaustPressure) + Rate);
 
      if (PotentiometerValue > 999){DesiredPosition = constrain(DesiredPosition, 970, 970);}
 else if ( ThrottlePosition > 25 ){ DesiredPosition = BoostVeinPosCalcDD(BoostPressure);}
 else if (ExhaustPressure < (MaxExhaustPressure - PotBuff)) { DesiredPosition = constrain(PotentiometerValue, 20, 970); }
 else if (ExhaustPressure >= (MaxExhaustPressure - PotBuff)) {
   DesiredPosition = (PotentiometerValue +(JumpSize * ManageRate));
   DesiredPosition = constrain(DesiredPosition, 40, 970);
 }
}

////////////////////////////Vein Position send////////////////////////////////
// Function to calculate turbo vein position
int BoostVeinPosCalcDD( int BoostPressureVal ){
  int VeinPosition = BoostMapDD[0][1];
  for(byte i = 0; (BoostPressureVal > BoostMapDD[i][0]) && (i < NumEntriesDD); i++) {
    VeinPosition = BoostMapDD[i][1];
   }
  return VeinPosition;
 }
int BoostVeinPosCalcPerf( int BoostPressureVal ){
  int VeinPosition = BoostMapPerf[0][1];
  for(byte i = 0; (BoostPressureVal > BoostMapPerf[i][0]) && (i < NumEntriesPerf); i++) {
    VeinPosition = BoostMapPerf[i][1];
   }
  return VeinPosition;
 }
 int BoostVeinPosCalcMpg( int BoostPressureVal ){
  int VeinPosition = BoostMapMpg[0][1];
  for(byte i = 0; (BoostPressureVal > BoostMapMpg[i][0]) && (i < NumEntriesMpg); i++) {
    VeinPosition = BoostMapMpg[i][1];
   }
  return VeinPosition;
 }

// Function to Send the Calculated Position to the Turbo
void SendTurboPosition() {
  int FinalPosition = map(DesiredPosition, 0, 1023, 999, 0);
  constrain(DesiredPosition, 0, 999);
  byte lobyte = lowByte(FinalPosition);
  byte hibyte = highByte(FinalPosition);
  unsigned long ID = 0x0CFFC600; // Random Extended Message ID
  byte length = 8; // Data length
  byte data[] = {lobyte, hibyte, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // data message with an added counter
  CAN1.send (ID, extID, length, data); // Load message and send
}

////////////////////////////BarGraph//////////////////////////////////////////
void BarGraph(int Line, int oldBars, int Bars, int Value, String Name) {
  //Line, which line on the LCD are we changing.
  //Bars, number of pixcels long the BaGraph is going to show
  //oldBars, number of Bars that this Line had lastt time
  //Value, what's the value we should print to the lcd
  //Name, the Name we should call this Line

  int GraphStartPoint = 11;//what cell does the graph start on on the lcd screen
 
  if (oldBars != Bars) { // if nothing changed then skip this function
    int oldBlocks = (oldBars / 5);
    int blocks = (Bars / 5);
    int singles = (Bars - (blocks * 5));
    if(blocks > oldBlocks) {
      for(int x = oldBlocks; blocks > x; x++) {
        lcd.setCursor((x + GraphStartPoint), Line);
        lcd.write(1023);
      }
    } else if (blocks < oldBlocks) {
      for(int x = oldBlocks; blocks <= x; x--) {
        lcd.setCursor((x + GraphStartPoint), Line);
        lcd.print(" ");
      }
    }
    if ((oldBars - oldBlocks) != singles) {//if the number of singles has changed display the new singles
      lcd.setCursor((blocks + GraphStartPoint),Line);
      lcd.write(singles);
    }
  }
  lcd.setCursor(GraphStartPoint - 4, Line);
  String TurboPos = String(Value, DEC);
  if (Value < 1000) { TurboPos += " "; }
  lcd.print(TurboPos);
  lcd.setCursor(0, Line);
  lcd.print(Name);
}

////////////////////////////LCD///////////////////////////////////////////////
void UpdateLCD() {
  int Line1Bars = map(DesiredPosition, 0, 1023, 0, 40);//map the value to a 0-50 value.
  BarGraph(0, Line1Last, Line1Bars, DesiredPosition, "Turbo");
  Line1Last = Line1Bars;
  float DrivePressRatio = ((ExhaustPressure * 1.00) / (BoostPressure*1.00));
  DrivePressRatio = constrain(DrivePressRatio, 0, 2.99);
  String Boost = String("Boost " + String(BoostPressure, DEC) + ' ');
  String Drive = String("Drive " + String(ExhaustPressure, DEC) + ' ');
  ///String Throttle = String(ThrottlePosition, DEC);
  String DtoBRatio = String("DtoB Ratio " + String(DrivePressRatio) + ":1");
  String MapMode = String(BoostMapMode);
  lcd.setCursor(0, 2);
  lcd.print(Boost);
  lcd.setCursor(19, 0);
  lcd.print(MapMode);
  //lcd.setCursor(0, 1);
  //lcd.print(Throttle);
  lcd.setCursor(10, 2);
  lcd.print(Drive);
  if (BoostPressure <= 0) {
    lcd.setCursor(0, 3);
    lcd.print("DtoB Ratio 1.00:1");
  } else {
    lcd.setCursor(0, 3);
    lcd.print(DtoBRatio);
  }
  if (EBSwitchPosition != HIGH && SwitchPosition == HIGH) {
    lcd.setCursor(4, 1);
    lcd.print("!EB  Active!");
  } else if(SwitchPosition != HIGH && PotentiometerValue > 999) {
    lcd.setCursor(0, 1);
    lcd.print("!Turbo Locked Open!");
  } else if(SwitchPosition != HIGH && ThrottlePosition < 25) {
    lcd.setCursor(0, 1);
    lcd.print("    !Pot Active!    ");
  }
    else {
    lcd.setCursor(0, 1);
    lcd.print("                   ");
    }
}

////////////////////////////Keep Time/////////////////////////////////////////
void keep_time() {
  timer++;
  adc_roll_over++;
  // Read Sensors
  // Uncomment the Sensors that you have connected
  // There functions will need to be calibrated to the sensor.
  if (adc_roll_over == 1) { BoostPressure = ReadBoostPressure(); }
  if (adc_roll_over == 2) { ExhaustPressure = ReadExhaustPressure(); }   
  if (adc_roll_over == 3) { PotentiometerValue = ReadPotentiometer(); }
  if (adc_roll_over == 4) { ThrottlePosition = ReadThrottlePosition(); }
  if (adc_roll_over == 5) { adc_roll_over = 0; }  
  if (timer % 200) {
    SwitchPosition = digitalRead(Switch);
    EBSwitchPosition = digitalRead(EBSwitch);
  }
  if (timer % 200) { UpdateLCD(); }
  if (timer == 1000) { timer = 0; }
  
}

Here is the code for using RPMS to control the turbo as said above you will need the added parts to count

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *
 *  This work is licensed under the
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

#include <SPI.h>
#include <can.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Timer.h>
#include <FreqMeasure.h>

// Defines for setting up the CAN Bus
#define mode NORMAL // define CAN mode
#define bitrate 250 // define CAN speed (bitrate)
MCP CAN1 (10);       //Create CAN Channel
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

// Timers
Timer t1;
Timer t2;
unsigned int timer = 0;
byte adc_roll_over = 0;

// Pin Assignments on UNO
#define BoostPressurePin A0
#define ExhaustPressurePin A1
#define PotentiometerPin A2
#define ThrottlePositionPin A3
#define Switch 7
#define EBSwitch 9

byte time_start1, time_finished1, time_elapsed1;
boolean millis_out = true;
// Controller Modes
boolean idle_mode = false;
boolean idle_walkdown_mode = false;
boolean idle_check = false;
boolean SwitchPosition = false;
boolean EBSwitchPosition = false;

//startup to cycle turbo.
boolean startcycle = false;
boolean AntiBark = false;
unsigned long over_run = 0;

//TPS
unsigned int TPS_range = 0;
boolean Offidle = false;

// Minimum and Maximum Vane Positions
const unsigned int min_position = 40;
const unsigned int max_position = 940;
// Vane Positions
const unsigned int idle_position = 700;
const unsigned int Offidle_position = 860;
unsigned int Stable_Pos = 0;
unsigned int vane_position = 0;
unsigned int last_vane_position = 0;
unsigned int final_vane_position;
unsigned int Movement = 0;
// Turbo Curves & Factors
const byte two_cm = 80;
const byte one_cm = 40;
const byte half_cm = 20;
const unsigned int idle_rpm = 12000;
const unsigned int idle_walkdown_rpm = 22000;
const unsigned long lit_rpm = 105000;  //RPM where turbo is considered to be making full boost
const unsigned long BarkRpm = 75000;  // If rpm is over this rpm process runs to keep turbo from barking when letting off throttle
const unsigned int curve_rpm[5] = { 17000, 20000, 26000, 37000, 65000 };
unsigned int turbo_curve[5] = { 0, 0, 0, 0, 0 };
const unsigned int turbo_curve_1[5] = { 800, 740, 700, 640, 584 }; // ends 12cm Perf curve larger vane position due to more fuel can + tap fuel. Curve is choosen by inactive pot position watchpot(); 770,730,710,600,416
const unsigned int turbo_curve_2[5] = { 830, 770, 730, 670, 625 }; //ends 11 cm DD curve with can fueling only mid curve
const unsigned int turbo_curve_3[5] = { 860, 800, 760, 700, 667 }; //ends 10 cm Tow curve for timing only no extra fueling 830,790,730,650,550

// Turbo
const int minimum_turbo_rpm = 3000;
unsigned long turbo_rpm = 0;
unsigned long last_turbo_rpm = 0;
boolean update_vane_position = false;
boolean TPS_low = false;
boolean TPS_midlow = false;
boolean TPS_mid = false;
boolean TPS_high = false;
//double turbo_accel = 0.0;
//double accel_factor = 0.0;
//Turbo Curve
boolean curvea = false;
boolean curveb = false;
boolean curvec = false;
//mode selection
boolean eb_mode = false;
boolean pot_mode = false;
boolean EBModeSense = false;
boolean PotModeSense = false;


/*
 * Turbo Size (cm^2) vs Position
 *   3   4   5   6   7   8   9  10  11  12  13  14
 * 960 918 876 835 793 751 709 667 625 584 542 500
 *  15  16  17  18  19  20  21  22  23  24  25
 * 458 416 375 333 291 249 207 165 124  82  40
 */


// Variables to read sensors
int MaxExhaustPressure = 50; //Set desired max exhuast back pressure
int PotentiometerValue = 0;
int ExhaustPressure = 0;
int BoostPressure = 0;
int ThrottlePosition = 0;


// Variables for LCD
int Line1Last = 0;
char BoostMapMode = 'Z';
int lastcurvemode = 0;
int curvemode = 0;

int VanePos = 0;


// Exhaustpressure Average variables
const byte ExtnumReadings = 4;            // number of reads to do.
unsigned int Extreadings[ExtnumReadings]; // the readings from the analog input
byte Extindex = 0;                        // the index of the current reading
unsigned int Exttotal = 0;                // the running total
unsigned int Extaverage = 0;              // the average

//  Boostpressure Average variables
const byte BstnumReadings = 4;            // number of reads to do.
unsigned int Bstreadings[BstnumReadings]; // the readings from the analog input
byte Bstindex = 0;                        // the index of the current reading
unsigned int Bsttotal = 0;                // the running total
unsigned int Bstaverage = 0;              // the average

//  Throttle Average variables
const byte ThrnumReadings = 4;            // number of reads to do.
unsigned int Thrreadings[ThrnumReadings]; // the readings from the analog input
byte Thrindex = 0;                        // the index of the current reading
unsigned int Thrtotal = 0;                // the running total
unsigned int Thraverage = 0;              // the average

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *
 *  This work is licensed under the
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////will run once at startup//////////////////////////
void setup() {
  // Initialize Serial communications with computer to use serial monitor
  Serial.begin(115200);
  lcd.begin(20, 4);        // initialize the lcd for 20 chars 4 lines and turn on backlight
  // Set CAN mode and speed
  CAN1.begin(NORMAL, bitrate);
  FreqMeasure.begin();

  // Setup Timers
  t1.every(2, set_turbo_position);
  t2.every(1, keep_time);

  // Setup Switch
  pinMode(Switch, INPUT_PULLUP); //configure switch to use internal pullup resistor
  pinMode(EBSwitch, INPUT_PULLUP); //configure EBswitch to use internal pullup resistor
  //Running exhaust average
  for (int ExtthisReading = 0; ExtthisReading < ExtnumReadings; ExtthisReading++) {
    Extreadings[ExtthisReading] = 0;
  }
  //Running Boost averag
  for (int BstthisReading = 0; BstthisReading < BstnumReadings; BstthisReading++) {
    Bstreadings[BstthisReading] = 0;
  }
  //Running Throttle averag
  for (int ThrthisReading = 0; ThrthisReading < ThrnumReadings; ThrthisReading++) {
    Thrreadings[ThrthisReading] = 0;
  }

  //-------- Write characters on the display ----------------
  // NOTE: Cursor Position: CHAR, LINE) start at 0
  startcycle = true;
  lcd.setCursor(2, 0);
  lcd.print("Starting HE351VE");
  lcd.setCursor(5, 1);
  lcd.print("Controller");
  lcd.setCursor(4, 2);
  lcd.print("Will Display ");
  lcd.setCursor(0, 3);
  lcd.print("Boost,Drive,Position");
  delay(2000);
  lcd.clear();
  lcd.setCursor(4, 0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6, 1);
  lcd.print("Position");
  lcd.setCursor(3, 3);
  lcd.print("Wait To Start!");
  delay(250);
  lcd.clear();
  vane_position = 960;
  set_turbo_position();
  lcd.clear();
  lcd.setCursor(4, 0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6, 1);
  lcd.print("Position");
  lcd.setCursor(3, 3);
  lcd.print("Wait To Start!");
  delay(250);
  vane_position = 960;
  set_turbo_position();
  lcd.clear();
  lcd.setCursor(4, 0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6, 1);
  lcd.print("Position");
  lcd.setCursor(3, 3);
  lcd.print("Wait To Start!");
  delay(250);
  vane_position = 960;
  set_turbo_position();
  lcd.clear();
  lcd.setCursor(4, 0); //Start at character 4 on line 0
  lcd.print("Cycling Vein");
  lcd.setCursor(6, 1);
  lcd.print("Position");
  lcd.setCursor(3, 3);
  lcd.print("Wait To Start!");
  delay(250);
  lcd.clear();
  lcd.setCursor(8, 2);
  lcd.print("Done!");
  delay(500);
  lcd.clear();
  vane_position = 500;
  set_turbo_position();
  startcycle = false;

  ///here I set the lcd screen items that are static to save time in the lcd update process at the end.  
  lcd.setCursor(0, 2);
  lcd.print("Boost ");
  lcd.setCursor(10, 2);
  lcd.print("Drive ");
  lcd.setCursor(7, 1);
  lcd.print("  Turbo Speed");
  lcd.setCursor(0, 0);
  lcd.print("CM^2 = ");
  lcd.setCursor(0, 3);
  lcd.print("DtoB Ratio ");
  lcd.setCursor(15, 3);
  lcd.print(":1  ");
  //  lcd.setCursor(0, 3);
  //  lcd.print("DtoB Ratio ");
  //  lcd.setCursor(15, 3);
  //  lcd.print(":1   ");


}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

//////////////////////////// Main loops that choices what to do.//////////////
void loop() {

  // Freq Measure to read turb rpm
  unsigned long sum[32];  //number of reads per array
  unsigned long final_sum;
  byte count = 0;
  
  // loop
  while(1) {
    t1.update();
    t2.update();
    
    // Freq Measure
    if (FreqMeasure.available()) {
    //time_start1 = millis();
      // average several reading together
      sum[count] = FreqMeasure.read();
      count++;
      // turbo_rpm = Freq(sum / count) * 60
      final_sum = 0;
      for (int i = 0; i < 32 ; i++) { final_sum += sum[i]; } //add read to array
      turbo_rpm = FreqMeasure.countToFrequency(final_sum >> 5); //divides the array by 32 or in bitwise >>5
      turbo_rpm = (turbo_rpm << 6) - (turbo_rpm << 2); //converts the turbo freq to RPM
      if (count > 31) { count = 0; }  //reset the array count if more than 31 reads.
    
  //time_finished1 = millis();
  //time_elapsed1 = time_finished1 - time_start1;
    }
  }
}

  void calculate_modes(){
      
     if (digitalRead(Switch) == LOW ) { pot_mode = true;} else { pot_mode = false; } //vein position is pot value
     if (digitalRead(EBSwitch) == LOW && ThrottlePosition < 5) { eb_mode = true;} else { eb_mode = false; } //If below %5 then engage Exhaust brake and regulate the exhaust pressure.   
  
   //Pot mode
     if (pot_mode && !eb_mode) {PotManage(); }  //watches for pot switch trigger, if it happens it bypasses the vane calc and goes to pot calc
  // -- BRAKE MODE -- //
     if (eb_mode) {EBManage(); }

// TPS_range calc process
     if (ThrottlePosition <= 25) {TPS_low = true;} else {TPS_low = false;}
     if (ThrottlePosition <= 45 && ThrottlePosition > 25) {TPS_midlow = true;} else {TPS_midlow = false;} //{TPS_range = 0;}// watches throttle input to increase vane position.  Vane position mapping is based on low throttle input. 
     if (ThrottlePosition <= 70 && ThrottlePosition > 45) {TPS_mid = true;} else {TPS_mid = false;} //{TPS_range = 20;}
     if (ThrottlePosition > 70)  {TPS_high = true;} else {TPS_high = false;} //{TPS_range = 40;}

     if (TPS_low) {TPS_range = 0;} //supports low throttle cruise. if under %25 don't change vanes
     if (TPS_midlow){
      if ( BoostPressure < 5) {TPS_range = -40;} //it will try and spool the turbo if tps is 25><45 - numbers decrease vane size
      else if ( BoostPressure < 10) {TPS_range = -20;}
      else {TPS_range = 0;}
     }
     if (TPS_mid){
      if (BoostPressure < 10) {TPS_range =  -20;} 
      else if (BoostPressure < 20) {TPS_range = 0;}
      else {TPS_range = 20;}
     }
     if (TPS_high){
      if (BoostPressure < 20) {TPS_range = 0;}
      else if (BoostPressure < 30) {TPS_range = 20;}
      else {TPS_range = 40;}
     }

  }
/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////Read Sensors//////////////////////////////////////
//Define the sensor type and range. (Namefromabove, 0v, 5v, 0v=minpos,5v=maxposition)

int ReadBoostPressure() {                                 // Works good but seems to be slower.
  Bstindex++;                                // advance to the next position in the array:
  if (Bstindex >= BstnumReadings) { Bstindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Bstreadings[Bstindex] = analogRead(BoostPressurePin);   // read from the sensor:
                                                          // add the reading to the total:
  Bsttotal = Bstreadings[0] + Bstreadings[1] + Bstreadings[2] + Bstreadings[3];
  Bstaverage = Bsttotal >> 2; // / BstnumReadings;        // calculate the average:
  return map( Bstaverage, 80, 920, 0, 100);               // Last two values are the psi range of the chosen sensor
}

int ReadExhaustPressure() {                               // Works good but seems to be slower.
  Extindex++;                                             // advance to the next position in the array:
  if (Extindex >= ExtnumReadings) { Extindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Extreadings[Extindex] = analogRead(ExhaustPressurePin); // read from the sensor:
                                                          // add the reading to the total:
  Exttotal = Extreadings[0] + Extreadings[1] + Extreadings[2] + Extreadings[3];
  Extaverage = Exttotal >> 2; // / ExtnumReadings;        // calculate the average:
  return map(Extaverage, 83, 920, 0, 100);                // Last two values are the psi range of the chosen sensor
}

int ReadThrottlePosition() {
  Thrindex++;                                             // advance to the next position in the array:
  if (Thrindex >= ThrnumReadings) { Thrindex = 0; }       // if we're at the end of the array... wrap around to the beginning:
  Thrreadings[Thrindex] = analogRead(ThrottlePositionPin); // read from the sensor:
                                                          // add the reading to the total:
  Thrtotal = Thrreadings[0] + Thrreadings[1] + Thrreadings[2] + Thrreadings[3];
  Thraverage = Thrtotal >> 2; // / ExtnumReadings;        // calculate the average:
  return map(Thraverage, 86, 760, 0, 100);                // Last two values are the psi range of the chosen sensor

 }
int ReadPotentiometer(){
  analogRead(PotentiometerPin);
  int PotVal = analogRead(PotentiometerPin);              
  return map(PotVal, 0, 1023, 1000, 0);                    // read the value from the sensor
}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

/////////////////////////////POS Manage////////////////////////////////////////
void PosManage() {
      if (turbo_rpm <= curve_rpm[4]) {
        if (ThrottlePosition < 3) {  // Idle Section
          if (turbo_rpm > BarkRpm) {AntiBark = true; vane_position = min_position;} else {AntiBark = false;} // this will slap the vane positon wide open if turbo is above barkrpm and TPS is below 3
            if(turbo_rpm <= idle_rpm) {  //if tps is below 3 and turbo rpm is below idle rpm post is idle position
             vane_position = idle_position;
             idle_walkdown_mode = false;
          } else {
            if (turbo_rpm <= idle_walkdown_rpm) { idle_walkdown_mode = true;} else { idle_walkdown_mode = false; }  //idle walk down walks the turbo position to idle position slowly.
            if (idle_walkdown_mode) { vane_position = idle_position - two_cm;}  
                        
          }
        }else {  AntiBark = false;
          // -----
          // Curve section
                
               if (turbo_rpm <= curve_rpm[0]) { vane_position = constrain(map(turbo_rpm, idle_rpm , curve_rpm[0], Offidle_position, turbo_curve[0]), Offidle_position, turbo_curve[0]);} // This will snap the vanes from idle position to starting position whne tps sense.
          else if (turbo_rpm <= curve_rpm[1]) { vane_position = map(turbo_rpm, curve_rpm[0], curve_rpm[1], turbo_curve[0], turbo_curve[1]);}  //this is the high end mapping of the turbo.
          else if (turbo_rpm <= curve_rpm[2]) { vane_position = turbo_curve[1];}  //this is the high end mapping of the turbo.
          else if (turbo_rpm <= curve_rpm[3]) { vane_position = map(turbo_rpm, curve_rpm[2], curve_rpm[3], turbo_curve[1], turbo_curve[2]);}  //this is the high end mapping of the turbo.
          else { vane_position = map(turbo_rpm, curve_rpm[3], curve_rpm[4], turbo_curve[2], turbo_curve[3]- TPS_range);}  //this is the high end mapping of the turbo.
        }
      } else if (turbo_rpm < lit_rpm) { AntiBark = false;
          vane_position = map(turbo_rpm, curve_rpm[4], lit_rpm, turbo_curve[3]- TPS_range, turbo_curve[4] - TPS_range);}//+ TPS_range was put into place to open the vane more if throttle input was higher

/////////////////This is the top end controls.  The turbo really does increase rpms VERY quickly the trick to to find the sweet spot where rpms stay steady at wot.       
////////////////
       else{
        AntiBark = false;
        if (curvea){  //end pos of 18cm starts 12 cm
                 if (turbo_rpm <= 120000) { vane_position = 540 - TPS_range;}  // the 6.7 logs we have show the turbo jumping to positions when at WOT rather than stepping.
            else if (turbo_rpm <= 128000) { vane_position = 456 - TPS_range;}  // this will jump to a higher position at given rpms on the top end to slow the turbo down.
            else { vane_position = 373 - TPS_range; }  //it will jump a good bit to slow the turbo down if above 130000
        }                                              // according to holset the turbo is balanced to 130,000 rpm.  
        if (curveb){  //End pos of 16cm start 11cm
                 if (turbo_rpm <= 120000) { vane_position = 624 - TPS_range;}
            else if (turbo_rpm <= 128000) { vane_position = 540 - TPS_range;} 
            else { vane_position = 456 - TPS_range; }  //16cm
        }
        if (curvec){  //End pos of 14cm 456 start 10cm
                 if (turbo_rpm <= 120000) { vane_position = 685 - TPS_range;}
            else if (turbo_rpm <= 128000) { vane_position = 624 - TPS_range;} 
            else { vane_position = 540 - TPS_range; }   //14cm
        }

        // Overrun protection
      if (turbo_rpm > 140000){  // 140,000 rpms is where I get worried about shaft speed.  
        if (!curvea) {vane_position -= one_cm;} 
        //this will creep the vane position more open each code cycle if turbo rpms are above 135,000 if not in curvea ( perf mode defined by "F_watchpot" tab) 
          
     }
   }
}  
/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////////Watches for the pot position when pot switch is off to see what turbo curve is selected//////////////////////////////////////////
///////////////////////////////copying an array takes some time so I only check for this ever 900ms and I only copy the array if the last array doesn't match//
void Watchpotcrv() {
     
if (!eb_mode && !pot_mode) {
  if (PotentiometerValue > 960) { curvea = true; curvemode = 3; } else {curvea = false;}
  if (PotentiometerValue > 40 && PotentiometerValue < 960){  curveb = true; curvemode = 2; } else {curveb = false;}
  if (PotentiometerValue < 40){ curvec = true; curvemode = 1; } else {curvec = false;}
   
  if (curvemode != lastcurvemode){  //here is where I check to ensure that I only copy the array when needed, not every time
    
    if (curvea) {memcpy(turbo_curve,turbo_curve_1,sizeof(turbo_curve)); BoostMapMode = 'P';}
    if (curveb) {memcpy(turbo_curve,turbo_curve_2,sizeof(turbo_curve)); BoostMapMode = 'D';}
    if (curvec) {memcpy(turbo_curve,turbo_curve_3,sizeof(turbo_curve)); BoostMapMode = 'T';}
    lastcurvemode = curvemode;  //if curve mode has changed this is where I set the last mode so I can check the next time.
    String MapMode = String(BoostMapMode);  //printing this only when I need to saves time.
    lcd.setCursor(19, 3);
    lcd.print(MapMode);
  }
 }
}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

/////////////////////////////EB Manage////////////////////////////////////////
//Manages the apply of the EB
void EBManage() {
  EBModeSense = true;  //this is the one time event that happens if eb is active so I know when to print blank spaces to "delete" the lcd print below when done
  int MaxEBPressure = 45; //set desired max EB Drive Pressure
  int Difference =  (ExhaustPressure - MaxEBPressure); //set a buffer make sure max ex press doesn't get hit.

  vane_position -= max(Difference, -7);              //This way it doesn't close the veins to fast
  vane_position = constrain(vane_position, 800, 1000);
  lcd.setCursor(9, 0);  // I only print this if in eb mode to save time.
  lcd.print("!EB Active!");

}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *
 *  This work is licensed under the
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////Pot Manage////////////////////////////////////////
void PotManage() {
  PotModeSense = true; 
  if (PotentiometerValue > 990) {  //if you have the pot set to full open or above 990 out of possible 1023 of the pot, it will lock the vanes at wide open.
    vane_position = 30; // position is set to 30 or 25cm^2
    lcd.setCursor(9, 0);
    lcd.print("!TurboOpen!");
  }

  else if ( ThrottlePosition >= 25 ) {  //if throttle input increases above %25 then kick out of pot mode.  Set this above your cruising throttle position.

    PosManage ();
  }

  else  {
    vane_position = constrain(map(PotentiometerValue, 0, 1000, 1000, 00), 20, 970);
    lcd.setCursor(9, 0);
    lcd.print("!PotActive!");
  }
}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////Vein Position send////////////////////////////////

void set_turbo_position() {
    final_vane_position = vane_position;
  if (!AntiBark){ //antibark is set when turbo rpms are above bark rpms
   if(turbo_rpm > curve_rpm[0]){ //this allows for the vanes to snap from idle position to lowested when tps is sensed.
    if(!startcycle) {      //disregards the smoothing function below when setup is running to allow for a full sweep of the vanes for cleaning.
     if(!eb_mode && !pot_mode) {  //disregards the smoothing if in EB mode or Pot mode.
      if(turbo_rpm < lit_rpm){ //above lit rpm there is no smoothing in effect
      
            constrain(vane_position, min_position, max_position);
               // Vane smoothing between large values
             if (vane_position >= last_vane_position + 20 && last_vane_position < max_position - 10) { //controls getting smaller
                final_vane_position = last_vane_position + 10;
              } else if (vane_position <= last_vane_position - 20 && last_vane_position > min_position + 10) { //controls getting bigger
                final_vane_position = last_vane_position - 10;
              } else if (vane_position - 10 >= last_vane_position || vane_position + 10 <= last_vane_position) {
                if (vane_position > last_vane_position + 2 && last_vane_position < max_position - 2) {
                  final_vane_position = last_vane_position + 2;
                } else if (vane_position < last_vane_position - 2 && last_vane_position > min_position + 2) {
                  final_vane_position = last_vane_position - 2;
                }
              }
             }
            }   
          }
        }
      }
   
// Function to Send the Calculated Position to the Turbo
  //void SendTurboPos(){
  last_vane_position =  final_vane_position;
  byte lo_byte = lowByte(final_vane_position);
  byte hi_byte = highByte(final_vane_position);
  byte data[] = { lo_byte, hi_byte, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // data message with an added counter
  // data[2] = 0x02 for recalibrating gearbox
  // Load message and send
  CAN1.send(0x0CFFC600, extID, 8, data);
 }

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////LCD///////////////////////////////////////////////
void UpdateLCD() {
  
  VanePos = constrain(map(final_vane_position,960,40,3,25), 3, 25);  //this maps the vane position to a readable value 3cm-25cm based on the 40-960 code value.
  String TurboPos = String(String(VanePos, DEC) + " ");
  
  String output = "";
  String extra = "";
  
  float DrivePressRatio = ((ExhaustPressure * 1.00) / (BoostPressure*1.00));  //create boost to drive
  DrivePressRatio = constrain(DrivePressRatio, 0, 2.99);  //holds the d2b ratio from 0-2.99
  
  String Boost = String(String(BoostPressure, DEC) + ' ');
  String Drive = String(String(ExhaustPressure, DEC) + ' ');
  //String Throttle = String(ThrottlePosition, DEC);  //for testing you will need to calibrate your tps using a live data tool when you start


  
  // Addes extra spaces infront of turbo_rpm to keep things aligned
  if (turbo_rpm < 1000) { extra = "    "; } else if (turbo_rpm < 10000) { extra = "   "; } else if (turbo_rpm < 100000) { extra = "  "; } else if (turbo_rpm < 1000000) { extra = " "; }
  output += extra + turbo_rpm; 
  
  ///Print all dynamic things to lcd
  lcd.setCursor(0,1);
  lcd.print(output);  // print turbo rpm
  lcd.setCursor(6, 2);
  lcd.print(Boost);  //print boost 
  lcd.setCursor(16, 2);
  lcd.print(Drive);  //Print Drive
  if (BoostPressure <= 0) {   // if boost pressure is 0 then print empty value into d2b ratio section (can't divide by zero so get null output from string above) 
    lcd.setCursor(11, 3);
    lcd.print("1.00");
  } else{
    lcd.setCursor(11, 3);
    lcd.print(DrivePressRatio);
  }
    lcd.setCursor(6,0);
    lcd.print(TurboPos);
  if (PotModeSense && !pot_mode){  ///If pot mode is active potmodesense = true.  So this code will only run one time after pot mode is active, then released
    lcd.setCursor(9,0);
    lcd.print("           ");
    PotModeSense = false;
  }  
  if (EBModeSense && !eb_mode){
    lcd.setCursor(9,0);
    lcd.print("           ");
    EBModeSense = false;
  }
}

/*  This code is put in place to control an HE351ve turbo using Turbo RPM and other inputs.
 *   
 *  Sections of this code, including but not limited to the rpm based vane position calculations, Freq Measure, and 
 *  Timer setup are thanks to Curtis R Hacker at lilbb.com and his RPM based HE351vgt arduino shield.
 *  
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */

////////////////////////////Keep Time/////////////////////////////////////////
void keep_time() {  //this is the timer section that controls how often I do the none critical things.
  timer++;
  adc_roll_over++;
// Read Sensors
  // Update last_turbo_rpm every 10ms
  if (timer % 10 == 0 ) {   
    last_turbo_rpm = turbo_rpm; 
    }
  // There functions will need to be calibrated to the sensor.
  if (adc_roll_over == 1) { BoostPressure = ReadBoostPressure(); }
  if (adc_roll_over == 2) { ExhaustPressure = ReadExhaustPressure(); }   
  if (adc_roll_over == 3) { PotentiometerValue = ReadPotentiometer(); }
  if (adc_roll_over == 4) { ThrottlePosition = ReadThrottlePosition(); }
  if (adc_roll_over == 5) { adc_roll_over = 0; }  //this section makes sure I read each sensor once every round.  It will count from 0 to 5 then reset and repeat.


  
    
  //update lcd every 500 millis 
  if (timer % 600) { UpdateLCD(); }  //this is the one that takes the longest to complete so I only run it 2 times per second.
  
  //update serial every 300 ms  
  //if (timer % 300) { serial_output(); } //this is for testing to enable serial output if need be.
  
  //  watch for Eb or Pot apply every 600 millis
  if (timer % 500) { calculate_modes(); }  //none critical function as 1/2 second delay on eb switch doesn't matter.
   
  // Update vane_position every 10ms 100k+ / 25ms 60k - 100k / 100ms 0 - 60k  this section teels when to run through the posmanage and calc vane position
     // Update vane_position every 10ms 100k+ / 25ms 60k - 100k / 50ms 0 - 60k
       if (timer % 10 == 0 && turbo_rpm > lit_rpm) { update_vane_position = true; }//accel_factor = 10.0;}
  else if (turbo_rpm > curve_rpm[4] && timer % 25 == 0) { update_vane_position = true; }//accel_factor = 25.0; }
  else if (timer % 50 == 0) { update_vane_position = true; }//accel_factor = 50.0;}
  // Update turbo_accel before calculating vane_position
 // if (update_vane_position) {
 //   turbo_accel = ((turbo_rpm / 60000.0) - (last_turbo_rpm / 60000.0)) * accel_factor;
 //   last_turbo_rpm = turbo_rpm;
 //  }
    
  // Calculate vane_position
  if (update_vane_position && !eb_mode && !pot_mode) { update_vane_position = false; PosManage(); }  
  
  
  //Checks to see what turbo curve postion is select on the pot
  if (timer % 900) { Watchpotcrv();}
  
  if (timer == 1000) { timer = 0; }
 }

/*
 *  Copyright (c) 2014-2015, Curtis R Hacker
 *  All rights reserved.
 * 
 *  This work is licensed under the 
 *  Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
 *  To view a copy of this license,
 *  visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
 */
/////////////////////////////////this is put into place to test the code and verify code.  It is disabled by default.

void serial_output() {
  if (turbo_rpm > minimum_turbo_rpm) {
    String output = "";
    String extra = "";
    byte current_mode = 2;
    if (idle_mode) { current_mode = 0; }
    if (idle_walkdown_mode) { current_mode = 1; }
    // Addes extra spaces infront of position to keep things aligned
    if (vane_position < 10) { extra = "  "; } else if (vane_position < 100) { extra = " "; }
    output += "CPOS : " + extra + vane_position + " | ";
    extra = "";
    if (final_vane_position < 10) { extra = "  "; } else if (final_vane_position < 100) { extra = " "; }
    output += "APOS : " + extra + final_vane_position + " | RPM : ";
    extra = "";
    // Addes extra spaces infront of turbo_rpm to keep things aligned
    if (turbo_rpm < 1000) { extra = "   "; } else if (turbo_rpm < 10000) { extra = "  "; } else if (turbo_rpm < 100000) { extra = " "; }
    output += extra + turbo_rpm + " | ";
    Serial.println(output);
  }
    if (millis_out) {
    Serial.print(time_elapsed1);
    Serial.print(" ms |loop()");
    Serial.print(" || " );
    }
}
 

Update - 3/4/15

Updated to include the changes for managing the EB apply, and the boostmap array issue.  The above bench test well.
 
Update 2/23/15
Thanks to cowboy I have a better method to print data to the serial lcd screen.  I am using a 20x4 currently.  you will need the i2c lcd library to make the above work.  There is a message if the eb is applied or if the pot switch is active.
 
Update 3/4/15
I have changed the way that I am trying to manage the DP while just driving.  Below 30psi boost the veins are controlled by the boost map.  This might have Drive to boost ratio of 2:1 ( haven't real world tested yet)  however about 30psi boost I am switching over to a manage program that will try and keep Drive pressure at 50psi.  The hope is, again not real world tested yet, that once 30 psi of boost is reached the manage loop will try and hold the veins at a position that keeps drive pressure at your defined max while the boost level catches up thus lowering the ratio when coming to the top of the turbos useable map.  The DPmanage vein position limits are 650 lower and 970 top.  650 matches the 29.5 position for the boost map so there shouldn't be any jumping when switching between the two.
 
Update 3/6/15
I have removed the TPS % display on the lcd screen as I use my quad for that and I have added a Drive Pressure to Boost reference
"DtoB Ratio 1.5:1" etc
 
update 3/9/15
I have changed the Drive to boost ratio to actually work.  I forgot to make it float and times by 1.00 to apply the decimal points needed.
 
Update 5/23/15
I have constrained the boost and drive pressure values to 0-100 values to not have negative values.  I have also doubled the lcdupdate time to help make the lcd screen more readable.
 
update 5/26/15
 
i have updated the read sensor section to read at least twice and average the readings.  I am reading exhaust sensor 5 times and averaging.  I might increase the reads to get more accurate readings.  Exhaust sensor jumps around somewhat,  Not terrible but not great.   I have also added a Boost reference so I can constrain the values I am looking at for the exhaust pressure averaging.  In order for the exhaustpressure to be valid it has to be > boost pressure since it is technically impossible to have a drive pressure lower than boost pressure.
 
Update 5/27/15
I have worked through the reading of the exhaust and boost pressure reads to build an array of values and average the value to give a more accurate reading and to help keep rouge readings from giving bad reads.
 
Update 6/15/15
Thanks to Hakcenter at http://www.lilbb.com/ the code now has a timer in place to manage the sensor reads once every 400ms rather than reading them all at once like before.  Code seems good, update is a little slower, but I am not sure if it will be an issue yet.   I will be doing some testing and editing if needed.  Hakcenter also has some code and shield to control the he351ve using the speed sensor.
 
Update 6/22/15
 
I have made some small changes to help improve the code.  Biggest thing is the addition of 3 boost maps.  You can select from performance / normal / mileage maps with the pot when you don't have the pot select switch active ( in my case I have a push pull and pot together on one switch so the manual control requires pulling the pot switch then adjusting position.   0-25 on the pot is performance 25-970 is normal and 970-1000 is mileage.
 
Update 6/23/15
 
After a couple days with the truck I have edited the boostmaps some.  I have added a lcd indicator to show what boost map you are in.  E= economy starts at 400 position or about 12 cm^2 D= drive mode starts at 235 or about 8 cm^2 and P=performance starts at 155 or about 6cm^2.  P mode needs to be tuned more for my truck, but that pretty much ensures that there is always boost.  Not the best to run as it pushes the turbo hard, but might prove helpful for emissions and so forth to keep smoke down.  
 
All 3 modes stay within the boostmap until 30 psi then jump to drive manage to try and keep drive pressure at the defined limit ( 50 psi in my case).
 
Currently VERY happy with the turbo.  I have some fuel issues that I am working on getting sorted, but I once the turbo lights it cleans up the smoke %100 all the way to 40+psi.  Egts with the quad off don't top 1200*F and with the quad set all the way up got to 1500*f I can dial in the tune some to get that a little lower, but I am not worried.

6/24/15

I have adjusted the boostmap WAY up as the 235 ( 7-8cm) starting position was way to small. There is WAY less smoke and better spool starting around 300 ( 9-10cm) .

 

7/14/15

 

Thanks to HakCenter lilbb.com I have moved my code over to RPM based turbo calc.  I have merged his lilbb 1.1 and my/cowboys boostmap code.  The control of the turbo works better using RPMS.  It is less jumpy, less smoke, no barking, more refined.  Pretty happy so far.  I have to clean some stuff up in the code, but over all working well.

 

7/15/15

 

Made some changes to the Posmanage section.  The lilbb.com code doesn't take into account throttleposition ( 12v guy) so he was using turbo rpms to try and qualify idle state.  While is does work good if you aren't watching throttle position it also means that you have to guess what is idle and what is not and sometimes there is times when you aren't truly at idle but the code thinks you are and you are left with the turbo open rather large, when it shouldn't be.  again it works pretty good if you aren't watching throttle.

 

( little more detail on the "issue")

In order to qualify none idle turbo rpms would have come up to past curve[1].  This means that when starting from a stop the turbo position would be at about 14cm ( idle position) then it would slowly shrink down to the curve position.  I was looking to have the turbo jump from idle state right to starting position as soon as you give it throttle.  

 

Cummins/dodge has a idle position of around 14cm also, but as soon as you tap the throttle the turbo veins snap down to ~5cm then open up slowly to 9ish cm then on to the large positions as needed.  This is to help "snap" the turbo speed up coming from a stop to clean smoke up.  

 

Hench why I am trying to emulate that.   

 

Update 7/25/15

 

Well a lot of changes are put into place.  I did figure out that the LCD screen is taking a ton of time to run through, which is throwing off the RPM read each time the lcd updates ( 500 millis).  Not a huge issue since we are averaging the turbo speed over 32 reads.  

 

I have also added some top end stuff to prevent barking when letting off the throttle.   I have also added a Position "bump" when over %45 throttle and %70 half cm at 45 and above and a full CM above %70 throttle.  This will only occur when above the curve rpm [4].  

 

What I found in my testing is

 

- With 100 hp injectors with no tuner I am able to keep the turbo position at about 12cm^2 to keep the turbo shaft speed in check below 130,000.

- With 100 hp injectors and canbus fueling (165hp total) Turbo position needs to be at 14cm^2 to prevent the shaft speed 130,000

- Wtih 100hp injectors, and canbus fuel and wiretap (100+65+115) Turbo position 18cm^2 to prevent the shaft speed 130,000.

 

that is how I am figuring everything out curve wise.  

 

The top end controls now try to keep turbo rpms between 120k and 127k vane position will move more as rpm are further away from the goals.

 

Update 8/11/15

 

some changes to better comment everything.  I have also went back to the top end controls setting a position rather than trying to increase and decrease to keep rpms at a certain speed.  Unsure if I will keep that or not. 

 

I have also cleaned up / sped up some of the lcd stuff.  I removed the bar graph section.  Even though it was nice to look at it was throwing off the turbo shaft speed reads.  In the end it wasn't worth running.  This allows me to print less to the lcd screen.

 

Update 8/20/15

 

I have adjusted the curves some.  I have also added a new section to the TPS sense that will reduce the vane position if you are at low/mid/midhigh/high but low boost to help spool the turbo.  This is to help with reducing smoke when going from cruise to high throttle.

IE:   You can see that if tps_midlow is true ( between %25 and %45 tps) and bosot is below 5psi the housing will close by 40 which is roughly equal to one cm.  If tps is midlow and boost is less than 10 then shrink housing by half cm.  

 

you can see below that I move the shrink/opening more as tps goes up to go along with the amount of fuel.

// TPS_range calc process
     if (ThrottlePosition <= 25) {TPS_low = true;} else {TPS_low = false;}
     if (ThrottlePosition <= 45 && ThrottlePosition > 25) {TPS_midlow = true;} else {TPS_midlow = false;} //{TPS_range = 0;}// watches throttle input to increase vane position.  Vane position mapping is based on low throttle input. 
     if (ThrottlePosition <= 70 && ThrottlePosition > 45) {TPS_mid = true;} else {TPS_mid = false;} //{TPS_range = 20;}
     if (ThrottlePosition > 70)  {TPS_high = true;} else {TPS_high = false;} //{TPS_range = 40;}

     if (TPS_low) {TPS_range = 0;} //supports low throttle cruise. if under %25 don't change vanes
     if (TPS_midlow){
      if ( BoostPressure < 5) {TPS_range = -40;} //it will try and spool the turbo if tps is 25><45 - numbers decrease vane size
      else if ( BoostPressure < 10) {TPS_range = -20;}
      else {TPS_range = 0;}
     }
     if (TPS_mid){
      if (BoostPressure < 10) {TPS_range =  -20;} 
      else if (BoostPressure < 20) {TPS_range = 0;}
      else {TPS_range = 20;}
     }
     if (TPS_high){
      if (BoostPressure < 20) {TPS_range = 0;}
      else if (BoostPressure < 30) {TPS_range = 20;}
      else {TPS_range = 40;}
     }

Edited by Me78569

  • Replies 746
  • Views 109.7k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • Finally broke down and bought the t3 to wgmt flange of the 351ve.  I should be getting this bolts up in the next couple weeks.  

  • Hi again, i just wanted to update the thread, i finally got around to finishing my controller and got everything working with the 1.11 version of code, the main problem i was experiencing previously w

  • Yes, I created that video.

Posted Images

Featured Replies

Just from the reference sheet the HX40 (possibly more with the HX Super 40) can flow between .53 Kg/sec to .54 Kg/sec which equates to 70-71 Lb/min of air flow.

  • Author

Yep the only maps I have seen were from the hx40 not the super 40.

From what the turbo calculator says a 6.7 Cummins at 500 ft of elevation running 35 PSI of boost out to 3400 RPM will require 85.2 Lb/min of airflow. This being said your turbo should be capable of this when all the parameters are set correctly. Your definitely on the right track.

What will hinder the turbos ability to yield these results is the restriction of the turbine and the housing. I have seen better fuel economy and reduced EGT with my Borg Warner 62/68/.80 than with the VGT due to the way the turbine side of the turbo flows. Geometry of the turbine wheel will dictate how it flows and responds along with the A/R ratio of the turbine housing.

Example the 68mm turbine wheel on my particular turbo has two configurations. The first is a flat blade or flat tip however you see it. The second being a J-Cup or a cupped tip blade. The flat tip is faster responding than the J-Cup, while the J-Cup flows better with a bit less response.

So in my case with a 14cm divided turbine housing and the flat tip turbine provide great response and good flow characteristics. If I wanted even faster response from the turbo a 12cm divided housing may be used but can become a restriction at higher RPM. The best way to mitigate this is to use the J-Cup turbine wheel with the 12cm turbine housing this will yield the fastest response and great flow.

I say all this to basically point out the point of restriction is the flow characteristics of the turbine housing with the vane position. So as we agreed earlier that the sweet spot is between 12cm and 14cm the turbo can be modulated from those positions to create the best overall outcome.

Keep up the good work and keep us posted.

A quick side note the HX40 and HX Super 40 shafts are notoriously weak but this has been addressed in the HE351VE.

  • Author

That map doesn't really make sense to me when compared to the specs in the other link.

 

850cfm is equal to what? 60ish lb/min?  are they spec'ing it within the highest efficiency island only?

 

But then the pressure ratio of 4.5 would mean the turbo was pushing nearly 50 psi?

 

 

Mass flow means what? it can't be lb/min can it? if so then it flows a bunch more than anyone thinks it does.  Everyone says the super will flow 70ish lb/min but that map shows it flowing nearly 90 lb/min.  Again doesn't make sense.  I just don't see the he351ve flowing 85 ln/min without blowing the compressor apart.

 

I am assuming that the top speed line on the map is ~130k? maybe?  

 

 

I really wish holset would just publish good maps haha.

 

Maybe I am reading it wrong?

That map doesn't really make sense to me when compared to the specs in the other link.

850cfm is equal to what? 60ish lb/min? are they spec'ing it within the highest efficiency island only?

But then the pressure ratio of 4.5 would mean the turbo was pushing nearly 50 psi?

Mass flow means what? it can't be lb/min can it? if so then it flows a bunch more than anyone thinks it does. Everyone says the super will flow 70ish lb/min but that map shows it flowing nearly 90 lb/min. Again doesn't make sense. I just don't see the he351ve flowing 85 ln/min without blowing the compressor apart.

I am assuming that the top speed line on the map is ~130k? maybe?

I really wish holset would just publish good maps haha.

Maybe I am reading it wrong?

Pressure Ratio changes with air density so at higher altitude it is different than sea level.

Also it states over 850 CFM but does not include an exact figure. The bottom portion of the map is Lb/min of airflow which is directly in line to the calculated value for the 6.7 Cummins at 500 feet pushing 35 PSI of boost while turning 3400 RPM.

There are no official efficiency percentages or islands on the map. From my understanding is as long as you remain in the area on the map you should be at worst case 65% efficient.

Yes the top speed seems to be 130,000 RPM on the HX Super 40. I do not have an official speed for the HE351VE. The HE351CW would be the closest to compare with because they share turbine wheels from my understanding but the compressor housing and wheel I do believe are different. (HE351VE compressor = HX Super 40 VS HE351CW compressor = HX40.

  • Author

so according to that map then the he351 flows nearly 90lb/min then right? even though it would be at %65 efficient and turbo speeds of 130k ( assuming that is the top line)

 

That's way beyond the 69 lb/min most spec the super hx40 at.   Just doesn't make sense, but I guess if holset says mass flow is lb/min then the map says nearly 90 lb/min.

 

Humm. 

so according to that map then the he351 flows nearly 90lb/min then right? even though it would be at %65 efficient and turbo speeds of 130k ( assuming that is the top line)

That's way beyond the 69 lb/min most spec the super hx40 at. Just doesn't make sense, but I guess if holset says mass flow is lb/min then the map says nearly 90 lb/min.

Humm.

The line is deceptive but I do believe 85-87 Lb/min is the capability of flow from the turbo.

The HX Super 40 is that high. The HE351VE uses that compressor I'm almost 95% certain. My data sheet shows .54 but only on the HX40 the HX Super 40 has a different compressor wheel and housing.

Yes I do believe the maximum capacity is 85-87 Lb/min at a maximum boost near 40 PSI with a 65% efficiency when achieving those numbers. That is like you said on the far tail end on the far right of the compressor map.

Edited by Vais01

Completely off topic but can you walk me through the picture posting process for my BHAF thread?

That's my thought as well, but he's been working on this for months so I'm sure he's got it figured out much better then I do.

 

I always thought that having a EGT gauge post turbo would be the best way to find the correct vain position while cruising.  To much drive pressure, and they get hotter, to little boost and they get hotter.

 

I just realized this is not true, this would rule out the drive pressure adding "artificial" heat to the exhaust, however with DP comes Boost.  So if you have the same amount of heat, with more boost (flow) there is overall more heat energy going into the exhaust.  

 

I went on a trip here this weekend, and found two interesting facts.  

 

1st, it is crazy easy to hit 1.4:1 Boost:DP with the stock turbo, just lug the crap out of it at 1200 RPM:ashamed:   Otherwise boost is about 1:1.1 throughout the RPM range/load.

2nd, the IC works crazy well, engine input temps going down the highway are maybe a couple *F above ambient, while the pre-intercooler temps are steady at 170-200*F.

I just realized this is not true, this would rule out the drive pressure adding "artificial" heat to the exhaust, however with DP comes Boost. So if you have the same amount of heat, with more boost (flow) there is overall more heat energy going into the exhaust.

I went on a trip here this weekend, and found two interesting facts.

1st, it is crazy easy to hit 1.4:1 Boost:DP with the stock turbo, just lug the crap out of it at 1200 RPM. :ashamed: Otherwise boost is about 1:1.1 throughout the RPM range/load.

2nd, the IC works crazy well, engine input temps going down the highway are maybe a couple *F above ambient, while the pre-intercooler temps are steady at 170-200*F.

Drive pressure cam be as high as 2.0:1 without hurting the HE351VE. Holset does state 1.5:1 as safe. Also the HX35W 12cm turbine housing wastegate only controls 1 of the 2 volutes so if you measure drive pressure on the rear volute the pressure will seem normal while the front volute will be over 1.1:1 when the wastegate opens.

This is another reason the HY35W was used on the auto transmission trucks because the wastegate is nearly always open and the turbine housing is a single volute.

When I say 1.4:1, I meant 10 psi boost, 6 psi drive pressure.  I read the pressure from the front runner.  The wastegate on mine doesn't start to open until exactly 35 psi, or 33 psi at the intake plenum.

When I say 1.4:1, I meant 10 psi boost, 6 psi drive pressure. I read the pressure from the front runner.

That makes a small difference haha.

  • Author

Is 10 psi boost with 6psi drive even possible?   

Is 10 psi boost with 6psi drive even possible?

It could be if cruising on the interstate.

  • Author

Humm interesting I suppose the effective leverage arm of the turbine is different compared to the compressor. 

Humm interesting I suppose the effective leverage arm of the turbine is different compared to the compressor.

That is correct. The A/R ratio determines the exhaust flow velocity through the volute which acts against the turbine wheel. The turbine wheel then becomes the point of restriction for a brief period until the shaft speeds up and begins creating boost.

After that the drive pressure rises incrementally according to boost pressure. On a VGT you can alter the A/R ratio thus producing boost at low speed and high speed without the unnecessary high drive pressure.

That is correct. The A/R ratio determines the exhaust flow velocity through the volute which acts against the turbine wheel. The turbine wheel then becomes the point of restriction for a brief period until the shaft speeds up and begins creating boost.

After that the drive pressure rises incrementally according to boost pressure. On a VGT you can alter the A/R ratio thus producing boost at low speed and high speed without the unnecessary high drive pressure.

This is while lugging it at 1200 rpm.  The explanation is simple.  The turbine runs off exhaust volume, heat is artificial exhaust volume,  if you have enough heat, the turbine will get enough energy out of the exhaust to drive the compressor without the need of as much back pressure.

 

Turbos have the possibility of running more boost then drive pressure easily.  The problem is we want quick spooling and high flowing... so the turbine is setup for the higher RRM's while the housing is sized for the lower RPMs.  I was looking at some dyno logs earlier, a 2000+ hp engine was making 90 psi of boost on a single turbo with 70 psi of drive pressure, EGT's were sub 1200 (I'm sure they had plenty of water injection).

This is while lugging it at 1200 rpm. The explanation is simple. The turbine runs off exhaust volume, heat is artificial exhaust volume, if you have enough heat, the turbine will get enough energy out of the exhaust to drive the compressor without the need of as much back pressure.

Turbos have the possibility of running more boost then drive pressure easily. The problem is we want quick spooling and high flowing... so the turbine is setup for the higher RRM's while the housing is sized for the lower RPMs. I was looking at some dyno logs earlier, a 2000+ hp engine was making 90 psi of boost on a single turbo with 70 psi of drive pressure, EGT's were sub 1200 (I'm sure they had plenty of water injection).

Heat is the driving force of a turbo. On a diesel the exhaust volume is high but our exhaust gas temps are low when compared to a gasoline powered vehicle.

Now on the topic of heat. The OE cast iron manifold retains heat very well but heat is also rejected through the manifold through conduction of the hot exhaust gas then convection of the heat that the manifold has absorbed. So the easy cheap way to address this is to use a heavier(thicker walled) exhaust manifold from an RV or an industrial application. The other is the use of 304 stainless steel which in its nature has a high tolerance to the heat within it. Stainless steel also reflects heat that is within the manifold and increases the driving force on the turbo. This is a marginal difference but every last bit helps.

To answer the 2000 hp engine heat explanation. Water methanol injection is common for those engines.

Did This Forum Post Help You?

Show the author some love by liking their post!

Welcome To Mopar1973Man.Com LLC

We are privately owned, with access to a professional Diesel Mechanic, who can provide additional support for Dodge Ram Cummins Diesel vehicles. Many detailed information is FREE and available to read. However, in order to interact directly with our Diesel Mechanic, Michael, by phone, via zoom, or as the web-based option, Subscription Plans are offered that will enable these and other features.  Go to the Subscription Page and Select a desired plan. At any time you wish to cancel the Subscription, click Subscription Page, select the 'Cancel' button, and it will be canceled. For your convenience, all subscriptions are on auto-renewal.