CAN connections

I’m about to try and connect my CANXtra to my car’s OBDII connector. I still have some doubts:

  1. Do the CAN1H and CAN1L from pin 24/25 of the DB25 connect to CAN H and CAN L on the ODBII connector or should they be switched like a serial connection (rx to tx and tx to rx)
  2. I should also connect the car’s GND to the CANXtra right?
  3. Anyone have some code to share?

Edit: Gonna use this to gather all info.

OBD-II PID’s: OBD-II PIDs - Wikipedia

#################################################

Pop in the TinyCLR community IRC channel and ask/chat

about whatever you want.

Details here: http://www.tinyclr.com/forum/topic?id=7210

#################################################

Nothing to share, but standing by to watch :slight_smile:

Ok,

the good news is that I managed to receive some data. 126 packets of 8 bytes (below are the first 20 packets) :slight_smile:

The bad news is that I have no clue how to interpret that data. :frowning: Can someone jump in here?

Data: (Don’t look at the date because I forgot to update the time on the CANXtra)

MSG: ID = 896 at time = 02/14/2011 00:02:14
30 B3 82 00 84 02 04 81
MSG: ID = 897 at time = 02/14/2011 00:02:14
15 40 88 00 43 00 40 04
MSG: ID = 1088 at time = 02/14/2011 00:02:14
00 00 00 00 00 00 04 81
MSG: ID = 1184 at time = 02/14/2011 00:02:14
00 00 72 57 40 00 40 04
MSG: ID = 1329 at time = 02/14/2011 00:02:14
03 00 28 01 01 00 04 81
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 8A 7F FF 6E 00 40 04
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 9C 7F FF 78 00 04 81
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 66 7F FF 82 00 40 04
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 68 7F FF 8C 00 04 81
MSG: ID = 320 at time = 02/14/2011 00:02:14
81 03 20 FC DF 00 00 00
MSG: ID = 640 at time = 02/14/2011 00:02:14
00 00 00 00 00 00 00 00
MSG: ID = 899 at time = 02/14/2011 00:02:14
9A 60 A0 00 00 00 00 00
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 72 7F FF 96 00 00 00
MSG: ID = 320 at time = 02/14/2011 00:02:14
82 03 20 FC DE 00 00 00
MSG: ID = 640 at time = 02/14/2011 00:02:14
00 00 00 00 00 00 00 00
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 44 7F FF A0 00 00 00
MSG: ID = 320 at time = 02/14/2011 00:02:14
83 03 20 FC DD 00 00 00
MSG: ID = 640 at time = 02/14/2011 00:02:14
00 00 00 00 00 00 00 00
MSG: ID = 384 at time = 02/14/2011 00:02:14
64 4E 7F FF AA 00 00 00
MSG: ID = 320 at time = 02/14/2011 00:02:14
80 03 20 FC E0 00 00 00
MSG: ID = 392 at time = 02/14/2011 00:02:14
00 00 0F FD AA 00 00 00

Go to gadgeteer.codeplex.com and get the Gadgeteer driver source for the OBD II module. All sorts of code for processing the data. I think you have to get all the Gadgeteer source…

Mike, I don’t think that is relevant because the OBD II module uses an ELM 327, which the CANXtra does not have.
The ELM327 has the protocols build in.

I will instead give the datasheet of the ELM327 a look in the hope to get something useful out of it.

@ EriSan500 (Eric) - Ah!

I think I’m getting somewhere :smiley:

Will test the code in the morning on my car…stay tuned

Nope, no joy :frowning:

First of all, I’m getting data back, so I can assume my connections are correct.

2nd: This is my first experience with the CAN bus and so far i haven’t got much luck.
From what I understood, there are 2 ways to get data: 1) Read the date as is is transmitted, 2) Request for specific PID’s

It’s the 2nd option I’m trying. I’m trying to read the Engine coolant temperature which is Mode 01 (hex) PID 05 (hex).

My code for requesting this data is:


    public class Program
    {
        // Messages list
        static CAN.Message[] msgList;
        static CAN.Message[] RequestMsg = new CAN.Message[1];

        static bool NetworkCableConnected = false;
        
        const byte ENGINE_COOLANT_TEMP =  0x05;

        public static void Main()
        {
            // Set the system time. CAN messages will have a time stamp
            NetworkCableConnected = Ethernet.IsCableConnected;
            if (NetworkCableConnected)
            {
                RealTimeClock.SetTime(NtpClient.GetNetworkTime());
            }
            Utility.SetLocalTime(RealTimeClock.GetTime());
            Debug.Print(DateTime.Now.ToString());
            
            Configuration.DebugInterface.Set(Configuration.DebugInterface.Port.Sockets1, Configuration.DebugInterface.Port.USB1);

            int T1, T2, BRP;

            // These numbers were calculated using the calculator on this link:
            // http://www.kvaser.com/en/about-can/the-can-protocol/22.html
            // We used the very first value from the calculator output

            /////////////////////////////////////////////////////////////////////////////////////////////
            // Bitrate 250 kbit/s
            // CLK = 72 MHz, with BRP = 12 -> 6 MHz CAN clock
            // 6 MHz/250 kbit/s = 24 TQ
            // T1 = 16 minus 1 for sync = 15
            // T2 = 8
            // 15 + 1 + 8 = 24 TQs which is what we need
            /////////////////////////////////////////////////////////////////////////////////////////////
            // Uncomment to use this bit timing
            //BRP = 12;
            //T1 = 15;
            //T2 = 8;

            /////////////////////////////////////////////////////////////////////////////////////////////
            // Bitrate 125 kbit/s
            // CLK = 72 MHz, with BRP = 24 -> 3 MHz CAN clock
            // 3 MHz/125 kbit/s = 24 TQ
            // T1 = 16 minus 1 for sync = 15
            // T2 = 8
            // 15 + 1 + 8 = 24 TQs which is what we need
            /////////////////////////////////////////////////////////////////////////////////////////////
            // Uncomment to use this bit timing
            BRP = 6;
            T1 = 15;
            T2 = 8;

            // For 500 kbit/s you can use BRP=6 and for 1 Mbit/s you can use BRP=3 ...and so on

            // Use channel 1
            CAN can = new CAN(CAN.Channel.Channel_1,
                              (uint)(((T2 - 1) << 20) |
                                     ((T1 - 1) << 16) |
                                     ((BRP - 1) << 0))
                             );



            // Create a message list of 126 messages
            msgList = new CAN.Message[126];
            for (int i = 0; i < msgList.Length; i++)
                msgList[i] = new CAN.Message();

            // Subscribe to events
            //can.DataReceivedEvent += new CANDataReceivedEventHandler(can_DataReceivedEvent);
            //can.ErrorReceivedEvent += new CANErrorReceivedEventHandler(can_ErrorReceivedEvent);

            float engine_data;

            // Example for sending one message
            // msg ID
            RequestMsg[0] = new CAN.Message();
            //RequestMsg[0].ArbID = 0x7DF;
            RequestMsg[0].Data[0] = 0x01;
            RequestMsg[0].Data[1] = 0x05;
            RequestMsg[0].Data[2] = 0x00;
            RequestMsg[0].Data[3] = 0x00;
            RequestMsg[0].Data[4] = 0x00;
            RequestMsg[0].Data[5] = 0x00;
            RequestMsg[0].Data[6] = 0x00;
            RequestMsg[0].Data[7] = 0x00;
            // Send the 8 bytes for example
            //RequestMsg[0].DLC = 8;
            //RequestMsg[0].IsEID = false;
            //RequestMsg[0].IsRTR = false;

            // Send one message
            int numberOfMessagesPosted = can.PostMessages(RequestMsg, 0, 1);

            Debug.Print("Transmit Errors: " + can.TransmitErrorCount);

            if (can.GetMessages(msgList, 0, msgList.Length) > 0)
            {
                for (int i = 0; i < msgList.Length; i++)
                {
                    Debug.Print("Pos: " + i + " Bytes: " + PrintBytes(msgList[i].Data) + " Hex: " + BytesToHex(msgList[i].Data));

                    switch (msgList[i].Data[2])
                    {
                        case ENGINE_COOLANT_TEMP:
                            engine_data = msgList[i].Data[3] - 40;
                            Debug.Print("Coolant Temp: " + engine_data.ToString());
                            break;

                        default:
                            break;
                    }
                }
                Debug.Print("CAN Done");
            }

            // Sleep forever
            Thread.Sleep(Timeout.Infinite);
        }

        private static string BytesToHex(byte[] b)
        {
            string x = string.Empty;
            for (int i = 0; i < b.Length; i++)
            {
                x += FromByteToHex(b[i]);
                if (i < b.Length)
                {
                    x += " ";
                }
            }
            return x;
        }

        private static string PrintBytes(byte[] b)
        {
            string x = string.Empty;
            for (int i = 0; i < b.Length; i++)
            {
                x += b[i];
                if (i < b.Length)
                {
                    x += " ";
                }
            }
            return x;
        }

        static readonly string hex = "0123456789ABCDEF";

        /// <summary>
        /// Converts Byte to a Hexadecimal string, like .ToString("X2") would do;
        /// </summary>
        /// <param name="number">Byte to represent has a hexadecimal string.</param>
        /// <returns>2 character string of hexadecimal representation of the number</returns>
        public static string FromByteToHex(byte number)
        {
            return new string(new char[] { hex[(number & 0xF0) >> 4], hex[number & 0x0F] });
        }
       

    }


This is the data that gets returned

Pos: 0 Bytes: 100 50 127 255 214 0 0 0 Hex: 64 32 7F FF D6 00 00 00
Pos: 1 Bytes: 129 3 32 252 223 0 0 0 Hex: 81 03 20 FC DF 00 00 00
Pos: 2 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 3 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 4 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 5 Bytes: 0 39 0 32 64 0 0 0 Hex: 00 27 00 20 40 00 00 00
Pos: 6 Bytes: 44 0 224 64 0 40 80 0 Hex: 2C 00 E0 40 00 28 50 00
Pos: 7 Bytes: 100 4 127 255 224 0 0 0 Hex: 64 04 7F FF E0 00 00 00
Pos: 8 Bytes: 130 3 32 252 222 0 0 0 Hex: 82 03 20 FC DE 00 00 00
Pos: 9 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 10 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 11 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 12 Bytes: 96 59 62 45 0 0 0 0 Hex: 60 3B 3E 2D 00 00 00 00
Pos: 13 Bytes: 100 14 127 255 234 0 80 0 Hex: 64 0E 7F FF EA 00 50 00
Pos: 14 Bytes: 131 3 32 252 221 0 0 0 Hex: 83 03 20 FC DD 00 00 00
Pos: 15 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 16 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 17 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 18 Bytes: 100 16 127 255 244 0 0 0 Hex: 64 10 7F FF F4 00 00 00
Pos: 19 Bytes: 128 3 32 252 224 0 0 0 Hex: 80 03 20 FC E0 00 00 00
Pos: 20 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 21 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 22 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 23 Bytes: 176 186 117 0 255 251 0 132 Hex: B0 BA 75 00 FF FB 00 84
Pos: 24 Bytes: 1 217 3 159 2 158 0 4 Hex: 01 D9 03 9F 02 9E 00 04
Pos: 25 Bytes: 100 26 127 255 254 0 0 132 Hex: 64 1A 7F FF FE 00 00 84
Pos: 26 Bytes: 129 3 32 252 223 0 0 0 Hex: 81 03 20 FC DF 00 00 00
Pos: 27 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 28 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 29 Bytes: 0 13 100 107 0 0 0 0 Hex: 00 0D 64 6B 00 00 00 00
Pos: 30 Bytes: 100 236 127 255 8 0 80 0 Hex: 64 EC 7F FF 08 00 50 00
Pos: 31 Bytes: 130 3 32 252 222 0 0 0 Hex: 82 03 20 FC DE 00 00 00
Pos: 32 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 33 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 34 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 35 Bytes: 100 246 127 255 18 0 0 0 Hex: 64 F6 7F FF 12 00 00 00
Pos: 36 Bytes: 131 3 32 252 221 0 0 0 Hex: 83 03 20 FC DD 00 00 00
Pos: 37 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 38 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 39 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 40 Bytes: 100 248 127 255 28 0 0 0 Hex: 64 F8 7F FF 1C 00 00 00
Pos: 41 Bytes: 128 3 32 252 224 0 0 0 Hex: 80 03 20 FC E0 00 00 00
Pos: 42 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 43 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 44 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 45 Bytes: 100 194 127 255 38 0 80 0 Hex: 64 C2 7F FF 26 00 50 00
Pos: 46 Bytes: 129 3 32 252 223 0 0 0 Hex: 81 03 20 FC DF 00 00 00
Pos: 47 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 48 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 49 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 50 Bytes: 100 212 127 255 48 0 0 0 Hex: 64 D4 7F FF 30 00 00 00
Pos: 51 Bytes: 130 3 32 252 222 0 0 0 Hex: 82 03 20 FC DE 00 00 00
Pos: 52 Bytes: 0 255 191 243 48 0 0 0 Hex: 00 FF BF F3 30 00 00 00
Pos: 53 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 54 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 55 Bytes: 0 13 100 107 0 0 0 0 Hex: 00 0D 64 6B 00 00 00 00
Pos: 56 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 57 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 58 Bytes: 1 0 58 0 0 20 0 0 Hex: 01 00 3A 00 00 14 00 00
Pos: 59 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 60 Bytes: 100 222 127 255 58 0 0 0 Hex: 64 DE 7F FF 3A 00 00 00
Pos: 61 Bytes: 131 3 32 252 221 0 0 0 Hex: 83 03 20 FC DD 00 00 00
Pos: 62 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 63 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 64 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 65 Bytes: 0 39 0 32 64 0 0 0 Hex: 00 27 00 20 40 00 00 00
Pos: 66 Bytes: 44 0 224 64 0 40 80 0 Hex: 2C 00 E0 40 00 28 50 00
Pos: 67 Bytes: 100 160 127 255 68 0 0 0 Hex: 64 A0 7F FF 44 00 00 00
Pos: 68 Bytes: 128 3 32 252 224 0 0 0 Hex: 80 03 20 FC E0 00 00 00
Pos: 69 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 70 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 71 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 72 Bytes: 100 170 127 255 78 0 80 0 Hex: 64 AA 7F FF 4E 00 50 00
Pos: 73 Bytes: 129 3 32 252 223 0 0 0 Hex: 81 03 20 FC DF 00 00 00
Pos: 74 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 75 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 76 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 77 Bytes: 100 188 127 255 88 0 0 0 Hex: 64 BC 7F FF 58 00 00 00
Pos: 78 Bytes: 130 3 32 252 222 0 0 0 Hex: 82 03 20 FC DE 00 00 00
Pos: 79 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 80 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 81 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 82 Bytes: 224 186 117 0 255 251 0 132 Hex: E0 BA 75 00 FF FB 00 84
Pos: 83 Bytes: 1 217 3 159 2 158 0 4 Hex: 01 D9 03 9F 02 9E 00 04
Pos: 84 Bytes: 28 7 12 0 0 0 0 132 Hex: 1C 07 0C 00 00 00 00 84
Pos: 85 Bytes: 3 0 40 1 1 0 0 4 Hex: 03 00 28 01 01 00 00 04
Pos: 86 Bytes: 100 134 127 255 98 0 0 132 Hex: 64 86 7F FF 62 00 00 84
Pos: 87 Bytes: 131 3 32 252 221 0 0 0 Hex: 83 03 20 FC DD 00 00 00
Pos: 88 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 89 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 90 Bytes: 0 13 100 107 0 0 0 0 Hex: 00 0D 64 6B 00 00 00 00
Pos: 91 Bytes: 100 136 127 255 108 0 80 0 Hex: 64 88 7F FF 6C 00 50 00
Pos: 92 Bytes: 128 3 32 252 224 0 0 0 Hex: 80 03 20 FC E0 00 00 00
Pos: 93 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 94 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 95 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 96 Bytes: 100 146 127 255 118 0 80 0 Hex: 64 92 7F FF 76 00 50 00
Pos: 97 Bytes: 129 3 32 252 223 0 0 0 Hex: 81 03 20 FC DF 00 00 00
Pos: 98 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 99 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 100 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 101 Bytes: 100 100 127 255 128 0 0 0 Hex: 64 64 7F FF 80 00 00 00
Pos: 102 Bytes: 130 3 32 252 222 0 0 0 Hex: 82 03 20 FC DE 00 00 00
Pos: 103 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 104 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 105 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 106 Bytes: 100 110 127 255 138 0 80 0 Hex: 64 6E 7F FF 8A 00 50 00
Pos: 107 Bytes: 131 3 32 252 221 0 0 0 Hex: 83 03 20 FC DD 00 00 00
Pos: 108 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 109 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 110 Bytes: 0 50 2 133 38 40 80 0 Hex: 00 32 02 85 26 28 50 00
Pos: 111 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 112 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 113 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 114 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 115 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 116 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 117 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 118 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 119 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 120 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 121 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 122 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 123 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 124 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00
Pos: 125 Bytes: 0 0 0 0 0 0 0 0 Hex: 00 00 00 00 00 00 00 00

At the moment I’m a bit lost. I would be thankful if someone can help me out here.

@ Brett, and anyone else who’s interested in OBD-II, I got it working :wink:

Now, let me ask this: OBD-II works with PID numbers, and the 1st PID of every Mode (0x0100 means Mode 01 PID 00, there are 10 modes in total) contains a bit-masked DWord (32 bits) of the supported PID’s.
For example: (hope the layout keeps it readable)

                        B       E      1          F        A        8        1             3               
                      ----    ----    ----       ----     ----     ----     ----      ----------

supported? 1011 1110 0001 1111 1010 1000 0001 0 0 1 1
PID num 1234 5678 … … … … … 29 30 31 32

Every PID has a description, and what I would like to do is when you read this PID, show all the supported PID’s with their description.
Is a HashTable the way to go here?

sweet !

Must find an OBD connector for my car now :slight_smile:

Brett, I use something similar to this to interface OBD-II with my smartphone. It could be a good wireless option for interfacing with a FEZ also. That port isn’t exactly in a great spot.

http://www.ebay.com/itm/Bluetooth-ELM327-V1-4-Scannner-OBD-2-OBDII-OBD2-diagnostic-tool-/400312825536?pt=Motors_Automotive_Tools&hash=item5d3480f6c0&vxp=mtr#ht_3998wt_1163

Thanks Ian; part of the appeal with CANxtra direct is there is no need to use the ELM chip and that potentially filters stuff you may not want (probably more correctly, it can’t handle stuff you may want so you can’t get to). Don’t get me wrong, buying stuff out of interest’s sake is a-ok with me :wink:

I think all I need is a connector plus some cable; yeah cable is never fun when you can have wireless right :slight_smile: plus I agree, locaiton of OBD ports on the car is another potential challenge - a 1yr old Subaru Forester that I have not even thought about pulling the dash covers off, well since my last thought about buying a connector :slight_smile: :slight_smile:

Eric, snap a pic of your setup when you plug it in next :slight_smile:

And nobody forget about Eric’s question… it’s just fallen off the current page so here it is:

[quote]Now, let me ask this: OBD-II works with PID numbers, and the 1st PID of every Mode (0x0100 means Mode 01 PID 00, there are 10 modes in total) contains a bit-masked DWord (32 bits) of the supported PID’s.
For example: (hope the layout keeps it readable)

B E 1 F A 8 1 3


supported? 1011 1110 0001 1111 1010 1000 0001 0 0 1 1
PID num 1234 5678 … … … … … 29 30 31 32

Every PID has a description, and what I would like to do is when you read this PID, show all the supported PID’s with their description.
Is a HashTable the way to go here?[/quote]

These are the PID’s supported by my car (The ones with TRUE at the end)

A bit disappointing that only 11 pid’s are supported. Most of the other info is also available, though it’s proprietary Opel and not documented (at least not on the internet)

07/31/2012 16:21:18
Valid OBD-II PID reply
Supported PID mask: -1740963823
Mask: 10011000001110110000000000010001
0x01 - STATUS_DTC - Status since DTC Cleared >>> TRUE
0x02 - FREEZE_DTC - Freeze Diagnostic Trouble Code >>> FALSE
0x03 - FUEL_SYS_STATUS - Fuel System Status >>> FALSE
0x04 - ENGINE_LOAD - Calculated Engine Load >>> TRUE
0x05 - ENGINE_COOLANT_TEMP - Engine Coolant Temperature >>> TRUE

0x06 - ST_FUEL_TRIM_1 - Short Term Fuel % Trim - Bank 1 >>> FALSE
0x07 - LT_FUEL_TRIM_1 - Long Term Fuel % Trim - Bank 1 >>> FALSE
0x08 - ST_FUEL_TRIM_2 - Short Term Fuel % Trim - Bank 2 >>> FALSE
0x09 - LT_FUEL_TRIM_2 - Long Term Fuel % Trim - Bank 2 >>> FALSE
0x0A - FUEL_PRESSURE - Fuel Pressure >>> FALSE
0x0B - INTAKE_PRESSURE - Intake Manifold Absolute Pressure >>> TRUE
0x0C - ENGINE_RPM - Engine RPM >>> TRUE
0x0D - VEHICLE_SPEED - Vehicle Speed >>> TRUE

0x0E - TIMING_ADVANCE - Timing Advance >>> FALSE
0x0F - INTAKE_TEMP - Intake Air Temperature >>> TRUE
0x10 - MAF_SENSOR - MAF Sensor Air Flow Rate >>> TRUE

0x11 - THROTTLE - Throttle Position >>> FALSE
0x12 - COMMANDED_SEC_AIR - Commanded Secondary Air Status >>> FALSE
0x13 - O2_SENS_PRES - Detected O2 Sensors >>> FALSE
0x14 - O2_B1S1_VOLTAGE - O2 Sensor Voltage - Bank 1 Sensor 1 >>> FALSE
0x15 - O2_B1S2_VOLTAGE - O2 Sensor Voltage - Bank 1 Sensor 2 >>> FALSE
0x16 - O2_B1S3_VOLTAGE - O2 Sensor Voltage - Bank 1 Sensor 3 >>> FALSE
0x17 - O2_B1S4_VOLTAGE - O2 Sensor Voltage - Bank 1 Sensor 4 >>> FALSE
0x18 - O2_B2S1_VOLTAGE - O2 Sensor Voltage - Bank 2 Sensor 1 >>> FALSE
0x19 - O2_B2S2_VOLTAGE - O2 Sensor Voltage - Bank 2 Sensor 2 >>> FALSE
0x1A - O2_B2S3_VOLTAGE - O2 Sensor Voltage - Bank 2 Sensor 3 >>> FALSE
0x1B - O2_B2S4_VOLTAGE - O2 Sensor Voltage - Bank 2 Sensor 4 >>> FALSE
0x1C - OBDII_STANDARDS - Supported OBDII Standards >>> TRUE
0x1D - O2_SENS_PRES_ALT - Detected O2 Sensors - Alternate Grouping >>> FALSE
0x1E - AUX_IN_STATUS - Auxiliary Input Status >>> FALSE
0x1F - ENGINE_RUNTIME - Run Time Since Engine Started >>> FALSE
0x20 - PID_21_40 - PID 0x21 - 0x40 Supported >>> TRUE

Valid OBD-II PID reply
Supported PID mask: -1610612735
Mask: 10100000000000000000000000000001
0x21 - DIST_TRAVELED_MIL - Distance Traveled with MIL On >>> TRUE
0x22 - FUEL_RAIL_PRESSURE - Fuel Rail Pressure Relative to Manifold >>> FALSE
0x23 - FUEL_RAIL_PRES_ALT - MPI/Diesel Fuel Rail Pressure >>> TRUE
0x24 - O2S1_WR_LAMBDA_V - O2 Sensor 1 Equivalence Ratio Voltage >>> FALSE
0x25 - O2S2_WR_LAMBDA_V - O2 Sensor 2 Equivalence Ratio Voltage >>> FALSE
0x26 - O2S3_WR_LAMBDA_V - O2 Sensor 3 Equivalence Ratio Voltage >>> FALSE
0x27 - O2S4_WR_LAMBDA_V - O2 Sensor 4 Equivalence Ratio Voltage >>> FALSE
0x28 - O2S5_WR_LAMBDA_V - O2 Sensor 5 Equivalence Ratio Voltage >>> FALSE
0x29 - O2S6_WR_LAMBDA_V - O2 Sensor 6 Equivalence Ratio Voltage >>> FALSE
0x2A - O2S7_WR_LAMBDA_V - O2 Sensor 7 Equivalence Ratio Voltage >>> FALSE
0x2B - O2S8_WR_LAMBDA_V - O2 Sensor 8 Equivalence Ratio Voltage >>> FALSE
0x2C - COMMANDED_EGR - Commanded EGR >>> FALSE
0x2D - EGR_ERROR - EGR Error >>> FALSE
0x2E - COMMANDED_EVAP_P - Commanded Evaporative Purge >>> FALSE
0x2F - FUEL_LEVEL - Fuel Level Input >>> FALSE
0x30 - WARMUPS_SINCE_CLR - Number of Warmups since DTC Cleared >>> FALSE
0x31 - DIST_SINCE_CLR - Distance Traveled Since DTC Cleared >>> FALSE
0x32 - EVAP_PRESSURE - Evap. System Vapor Pressure >>> FALSE
0x33 - BAROMETRIC_PRESSURE - Barometric Pressure >>> FALSE
0x34 - O2S1_WR_LAMBDA_I - O2 Sensor 1 Equivalence Ratio Current >>> FALSE
0x35 - O2S2_WR_LAMBDA_I - O2 Sensor 2 Equivalence Ratio Current >>> FALSE
0x36 - O2S3_WR_LAMBDA_I - O2 Sensor 3 Equivalence Ratio Current >>> FALSE
0x37 - O2S4_WR_LAMBDA_I - O2 Sensor 4 Equivalence Ratio Current >>> FALSE
0x38 - O2S5_WR_LAMBDA_I - O2 Sensor 5 Equivalence Ratio Current >>> FALSE
0x39 - O2S6_WR_LAMBDA_I - O2 Sensor 6 Equivalence Ratio Current >>> FALSE
0x3A - O2S7_WR_LAMBDA_I - O2 Sensor 7 Equivalence Ratio Current >>> FALSE
0x3B - O2S8_WR_LAMBDA_I - O2 Sensor 8 Equivalence Ratio Current >>> FALSE
0x3C - CAT_TEMP_B1S1 - Catalyst Temperature Bank 1 Sensor 1 >>> FALSE
0x3D - CAT_TEMP_B2S1 - Catalyst Temperature Bank 2 Sensor 1 >>> FALSE
0x3E - CAT_TEMP_B1S2 - Catalyst Temperature Bank 1 Sensor 2 >>> FALSE
0x3F - CAT_TEMP_B2S2 - Catalyst Temperature Bank 2 Sensor 2 >>> FALSE
0x40 - PID_41_60 - PID 0x41 - 0x60 Supported >>> TRUE

Valid OBD-II PID reply
Supported PID mask: 1
Mask: 00000000000000000000000000000001
0x41 - MONITOR_STATUS - Monitor Status This Drive Cycle >>> FALSE
0x42 - ECU_VOLTAGE - Control Module Voltage >>> FALSE
0x43 - ABSOLUTE_LOAD - Absolute Load Value >>> FALSE
0x44 - COMMANDED_EQUIV_R - Commanded Equivalence Ratio >>> FALSE
0x45 - REL_THROTTLE_POS - Relative Throttle Position >>> FALSE
0x46 - AMB_AIR_TEMP - Ambient Air Temperature >>> FALSE
0x47 - ABS_THROTTLE_POS_B - Absolute Throttle Position B >>> FALSE
0x48 - ABS_THROTTLE_POS_C - Absolute Throttle Position C >>> FALSE
0x49 - ACCEL_POS_D - Accelerator Pedal Position D >>> FALSE
0x4A - ACCEL_POS_E - Accelerator Pedal Position E >>> FALSE
0x4B - ACCEL_POS_F - Accelerator Pedal Position F >>> FALSE
0x4C - COMMANDED_THROTTLE - Commanded Throttle Actuator >>> FALSE
0x4D - TIME_RUN_WITH_MIL - Time Run with MIL on >>> FALSE
0x4E - TIME_SINCE_CLR - Time Since DTC Cleared >>> FALSE
0x4F - MAX_R_O2_VI_PRES - Maximum Value - Equivalence ratio, O2 Voltage, O2 Current, Intake Manifold Pressure >>> FALSE
0x50 - MAX_AIRFLOW_MAF - Maximum MAF Airflow Value >>> FALSE
0x51 - FUEL_TYPE - Fuel Type >>> FALSE
0x52 - ETHANOL_PERCENT - Ethanol fuel % >>> FALSE
0x53 - ABS_EVAP_SYS_PRES - Absolute Evap. System Vapor Pressure >>> FALSE
0x54 - EVAP_SYS_PRES - Evap. System Vapor Pressure >>> FALSE
0x55 - ST_O2_TRIM_B1B3 - Short Term Secondary O2 Sensor Trim - Bank 1 and 3 >>> FALSE
0x56 - LT_O2_TRIM_B1B3 - Long Term Secondary O2 Sensor Trim - Bank 1 and 3 >>> FALSE
0x57 - ST_02_TRIM_B2B4 - Short Term Secondary O2 Sensor Trim - Bank 2 and 4 >>> FALSE
0x58 - LT_O2_TRIM_B2B4 - Long Term Secondary O2 Sensor Trim - Bank 2 and 4 >>> FALSE
0x59 - ABS_FUEL_RAIL_PRES - Absolute Fuel Rail Pressure >>> FALSE
0x5A - REL_ACCEL_POS - Relative Accelerator Pedal Position >>> FALSE
0x5B - HYBRID_BATT_PCT - Hybrid Battery Pack Charge Percent >>> FALSE
0x5C - ENGINE_OIL_TEMP - Engine Oil Temperature >>> FALSE
0x5D - FUEL_TIMING - Fuel Injection Timing >>> FALSE
0x5E - FUEL_RATE - Engine Fuel Rate >>> FALSE
0x5F - EMISSIONS_STANDARD - Emmissions Requirements >>> FALSE
0x60 - PID_61_80 - PID 0x61 - 0x80 Supported >>> TRUE

Valid OBD-II PID reply
Supported PID mask: 0
Mask: 00000000000000000000000000000000
0x61 - DEMANDED_TORQUE - Driver’s Demanded Torque - Percent >>> FALSE
0x62 - ACTUAL_TORQUE - Actual Engine Torque - Percent >>> FALSE
0x63 - REFERENCE_TORQUE - Engine Reference Torque >>> FALSE
0x64 - ENGINE_PCT_TORQUE - Engine Percent Torque >>> FALSE
0x65 - AUX_IO_SUPPORTED - Auxiliary Input/Output Supported >>> FALSE
0x66 - P_MAF_SENSOR >>> FALSE
0x67 - P_ENGINE_COOLANT_T >>> FALSE
0x68 - P_INTAKE_TEMP >>> FALSE
0x69 - P_COMMANDED_EGR >>> FALSE
0x6A - P_COMMANDED_INTAKE >>> FALSE
0x6B - P_EGR_TEMP >>> FALSE
0x6C - P_COMMANDED_THROT >>> FALSE
0x6D - P_FUEL_PRESSURE >>> FALSE
0x6E - P_FUEL_INJ_PRES >>> FALSE
0x6F - P_TURBO_PRESSURE >>> FALSE
0x70 - P_BOOST_PRES_CONT >>> FALSE
0x71 - P_VGT_CONTROL >>> FALSE
0x72 - P_WASTEGATE_CONT >>> FALSE
0x73 - P_EXHAUST_PRESSURE >>> FALSE
0x74 - P_TURBO_RPM >>> FALSE
0x75 - P_TURBO_TEMP1 >>> FALSE
0x76 - P_TURBO_TEMP2 >>> FALSE
0x77 - P_CACT >>> FALSE
0x78 - P_EGT_B1 >>> FALSE
0x79 - P_EGT_B2 >>> FALSE
0x7A - P_DPF1 >>> FALSE
0x7B - P_DPF2 >>> FALSE
0x7C - P_DPF_TEMP >>> FALSE
0x7D - P_NOX_NTE_STATUS >>> FALSE
0x7E - P_PM_NTE_STATUS >>> FALSE
0x7F - P_ENGINE_RUNTUME >>> FALSE
0x80 - PID_81-87 0x80 >>> FALSE

There’s got to be a more elegant way…Anyone?


        PID020 = ((can_MsgRx[0].Data[3] << 24) | (can_MsgRx[0].Data[4] << 16) | (can_MsgRx[0].Data[5] << 8 ) | (can_MsgRx[0].Data[6]));
        string pid20 = GetIntBinaryString(PID020);
        if (_debug)
        {
            Debug.Print("Supported PID mask: " + PID020);
            Debug.Print("Bits: " + pid20);
            for (int i = 0; i < pid20.Length; i++)
            {
                bool set = pid20[i] == '1' ? true : false;
                Debug.Print("0x" + FromByteToHex((byte)(i + 1)) + " - " + OBDIISupport.SupportLookup(i + 1) + " >>> " + (set ? "TRUE" : "FALSE"));
            }

            }




        static string GetIntBinaryString(int n)
        {
            // Displays bits.
            char[] b = new char[32];
            int pos = 31;
            int i = 0;

            while (i < 32)
            {
                if ((n & (1 << i)) != 0)
                {
                    b[pos] = '1';
                }
                else
                {
                    b[pos] = '0';
                }
                pos--;
                i++;
            }
            return new string(b);
        }

Not really any different or elegant, just another flavor


static string GetIntBinaryString(int n)
{
  char[] b = new char[32];
  for (int i = 31; i >= 0; i--)
  {
    b[i] = (n & 1) == 1 ? '1' : '0';
    n >>= 1;
  }
  return new string(b);
}

If I could make one suggestion on the naming. Since you are passing an ‘int’ argument you can leave out the ‘Int’ from the function name. Why? well later you can provide overloads that accept byte, short etc. and the name will still be ‘GetBinaryString’ the argument type will dictate the overload that is called.

Thanks taylorza, but I was more referring to this line:

string pid20 = GetIntBinaryString(PID020);

can that not be completely avoided to read the individual bits in the for loop?

For the CANXtra, this is all you need: https://www.sparkfun.com/products/9911

Brett, here’s the location of the OBD connector on your car: https://www.google.be/search?q=subaru+forester+obd+location&hl=nl&prmd=imvnsfd&source=lnms&tbm=isch&sa=X&ei=FTgYUKH8F4Ke0QXs5YGICw&ved=0CEQQ_AUoAQ&biw=1920&bih=979

How about Obd Iis Australia | Little Bird Australia since it has cable attached. I suspect the one you point to is the same connection except no easy place to grab hold and remove it… (and $20 for the convenience and cables )

Brett, yes, thats even better.

Besides, just stumbled upon this: http://developer.berlios.de/projects/freessm/

Source code available.