Jump to content
Me78569

He351ve stand alone Arduino controller code for 2nd Gen Cummins

Recommended Posts

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

Share this post


Link to post
Share on other sites

Funny you should post this, I was just thinking last week about getting a holset vgt turbo to possibly put on my truck if I could work out some sort of controller using adruino, I only got as far as wrighting down ideas on paper though.

Following to see how you get along.

Share this post


Link to post
Share on other sites

I should be getting the new shield today or tomorrow. 

 

 

I have 4 different pots to simulate on my desk for boost vs exhuast and throttle. 

 

 

My c coding skillings are VERY dusty so it is a lot of trial and error.

Share this post


Link to post
Share on other sites

This is awesome! I have allot of the parts needed for my swap to do this except some small ends and pieces like a controller. Why are you doing this instead of the banshee or fleece?

I have no idea what all the code means nor would i even begin to know how to write it..

Will the end result be comparable to the fleece or banshee? Except probably cost a fraction compared to theirs?

Share this post


Link to post
Share on other sites

The arduino and canbus are ~$90

 

for a few hundred you can have pretty much the same thing as fleece or banshee, but you can tune it to your own liking.   I can tune for cruising throttle input for my truck and driving style etc etc etc. 

 

HOWEVER if you don't care to learn the code, or at least the basics of it I am not sure I would venture down this road. 

Share this post


Link to post
Share on other sites

Alright here is an updated section of the above code dealing with how to define vein position based upon switch positons etc.

 

Any thoughts on this?  Again my C+ skills are dusty, but I am getting better.  Items after // are my notes

 

If I'm looking at it right, this should give the same output.

 

 
    if ( SwitchPosition == HIGH && EBSwitchPosition == HIGH) 
      DesiredPosition = BoostVeinPosCalc( BoostPressure); //set vein position based on boostmap
 
    else if ( ThrottlePosition < 300 && SwitchPosition != HIGH && EBSwitchPosition == HIGH)  
      DesiredPosition = PotentiometerValue; //vein position is pot value
 
    else if (EBSwitchPosition != HIGH && ThrottlePosition < 50 )  
      DesiredPosition = EBpos; //If below %5 then engage Exhaust brake "ebpos = 140" from above
 
    else 
     DesiredPosition = BoostVeinPosCalc( BoostPressure); //set vein position based on boostmap

    // Set the Turbo Position
    SendTurboPosition( DesiredPosition );
 
    // Delay for Processor
    delay(2);
 

 

I'm in the market for a he351ve as well,  I'm really cheap though, so you'll probably have yours done before I find one lol.

 

Also, how were you planning on reading the exhaust gas temperature?

  • Like 1

Share this post


Link to post
Share on other sites

HUGE thanks there man.  I was working through the logic in my mind, but I wasn't sure.  that so sooooo much cleaner.

 

 

I am reading egts to my quad and not to this.  I will use any backdowns needed on the quad, but the boost map is generated from drive pressure and boost pressure.

 

I got my 351 for 500 shipped with 4000 miles on it.

 

Its sitting right next to me as I am testing.

 

 

 

As for a super cheap 351, I talked with destroked out of denver and they typically have vgts they sell as cores.  the last one they had was only $100 but it was REALLY chewed up.

Share this post


Link to post
Share on other sites

I was looking over my notes/ideas that I had wrote down and there are 2 things that I thought I would bring up.

 

First have you thought about using the turbo shaft speed sensor at all? It would be great to use as a safety to prevent any over speeding of the turbo, and could also be used to smooth out vane movement.

 

Second comes from working on ISX's that have the he351ve's big brothers on them, the he451ve and he551ve, when you use the engine brake on a ISX with the electronic VGT you have 3 settings, for the "low" and "mid" settings it just uses the compression release solenoids on the valve train, but for the "high" setting it also uses the turbo and gradualy closes the vanes based on engine load, RPM and various other parameters. That being said most standalone controllers I have seen for the he351ve snap the vanes all the way closed for a engine brake setting but I was thinking that it would be better to close the vanes off more gradually instead of just snapping them closed, maybe have a setting so the turbo doesn't exceed x amount of boost while in engine brake mode or something like that.

 

These are things I was planning to work out if I decide to get a he351ve and have a go at it so I though I would throw it out there as some food for thought.

Share this post


Link to post
Share on other sites

Good thoughts,

 

I have also added a else if to handle what happens if you have the pot switch enabled and hit the EB.  since my EB will be run off the brake pedal sense that would happen from time to time. 

 

I default to the pot in that case.

 

 

 

I was looking over my notes/ideas that I had wrote down and there are 2 things that I thought I would bring up.

 

First have you thought about using the turbo shaft speed sensor at all? It would be great to use as a safety to prevent any over speeding of the turbo, and could also be used to smooth out vane movement.

 

Second comes from working on ISX's that have the he351ve's big brothers on them, the he451ve and he551ve, when you use the engine brake on a ISX with the electronic VGT you have 3 settings, for the "low" and "mid" settings it just uses the compression release solenoids on the valve train, but for the "high" setting it also uses the turbo and gradualy closes the vanes based on engine load, RPM and various other parameters. That being said most standalone controllers I have seen for the he351ve snap the vanes all the way closed for a engine brake setting but I was thinking that it would be better to close the vanes off more gradually instead of just snapping them closed, maybe have a setting so the turbo doesn't exceed x amount of boost while in engine brake mode or something like that.

 

These are things I was planning to work out if I decide to get a he351ve and have a go at it so I though I would throw it out there as some food for thought.

 

 

I have a bit of code from Bdubb'z on the cummins forum in the attempt to read the speed sensor, but I haven't gotten it put into place yet.  I have every intention to as it should be pretty easy to watch for overspin and open up the veins some.  Desiresposition = Desiredposition + 50; or something similar.

 

bdubb'z also has some code to handle the to muhc backpressure issue.  I have it stored, but again have not put it into place in my code  yet.  Once this is done it will allow me to define a max back pressure and open the veins if that pressure is reached.    This will work well for both the EB functions and at high boost.

 

I haven't thought of staging the EB yet, I suppose if the need is there we can figure it out.

 

If case you want to look at Bdubb'z code here it is.  He has done a TON of work in regards to this.  I can't thank him enough

Share this post


Link to post
Share on other sites

I like the idea of not slamming the EB on.  And then regulating it to not get to much back pressure.  Something simple along these line should do it.

 

 
loop(){
if(EBActive) EBManage();
}
 
void EBManage(){
 
if (DrivePressure <= 40) desiredVainPosition -= 5;
else if (Drivepressure <= 60) desiredVainPosition--;
else if (Drivepressure >= 60) desiredVainPosition++;

desiredVainPosition = constrain(desiredVainPosition, lowLimit, highLimit);
}
 

Share this post


Link to post
Share on other sites

Cowboy,

 

can you explain what -- and ++ mean? 

 

I tried to look it up but I couldn't find anything.

 

 

 

First post updated with my current code.  It applies the EB manage.

Share this post


Link to post
Share on other sites

Val++ is the same as Val += 1 which is the same as Val = Val + 1.

 

Val-- is the same as Val -= 1 which is the same as Val = Val - 1.

 

When programming the arduino, I normally keep this page open lol.

http://arduino.cc/en/reference/homePage

 

Also, the lowLimit and highLimit stuff, was for the veins,  like if you can only send 0 to 255 through the can buss.  then you want to constrain it between those values.  As in, you don't want to set desiredVainPosition to -1 or 256.

Share this post


Link to post
Share on other sites

I was just looking through the thread over on cummins forum and saw where BDubb'z had hooked the turbo speed sensor up to the arduino but did not get it to work,  looking at the code he has for it I think it may be because he has the input for it in pin 2(digital) when it would need to be in one of the analog input pins instead.

Share this post


Link to post
Share on other sites

Yea I seen that also, but I wasn't gonna mess with it until the rest of my setup was working somewhat smooth.

 

Harness is built no wI just have to attach my pots for each pressure sensor to bench test it fully.

 

thanks for the lesson cowboy.  I was looking for that page but never could find it.

Share this post


Link to post
Share on other sites

Neat. Smart guy stuff here.

Share this post


Link to post
Share on other sites

I went through the code in the first post trying to find any bugs or potential issues.  While also trying to streamline it a little bit without making it to hard to understand.

 

To keep from cluttering this thread up, I attached it as a text document.  It's just the way I would set it up, don't feel obligated to use anything from it.

 

VGT Code.txt

  • Like 1

Share this post


Link to post
Share on other sites

I was just looking through the thread over on cummins forum and saw where BDubb'z had hooked the turbo speed sensor up to the arduino but did not get it to work,  looking at the code he has for it I think it may be because he has the input for it in pin 2(digital) when it would need to be in one of the analog input pins instead.

 

The reason for that is the turbo RPM sensor doesn't give out a variable voltage.  It is a Variable Reluctance sensor  so it puts out a voltage spike for every revolution.  So he's likely got a interrupt attached to that pin (which on the uno, you can only attach an interupt to digital pins 2 & 3), and so he counts how many pulses per second and does the math for RPM.

 

Edit,  I just checked out the CF thread, he doesn't say how it "wasn't working"  but I do see one issue.

 

volatile byte ShaftRevolutions = 0;

 

should be 

volatile unsigned int ShaftRevolutions = 0;

 

or

volatile unsigned long ShaftRevolutions = 0;

 

And then his RPM calculating would be a little more stable if he tried something like

 

RPM = ( 60000 / (CurrentTime / ShaftRevolutions) ); // Convert frequency to RPM, for one interrupt per full revolution

 
If my head is on straight, the math there should be about right.
 
Also, he's trying to Serial.print ShaftRevolutions  after setting it to 0.
  • Like 1

Share this post


Link to post
Share on other sites

Bench testing your EB manage section and it works really well.

 

Thanks again.  I feel bad you are writing my code for me lolololol.

Share this post


Link to post
Share on other sites

Double Edit:

 

spoke two soon, seems that I am only getting about half the movement in the veins when adjusting boost values up.

 

very odd.

Share this post


Link to post
Share on other sites

Double Edit:

 

spoke two soon, seems that I am only getting about half the movement in the veins when adjusting boost values up.

 

very odd.

 

You're adjusting the viens based on a 0-49 psi boost level, but have your pot mapped from 0-100 psi.  Would that cause the problem you're having?

 

Also, add this in the EBManage right below the first "if" but on top of the other "if else"

 

 

  else if (ExhaustPressure >= (MaxExhaustPressure + 10)) 
  DesiredPosition += ((ExhuastPressure - MaxExhaustPressure) * 5);//if Exhaust Pressure spikes, open the veins quick.

 

 

Another EDIT.

 

I'm happy to help,  I'll likely be going down this road shortly as well.

Share this post


Link to post
Share on other sites

I adjusted the boost map to read 0-100 with the different veins and I have the same results. 

 

Gonna dig into that in a bit.

 

 

 

Thoughts on this?    I haven't benchtested it yet, but I think it should work like I want.

    {
    if ( SwitchPosition == HIGH && EBSwitchPosition == HIGH)
      DesiredPosition = BoostVeinPosCalc( BoostPressure ); //set vein position based on boostmap
     
    else if ( ThrottlePosition < 300 && SwitchPosition != HIGH)
      DesiredPosition = PotentiometerValue; //vein position is pot value
 
    else if (EBSwitchPosition != HIGH && SwitchPosition == HIGH && ThrottlePosition < 15 )  
      EBManage ();//If below %1.5 then engage Exhaust brake and regulate the exhaust pressure.
           
    else DesiredPosition = BoostVeinPosCalc( BoostPressure );
    }
 
    // Set the Turbo Position
    SendTurboPosition( DesiredPosition );
 
    // Delay for Processor
    delay(2);
  }

 //Manages the apply of the EB
void EBManage(){
  
 
if (ExhaustPressure <= (MaxExhaustPressure - 10)) DesiredPosition -= 5;//these assume that the lower the number, the more restrictive the turbine housing is.

  else if (ExhaustPressure >= (MaxExhaustPressure + 10)) 
    DesiredPosition += ((ExhaustPressure - MaxExhaustPressure) * 5);//if Exhaust Pressure spikes, open the veins quick.

  else if (ExhaustPressure < MaxExhaustPressure) DesiredPosition--;  

  else if (ExhaustPressure > MaxExhaustPressure) DesiredPosition++;
    DesiredPosition = constrain(DesiredPosition, 140, 960);

}

Edit:

 

Benchtested the above code and it is doing what I want, other than the pot not working like the sensor would.

 

If you adjust tps it will kick you out of the eb loop and also the pot loop depending on what switches are on/off etc.

 

Calling it a night, I will tackel the pot issue later.

Share this post


Link to post
Share on other sites

Did you have to add this to get it to work?

 

if (ThrottlePosition > 15) loop(); //if throttle position is more than %1.5 then exit EBmanage

 
I'd have to see your code, but I didn't think it should be necessary.  Would you be able to attach your code to your post, for me to take a looky see?
 
Also, I don't want to mislead you, I am by no means good at programming.  Most my stuff is other peoples stuff spliced together.
If I say one thing, and Ed says another.  Screw me and listen to Ed lol.

 

 

Share this post


Link to post
Share on other sites

Odd,

 

Seems to be working today without that section added, I must have been tired last night.  The first post has my current code.

 

And yes ctrl c and crtl v are a rookie programmers best friend lol.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now




×