With OBD-II you're allowed only one outstanding request. Try using a mutex to prevent your timers or threads from accessing the vehicle simultaneously. Also if there's more than one ECU on the vehicle, you should wait for all responses before submitting a second request.
Typically it's easier to keep your code single threaded. I've created several .NET examples for
Mongoose. Here's a snippet of how I make an OBD-II request on J1850VPW:
Code:
uint ProtocolID = J1850VPW;
// Clear any messages received before this request
PassThruIoctl(ChannelID, CLEAR_RX_BUFFER, NULL, NULL);
// Mode 01: Request vehicle data
numMsgs = 1;
Msg[0].ProtocolID = ProtocolID;
Msg[0].TxFlags = 0;
Msg[0].Data[0] = 0x68; // Header
Msg[0].Data[1] = 0x6A;
Msg[0].Data[2] = 0xF1;
Msg[0].Data[3] = 0x01; // Mode 01: Request vehicle data
Msg[0].Data[4] = PID; // PID: 8-bit
Msg[0].DataSize = 5;
PassThruWriteMsgs(ChannelID, Msg, ref numMsgs, 100);
// Wait P2_J1850_MAX (100ms) for a response from the ECU
timestamp = (uint) Environment.TickCount;
while (((uint) Environment.TickCount - timestamp) < 100)
{
numMsgs = 3;
PassThruReadMsgs(ChannelID, InMsg, ref numMsgs, 100);
for (i=0; i < numMsgs; i++)
{
if ((InMsg[i].RxStatus & (ISO15765_PADDING_ERROR | TX_DONE | RX_BREAK | START_OF_MESSAGE | TX_MSG_TYPE)) == 0)
{
if ((InMsg[i].Data[3] == (mode + 0x40)) && (InMsg[i].Data[4] == PID))
{
// Valid response. Restart the P2_MAX timeout.
timestamp = (uint) Environment.TickCount;
// Should improve this code to wait for other ECUs instead of returning immediately.
switch (size)
{
case 1:
value = (UInt32) InMsg[i].Data[5];
return PASS;
case 2:
value = (UInt32) (InMsg[i].Data[5] << 8) | InMsg[i].Data[6];
return PASS;
case 4:
value = ((UInt32) InMsg[i].Data[5] << 24) | ((UInt32) InMsg[i].Data[6] << 16) | ((UInt32) InMsg[i].Data[7] << 8) | (UInt32) InMsg[i].Data[8];
return PASS;
default:
// This code handles only 1, 2, and 4 byte responses.
value = 0;
return FAIL;
}
}
}
}
}
// We exited the loop for a timeout. Indicate failure.
value = 0;
return FAIL;