Jump to content
  • Welcome To Mopar1973Man.Com LLC

    We are a privately owned support forum for the Dodge Ram Cummins Diesels. All information is free to read for everyone. To interact or ask questions you must have a subscription plan to enable all other features beyond reading. Please go over to the Subscription Page and pick out a plan that fits you best. At any time you wish to cancel the subscription please go back over to the Subscription Page and hit the Cancel button and your subscription will be stopped. All subscriptions are auto-renewing. 

He351ve stand alone Arduino controller code for 2nd Gen Cummins


Recommended Posts

Had a thought that I am going to work on.  

 

I think I have been going at it wrong in terms of the ablilty to select multiple curves.   Right now I have 4 curves mpg, tow, dd, and perf.  These all have different vane position per the turbo shaft speed, but each of these curves is linear to each other.    so rather than using the pot to select a curve I think I am going to have pot define what I will call the fuel offset.

 

Since the turbo spools in the same manner regardless of fueling, IE slow to increase speed at x rpm vs slingshot at x rpm, the base curve will be configured in a manner than increases vane size in relation to RPM / turbo map, but the Fuel offset will define how much that curve is increased / decreased.   

 

This SHOULD make it useable on any application without changing the code, rather you define the fuel you are throwing at it via a knob and you are good to go.  

Link to comment
Share on other sites

The changes I made to curve select works really well.  

 

You effectively set the lowest power curve and adjust the pot in the cab for the fuel you have.  Way way down the road, I think I could have a "setup" feature.  You go out, set the turbo to WOT position manually, do a WOT run, if shaft speeds are lower than 130k you adjust the pot and repeat until you find the sweet spot for the end position for the turbo.  You could map the rest of the curve off of that pretty easy.

 

Anyways I am using 

SpeedOffset = map(turbo_rpm, 0, 140000, 1, 20);

to give a variable based on shaft speed that I can use to alter the turbo position.  A value of 40 is ~1cm

 

that plus

if (timer % 900) {FuelOffset = map(PotentiometerValue, 1000, 0 , 10, 1);} 

to define the pot value into a readable tubro positon,

 

Then to alter the curve I have this at the end of the Poscalc section

vane_position -= (FuelOffset * SpeedOffset); 

Effectively The Poscalc section defines x vane position at x shaft speed.  then after I have calc'd that position I then minus ( make turbo bigger) by the above 2 multipled by each other.  You could in theory give you full range of the turbo via the Pot.

 

 

Works pretty well from my limited testing so far.

Link to comment
Share on other sites

Nick, it is kinda funny, but this project you and cowboy have done is pretty good.  I've seen engineering studs put together far worse and get high marks on it.  All it would need is some theory and boom, you're an engineer!  

Link to comment
Share on other sites

Just now, CSM said:

Nick, it is kinda funny, but this project you and cowboy have done is pretty good.  I've seen engineering studs put together far worse and get high marks on it.  All it would need is some theory and boom, you're an engineer!  

Haha my thoughts exactly. A good friend of mine is in disbelief that the Ardrunio can control the turbo nozzle.

Link to comment
Share on other sites

An arduino is just a little simple microcontroller.  Turbos on the other hand, them things are black magic.

On a scale of 1-10, I did 0, Nick has taken this thing and ran with it which is awesome!

Great Job Nick!

picard_clapping.gif

 

Link to comment
Share on other sites

3 minutes ago, Cowboy said:

An arduino is just a little simple microcontroller.  Turbos on the other hand, them things are black magic.

On a scale of 1-10, I did 0, Nick has taken this thing and ran with it which is awesome!

Great Job Nick!

picard_clapping.gif

 

Agree. He's gone above and beyond.

Link to comment
Share on other sites

Well another snag.  

 

The reader I got supports 250k29b canbus but not j1939...... ugh.  so it is junk.  

 

Now I am looking to connect my OBD reader to the arduino and send AT commands to the PCM to read, RPM, IAT, ECT, TPS, and load.  I can use the computer to talk to the ecm Via terminal program, so I know it is possible to do.  

 

Working through the arduino code to send and receive AT commands using serial pins 0 + 1 on the arduino at the Baudrate 9600.  Not going as smooth as I would have hoped, but making progress.  

 

The key to all of this is we are able to communicate with the PCM via the ELM327 using AT commands

In short on the arduino / terminal

serial.print("atz"); tells us the 327 version

serial.print("atsp0") connects the 327

serial.print("0100"); returns a list of PID's that we can read / supported. 01 is the canbus mode, 00 is the command

serial.print("010c"); will return engine RPM in HEX via 2 bytes.  use rpm= ((values[0]*256)+values[1])/4 to convert to rpm. 

 

Anyways it is getting there, just have to get it all into the arduino and see if i can read data in a timely manner from the pcm.

Edited by Me78569
Link to comment
Share on other sites

Well some bad news.

 

I did get the ecm info ported into the arduino.  HOWEVER it takes FOREVER, to read the RPM value from the ecm takes 175 MS.  I know it doesn't seem like a lot but in terms of calculating Turbo shaft speed at 140,000 rpm that 140 ms might as well be 20 years.  

 

Not sure where to go from here.  I might test another method of talking with the elm327.  I need another set of eyes on this lolol.  

Link to comment
Share on other sites

Yes,

 but I really want to avoid having wires all over the engine bay waiting to get caught up in something or whatever.  Plus each Connection to a sensor takes another wire, plug, a pin on the arduino.  

 

If I can read 5 or 6 sensors from the OBD I can free up a ton of wire, and connections.

 

 

UGH, another update, my shaft speed RPM stopped working today.  time to chase wires.

Link to comment
Share on other sites

Worst case you could have a second arduino polling the OBD2 port and then have the info rip roaring ready to go for when the main arduino asks for it.  173 ms is forever, it takes me ~ 20ms to read about a dozen sensors and datalog it.  :hyper:   

 

And yes, a bunch of wires, connections and things that break are a pain.

Edited by Cowboy
Link to comment
Share on other sites

Yea, to ready my sensors takes 2ms when they are wired to the arduino directly.   I read them one time per cycle then advance to the next sensor so each sensor gets read once every 5 times the program runs.  

 

I might end up with another arduino reading the canbus, I wanted to go with an arduino DUe but it is only 3.3 v vs 5v so I couldn't run the sensors off of it.  

Link to comment
Share on other sites

Alright Cowboy, I hope you can help me out here.

 

I got my loop time down to 56 ms (which includes a 50ms delay) so 6 ms.  but I am not reading anything from the obd port.  

 

Code is 

void loop()
{
  time_start1 = millis();
    timer++;
    Serial.flush();
    SentMessage = "01 11";
    Serial.println("01 11");
    delay(500);
 //while(Serial.available() != '\r'){
 if (Serial.available() > 0){   
    if (SentMessage=="01 0C") {
    WorkingString = BuildINString.substring(7,9);
    A = strtoul(WorkingString.c_str(),NULL,16);
    WorkingString = BuildINString.substring(10,12);
    B = strtoul(WorkingString.c_str(),NULL,16);
   
   DisplayValue = ((A * 256)+B)/4;
   lcd.setCursor(5 , 0);
   lcd.print(DisplayValue);
  } //else {Serial.flush();}
 
   //Throttle position 
  if (SentMessage=="01 11")
  {
   A = Serial.read(); //WorkingString = BuildINString.substring(7,9);
   //A = strtol(WorkingString.c_str(),NULL,0);
   DisplayValue = A;
   //DisplayString = String(DisplayValue) + " %            ";
   lcd.setCursor(5, 1);
   lcd.print(DisplayString); 
  }
  //}
 }
  
 lcd.setCursor(0,2);
 lcd.print(timer);

 time_finished1 = millis();   
 time_elapsed1 = time_finished1 - time_start1;
 lcd.setCursor(5,3);
 lcd.print(time_elapsed1);
 

}

Issue is that I see that I am sending the command out "0111" which means to our trucks give me the tps reading.  but I am not seeing anything come back. I think my issue is that A = Serial.read(); isn't grabbing any data.

 

I can communicate with the truck directly via the scanner and terminal program so I know the truck responds with an answer.

Link to comment
Share on other sites

Dang it man, It's been forever since my head was in this stuff, I wish I could be of more help but here are my thoughts.

First, I'm sure this isn't all your code, but I don't see where you actually sent "SentMessage".

Also, In the code below, I changed "if (serial)" to "while(serial)" plus added a timeout for it.  Just incase you are getting the message, but for some crazy reason it's taking longer than expected.

 

void loop()
{
  time_start1 = millis();
    timer++;
    Serial.flush();
    SentMessage = "01 11";
    Serial.println("01 11");
    delay(500);
 //while(Serial.available() != '\r'){

 int timeout = (5000 + millis());
  while ((Serial.available() > 0) && (millis() <= timeout) ){   

    if (SentMessage=="01 0C") {
    WorkingString = BuildINString.substring(7,9);
    A = strtoul(WorkingString.c_str(),NULL,16);
    WorkingString = BuildINString.substring(10,12);
    B = strtoul(WorkingString.c_str(),NULL,16);
   
   DisplayValue = ((A * 256)+B)/4;
   lcd.setCursor(5 , 0);
   lcd.print(DisplayValue);
  } //else {Serial.flush();}
 
   //Throttle position 
  if (SentMessage=="01 11")
  {
   A = Serial.read(); //WorkingString = BuildINString.substring(7,9);
   //A = strtol(WorkingString.c_str(),NULL,0);
   DisplayValue = A;
   //DisplayString = String(DisplayValue) + " %            ";
   lcd.setCursor(5, 1);
   lcd.print(DisplayString); 
  }
  //}
 }
  
 lcd.setCursor(0,2);
 lcd.print(timer);

 time_finished1 = millis();   
 time_elapsed1 = time_finished1 - time_start1;
 lcd.setCursor(5,3);
 lcd.print(time_elapsed1);
 

}

 

Link to comment
Share on other sites

So it appears that the elm327 isn't talking to the truck.  :banghead:

 

If I use the elm327 via bluetooth to my laptop I can send the serial command "atsp0" through terminal and get a response from the obd saying "ok" which means I know the protocol and how to talk to the truck.  If I do the same thing via the arduino nothing ever happens.  

 

Via the laptop I can spit commands at the truck all day long, arduino.... nope.

 

I must be talking to the elm327 wrong.... from the arduino.  time to read the elm327 datasheet....ugh

 

 

 

Edit, well I feel dumb......I was issuing the commands without "\r"........I was hitting Enter on the laptop for the truck to talk.........  Time to see what I can do now.

Yep,

 

adding \r to my serial print or using serial.println("atsp0"); works.  I am not talking with the ecm.   Still speaking french in terms of what I want, but communication is the first step....

 

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int line;

void setup() {
  // put your setup code here, to run once:
  
  Serial.begin(38400);
  lcd.begin(20,4);
  char data[20];
  lcd.setCursor(0,0);
  lcd.print("Starting OBD Link");
  delay(1500);
  lcd.clear();
  Serial.flush();
  lcd.setCursor(0,0);
  lcd.print("Sending Serial");
  Serial.print("atz\r"); //tells the elm327 to reset
  delay(1500);
  lcd.clear();
if (Serial.available()) {
    lcd.setCursor(0,0);  
    lcd.print("serialisthere");
    delay(1000);

 line = Serial.read();
 lcd.clear();
 lcd.setCursor(3,0);
 lcd.print(line);
 delay(1000);
 }
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Sending Serial");
  Serial.flush();
  Serial.print("atsp0\r"); //tells the elm327 to auto find protocol.
  delay(1500);
  
  if (Serial.available()) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("serialisthere");
    delay(1000);
 line = Serial.read();
 lcd.clear();
 lcd.setCursor(3,0);
 lcd.print(line);
 delay(1000);
  }
 Serial.print("ath0\r"); //set echo off
 delay(1500);
 Serial.flush();
 lcd.clear();

}

void loop(){

  //you code here
  
}

there the setup code to connect an arduino via TX/RX ports to a ELM327 and making it connect to the dodge ECM.

 

Remember it is returning bytes so it doesn't make sense, but I am working on it.

Edited by Me78569
Link to comment
Share on other sites

well I am banging my head on my desk trying to figure out why my shaft speed is no longer working.  I found that the 5v rail on my shield was no longer 5v, but after I fixed that issue I am still not getting any readings.  

 

Ohm'd out all the wireing and it is all good.  

 

All I am left with is the pin 8 on my arduino is burnt up.  it might be time for me to build a new controller that isn't "beta"   dunno.

Link to comment
Share on other sites

15 minutes ago, Me78569 said:

well I am banging my head on my desk trying to figure out why my shaft speed is no longer working.  I found that the 5v rail on my shield was no longer 5v, but after I fixed that issue I am still not getting any readings.  

 

Ohm'd out all the wireing and it is all good.  

 

All I am left with is the pin 8 on my arduino is burnt up.  it might be time for me to build a new controller that isn't "beta"   dunno.

Have you checked the sensor? Even with 5V of source voltage if the sensor has a damaged coil it will fail to properly sense the blade tips on the compressor. Also make sure everything is tight.

Edited by Vais01
Link to comment
Share on other sites

×
×
  • Create New...