So… a while back I posted about the car issues I was having and the OBD II board I picked up from Sparkfun….
Well, I needed to use the OBD II board again to see if the old 1998 Mazda MPV minivan was going to pass inspection with it’s brand new O2 sensor. But this time I did a quick Google search for an OBD II Ruby Gem and sure enough, someone had thrown one together!
However, a bunch of the good code on various people’s forks hadn’t been pulled back into the upstream repo. So I forked, and cherry picked the code into my own fork while also adding a few extra features. It’s over there on GitHub: github.com/JamesHagerman/obd
Now, most of the existing OBD II stuff doesn’t actually help me all that much because the van is from 1998… But I got a new car and the 2013 Honda Fit totally DOES support all that cool OBD II and CAN stuff.
And so I started digging into all the awesome things people have done with CAN and their cars and I decided to start taking a closer look at CAN and this STN1100 OBD II interface boards features.
Why CAN?
So, there are a bunch of other people that have talked about this, but basically, CAN is one of the inter-chip communication protocols used in the electrical systems of cars. Different car manufacturers use different protocols, but basically, every electrical part of the car has an address and a bunch of ports you can send data to.
If you want to start COMMUNICATING with all of those electrical systems, you basically have to reverse engineer the proprietary addresses and ports configured by the car manufacturer.
The easiest way to start reverse engineering most communication protocols is to log as much data as you can from the system. Since CAN has no real security protections in place we should be able to just grab the CAN messages off the wire and log them for future inspection.
More on that in a bit though. Let’s talk a little about CAN! Specifically, I’m going to talk about the 29 bit version of CAN used in the 2013 Honda Fit… you car is probably much different…
CAN Addresses
Let’s talk about 29 bit CAN addresses. The ‘header’ will be 29 bits. Actually, it’s 32 bits… but the first three bits are 0’s/dnc bits. Therefore, every CAN header is going to start with 0x1
Then, the next 8 hex values will represent the header itself:
18DAF110 After the header, there are 8 more bytes (the first of which is PCI, the message formatting byte):
18DAF110 064100BEThen, there are some number of checksum bytes (looks like another 8 bytes…):
18DAF110 064100BE 3FA81355CAN Headers/CAN ID’s
Now, a bit more about 29 bit CAN headers. First, CAN headers are also called CAN ID’s. This will come in handy to know when we get to filtering a bit later. The first byte (not includeing the three 0 bits) is the CAN Bus Priority. For Diagnostics work, this byte should pretty much always be set to: 0x18 18
The next three bytes are:
- Message Type (DA for physical addressing, DB for functional addressing)
- The receiver (the Target Address)
- And the transmitter (the Source Address)
DA F1 10CAN Filters: CAN Filter and CAN Mask play together…
So now that we understand CAN Headers we SHOULD be able to start figuring out how to set up filters to listen to specific data. There are Four levels of filtering:
- CAN HW Filter: This first step compares the bits in the CAN Header (the CAN ID) with the bits in the CAN Filter to decide what messages to listen to. The important thing to keep in mind is that the CAN Filter bits ONLY HAVE TO MATCH the CAN Header bits (the CAN ID Bits) if the corresponding CAN Mask bit is set to 1.
This means that you can do a “wildcard” filter by clearing all of the bits in the CAN Mask!
That said, you can set the 29 bit CAN Filter and CAN Mask with AT CF and AT CM respectively:
AT CF 18DAF110
AT CM 00000000In the above settings, since we’re clearing all of the bits in the CAN Mask, the CAN Filter itself shouldn’t matter at all. This SHOULD let us pass ALL messages through to the rest of the filter chain.
If we wanted to test this first filter, we might try to match JUST messages with the priority of 0x18 and then send a standard OBD II command to get the supported, standard PID’s:
>AT CF 18DAF110
OK
>AT CM 11000000
OK
>0100
18DAF110064100BE3FA81355Or at least… that’s supposed to work. I haven’t actually tried it yet…
CAN interfacing with the STN1100
But none of this should really matter all that much. It should be easier than all that! Basically, we just want the damn thing to spit back ALL of the nice raw CAN messages!
Here’s how you’re supposed to do that:
% screen /dev/tty.usbserial-FTDI_A 38400
>AT E1
>AT L1
>AT S1
>AT AT2
>AT H1
>AT AL
>AT SP 7
>AT DP Annnd that’s all setup. The important ones are AT H1 which turns on ALL header info, and AT SP 7 which sets the CAN protocol to use.
Once that is all done, apparently you’re supposed to be able to just do the following and get back a bunch of messages streaming from the car.
>AT MABut it doesn’t work… and I honestly don’t know why. I’m still looking into it…
