So I bought a Sparkfun Can-Bus shield for use with my Uno and trying to get it to display a variety of engine parameters from my 2008 BMW 335i. Eventually they will go on a LCD but for now, just testing the code on the Serial Monitor. Using a OBD2 to DB9 adapter cable plugged into the shield, I have successfully read the data from the example code provided by Sparkfun's Canbus.h library. However, because I want to display more parameters than the sample code provides I've been trying to modify this library to accommodate these extra readings (oil temp, fuel pressure, engine run time, fuel flow). I have successfully modified the code for engine run time but the other three readings won't return a value. When I run the debugging code, the first readings for these three parameters are blank and after the loop goes around once, the next reading displays the data from the preceding functioning parameter. It's as if the buffer is not getting the updated reading and re-printing the last good one. Are the PIDs that I've added not valid? I thought they were an industry standard. Why was I able to get the engine timer (Hex 0x1F) to work but not the others? Thanks in advance. I'll be really embarrassed if the answer is a simple one.
Here is the main sketch:
#include <Canbus.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>
#include <ODB2Parser.h>
#include <ODB2Response.h>
#include <pids.h>
#include <Canbus.h>
char UserInput;
int data;
char buffer[456]; //Data will be temporarily stored to this buffer before being written to the file
//********************************Setup Loop*********************************//
void setup(){
Serial.begin(9600);
Serial.println("CAN-Bus Demo");
if(Canbus.init(CANSPEED_500)) /* Initialise MCP2515 CAN controller at the specified speed */
{
Serial.println("CAN Init ok");
} else
{
Serial.println("Can't init CAN");
}
delay(1000);
}
void loop(){
Canbus.ecu_req(FUEL_FLOW, buffer);
Serial.print(" FF: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(FUEL_PRESSURE, buffer);
Serial.print(" Fp: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(VEHICLE_SPEED, buffer);
Serial.print("Spd: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(ENGINE_RPM, buffer);
Serial.print(" RPM: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(ENGINE_COOLANT_TEMP, buffer);
Serial.print(" Cool: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(OIL_TEMPERATURE, buffer);
Serial.print(" Ot: ");
Serial.print(buffer);
delay(150);
Canbus.ecu_req(ENGINE_TIME, buffer);
Serial.print(" Time: ");
Serial.println(buffer);
delay(150);
}
Here is a portion of the Canbus.cpp. For brevity, I only added the switch function to the code below. Let me know if it's necessary to see the whole .cpp file to better diagnose my problem
char CanbusClass::ecu_req(unsigned char pid, char *buffer)
{
tCAN message;
float engine_data;
if(CanbusClass::ecu_req(pid, &message))
{
switch(message.data[2])
{
/* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
case ENGINE_RPM: // ((A*256)+B)/4 [RPM]
engine_data = ((message.data[3]*256) + message.data[4])/4;
sprintf(buffer,"%d rpm ",(int) engine_data);
break;
case ENGINE_COOLANT_TEMP: // A-40 [degree C]
engine_data = message.data[3] - 40;
sprintf(buffer,"%d degC",(int) engine_data);
break;
case VEHICLE_SPEED: // A [km]
engine_data = message.data[3];
sprintf(buffer,"%d km ",(int) engine_data);
break;
case MAF_SENSOR: // ((256*A)+B) / 100 [g/s]
engine_data = ((message.data[3]*256) + message.data[4])/100;
sprintf(buffer,"%d g/s",(int) engine_data);
break;
case O2_VOLTAGE: // A * 0.005 (B-128) * 100/128 (if B==0xFF, sensor is not used in trim calc)
engine_data = message.data[3]*0.005;
sprintf(buffer,"%d v",(int) engine_data);
break;
case THROTTLE: // Throttle Position
engine_data = (message.data[3]*100)/255;
sprintf(buffer,"%d %% ",(int) engine_data);
break;
case OIL_TEMPERATURE: // Oil Temperature added to Library, not working
engine_data = message.data[3] - 40;
sprintf(buffer,"%d degF",(int) engine_data);
break;
case ENGINE_TIME: // Engine Time added to Library, functional
engine_data = ((message.data[3]*256)+ message.data[4]);
sprintf(buffer,"%d sec",(int) engine_data);
break;
case FUEL_PRESSURE: // Fuel Pressure added to Library, not working
engine_data = (message.data[3]*3);
sprintf(buffer,"%d psi",(int) engine_data);
break;
case FUEL_FLOW: // Fuel Flow added to Library, not working
engine_data = ((message.data[3]*256)+ message.data[4])/20;
sprintf(buffer,"%d gal/hr",(int) engine_data);
break;
}
return 1;
}
return 0;
}
Here is the pids.h file I also modified. I added the hex ID from the wikipedia article on OBD-II PIDs. This is also where I got the formulas for the parameters I've added.
#ifndef pids__h
#define pids__h
#define PID_REQUEST 0x7DF
#define PID_REPLY 0x7E8
#define ENGINE_COOLANT_TEMP 0x05
#define ENGINE_RPM 0x0C
#define VEHICLE_SPEED 0x0D
#define MAF_SENSOR 0x10
#define O2_VOLTAGE 0x14
#define FUEL_LEVEL 0x2F
#define THROTTLE 0x11
#define REL_ACCELERATOR_PEDAL_POS 0x5A
#define ACCELERATOR_PEDAL_POS_D 0x49
#define ACCELERATOR_PEDAL_POS_E 0x4A
#define ACCELERATOR_PEDAL_POS_F 0x4B
#define OIL_TEMPERATURE 0x5C //added to original Library, not working
#define ENGINE_TIME 0x1F //added to original Library, functional
#define FUEL_PRESSURE 0x0A //added to original Library, not working
#define FUEL_FLOW 0x5E //added to original Library, not working
#endif