We’re working on a little demo project on a `16 Ford Fiesta. @CollinK was kind enough to make this example sketch to spit out a handful of OBD2 PIDs to the terminal. The code works great on a '08 Buick, but not the Fiesta.
Anyone else want to try out on their car or have some suggestions for what to try next?
Here is the code:
#include <due_can.h>
uint8_t codes[4] = {5, 0xB, 0xC, 0xD};
int idx = 0;
uint32_t tick = 0;
void sendPIDRequest(uint32_t id, uint8_t PID)
{
CAN_FRAME frame;
frame.id = id;
frame.length = 8;
for (int i = 0; i < 8; i++) frame.data.bytes[i] = 0xAA;
frame.data.bytes[0] = 2; //2 more bytes to follow
frame.data.bytes[1] = 1;
frame.data.bytes[2] = PID;
Can0.sendFrame(frame);
}
void processPID(CAN_FRAME &frame)
{
int temperature;
float psi;
int RPM;
int MPH;
if (frame.data.bytes[1] != 0x41) return; //not anything we're interested in then
switch (frame.data.bytes[2])
{
case 5:
temperature = frame.data.bytes[3] - 40;
SerialUSB.print("Coolant temperature (C): ");
SerialUSB.println(temperature);
break;
case 0xB:
psi = frame.data.bytes[3] * 0.145038; //kPA to PSI
SerialUSB.print("Manifold abs pressure (psi): ");
SerialUSB.println(psi);
break;
case 0xC:
RPM = ((frame.data.bytes[3] * 256) + frame.data.bytes[4])/4;
SerialUSB.print("Engine RPM: ");
SerialUSB.println(RPM);
break;
case 0xD:
MPH = frame.data.bytes[3] * 0.621371;
SerialUSB.print("Vehicle Speed (MPH): ");
SerialUSB.println(MPH);
break;
}
}
void setup() {
Can0.begin(CAN_BPS_500K);
int filter;
//extended
for (filter = 0; filter < 3; filter++) {
Can0.setRXFilter(filter, 0, 0, false);
Can1.setRXFilter(filter, 0, 0, false);
}
}
void loop() {
CAN_FRAME incoming;
if (Can0.available() > 0) {
Can0.read(incoming);
if (incoming.id > 0x7DF && incoming.id < 0x7F0)
{
processPID(incoming);
}
}
//every second rotate to a new code and send it. Hopefully something replies
if (millis() > (tick + 1000) )
{
tick = millis();
sendPIDRequest(0x7DF, codes[idx]);
idx = (idx + 1) % 4;
SerialUSB.println(".");
}
}
Couple things we’re going to try next:
- Send “tester present” messages periodically like this:
CAN_FRAME frame;
frame.id = 0x7DF;
frame.length = 8;
frame.data.bytes[0] = 2;
frame.data.bytes[1] = 0x3E;
frame.data.bytes[2] = 0;
Can0.sendFrame(frame);
- Target the first ECU address directly in case it doesn’t respond to the broadcast address. In that case turn 0x7DF to 0x7E0 and try 0x7E1 through 0x7E8 too.