I have collected another bunch of information, and have a definite lock
on some outright protocol bugs in the Scangauge. But for the moment,
it is serving as a primitive network sniffer well enough to begin
reverse-engineering some scantool data.
.
This is greatly facilitated by having thrown together this little unit:
.

.
Pin 1 of the DLC is marked with a little red triangle on the left side,
and the terminating resistor fakeout by the red arrow on the right. All
the connectors have power and ground. The car gets connected with the
Scangauge cable to jack 2, the scangauge gets a short cat5 jumper from
jack 1, and the scantool goes into the DLC on this box. The switch either
connects the CAN leads to all three, or cuts off the connection to the car
and creates a stub network between jack 1 and the DLC by dropping the
60-ohm or thereabouts resistor across the CAN leads between them. This
allows the scantool and the scangauge to keep talking to each other
without the car's running chatter interfering with data collection. The
two bare junctions hanging in space are CANH and CANL in case I want to
clip onto them for further messing around later. Or short them together
and watch the car go into omfg-the-universe-is-ending-in-fiery-death mode..
.
I decided to do things mostly in the RJ45 universe since I have some of
these old office wall-jack data/phone boxes kicking around, and the DLC
I pulled from the '04 Saturn happens to clip perfectly in the mounting
rails of the box. A blank panel holds the switch and the dual jack thingie
is a standard 110 style punchdown wired in EIA 568B configuration [which
made the mapping a little bit interesting].
.
Here's the pinout of the Scangauge cable.
Code:
J1962 DLC RJ45 color (EIA568B) what
1 nc
2 4 blue-white PWM/VPW (+)
3 nc
4 1 white-org chassis gnd
5 1 white-org signal gnd
6 2 org-white CAN hi
7 6 grn-white K line
8 nc
9 nc
10 5 white-blue PWM/VPW (-)
11 nc
12 nc
13 nc
14 3 white-grn CAN lo
15 7 white-brown L line
16 8 brown-white (+) power
.
Note that this represents a poor choice of pairing for high-speed CAN
data, since orange-white and white-green aren't twisted together in
standard cat-anything data cable. But it seems to work okay at 500 Kb.
.
Both the scangauge and scantool can ask the car for data at the same time
and for the most part not interfere with each other, although with the SG
connected I would occasionally see values blink to 0 on the scantool and
then recover. Since ECU replies are relatively slow and who knows how
frequently both devices ask, they could easily be getting each others'
answers now and again. No biggie, although the fact that this random
stomping is going on seems to trigger an odd cursor-positioning bug in
the Scangauge when going to edit an Xgauge. Anyone ever see the editing
cursor jump to some random place in the bottom line? Try editing a gauge
with the car turned off, you might see it in that state too.
.
To sniff the network, I have an Xgauge called "BUS" which uses TXD of
various passive-CAN flavors like 07 E7 or 07 E8 depending on what I want
bit 3 to be, or possibly 07 D0 for seeing the 7DF generic ID traffic.
The scantool can be set up to either ask for "Generic OBD-II" or "enhanced
powertrain". When in the former mode, it sends everything with id 7DF and
in the latter, uses 7E0 for "powertrain" and 7E2 when talking specifically
to the hybrid ECU. I think we pretty much knew this about the Prius, but
it's nice to see it actually on the wire. The rest of the Xgauge is RXF
of 0107 1000 0000 to just return any query/response type traffic and
display it in hex, 0001 0001 0000 for MTH, and I walk out along the packet
with RXD of 0010, 1010, 2010, etc. Klunky, but it does work. Sometimes
I have to add a little more to RXF to suppress some of the scangauge's
own traffic or stray keepalive stuff from the scantool.
.
Once the scantool is connected, I start asking for ONE parameter, and then
flip the switch. BUS then generally shows me what the scantool is sending.
Fortunately, the scantool doesn't take the sudden lack of answers from the
car as a disconnect event -- it just keeps asking, so I can then keep
editing RXD and build up the whole packet. Of course the Scangauge keeps
going to sleep until I poke it, since it can't read RPM and such and
assumes the car powered off.
.
For a totally generic OBD-II connection, the scantool sends 07 DF 02 01 00
as sort of an "are you there" query while trying to establish a connection
to the car. It isn't really a "connection" per se like stateful TCP, it's
just sort of a hello and an answer. Breakdown: CAN ID 7DF, the "any"
address ; OBD-II length of 02 ; mode 01 ; PID 00 meaning "give me the
mask for the first 32 supported PIDs". We don't see the CAN length,
since that's always assumed to be 8. [That's held in four bits of the
CAN header which is, confusingly enough, also called a DLC!] The car
answers with the ID of whatever ECU replies, but generally 7E8 for
engine/powertrain and 7EA for the hybrid ECU. One or more ECUs may
answer this query at once, too! Remember that all this 7DF/7Ex stuff
is completely arbitrary, defined by the SAE, but does have the quality
that CAN IDs that high are going to take a LOW priority on the bus and
not interfere with the high-rate non-OBD-II running chatter.
.
It is unclear if the 7E0/7E2 distinction is actually between the physical
engine ECU and the hybrid ECU in the Prius, since I'm sure that both are
smart enough to form up a response to either, but let's assume that
"powertrain" is handled mostly by the engine ECU. It doesn't really
matter; we just fire our questions into the big cloud and if we got the
protocol right, eventually out pops our Answer To All Things from the
Rolling Spaghetti Monster.
.
When the scantool isn't actually asking for any parameters but is connected
in "enhanced" mode, it seems to send a keepalive of 07 E0 02 3E 01. I
think the car replies with 07 E8 01 7E -- consistent with the protocol
including the mode bit-flip, but basically empty. If the scantool doesn't
get those back for a while it doesn't seem to care, it just keeps trying.
When a specific PID is being requested, these keepalives cease in favor
of sending the real query instead. Note that when getting any running
parameters, the queries are sent over and over -- at least once a second,
so one doesn't have to wait long for the BUS Xgauge to fill in.
.
Enhanced-mode queries to the Prius definitely use 07 Ex 02 21 yy where x
is specific to an ECU and yy is whatever PID is being requested. Always
a one-byte PID, not two like we see for Ford. Replies tend to carry a lot
of data, and I think some of these spill into multi-packet blocks but I
have yet to work up a way to walk out those. Norm appears to be right
about this, particularly in the likelihood that MG torques and RPMs are
buried in some big block of hybrid-ECU data that is hopelessly beyond
the reach of an Xgauge as currently implemented.
.
Sufficient fooling around allowed me to finally dig up how to get fuel
injector open-time in milliseconds from the Prius, which I'll post more
about the benefits of in a separate thread so people can read it without
wading through all the protocol discussion. Basically, we want to send
07 E0 02 21 F3. We'll get back 07 E8 06 61 F3 xx yy zz qq -- see why?
Six bytes of return data from the powertrain ECU, mode/pid 61 F3 to
confirm what the answer is for, and then four bytes to dig the figure
out of. The same PID seems to be used for "injector milliliters" as
well as time, and it took a bit of guesswork to determine that I want
"zz" at RXD 3808. Next was how to scale it, and by comparing against
what the scantool says it seems to be given in eighths of a millisecond.
I can only theorize from the grouping of parameters in the scantool and
eyeballing BUS for a while that the milliliters is a 16-bit quantity
from "xx yy", and "qq" is something about fuel trim which seems to sit
near 7F or 80 which would be consistent with some other fuel-trim
figures we've discussed here already.
.
So how do we turn this into an Xgauge? Here's one of the most confusing
Xgauge bugs that I finally have a handle on and we really need to get Ron
to re-examine and fix. My best guess for injector milliseconds is
07E021F3 / 0461 85F3 0000 / 3808 / 000A 0008 0000 / inj. [Actually this
consistently deviated from what the scantool says by 0.1 millisecond, so
adding one in MTH brings them in line. The scantool might have an off-by-
one error in its own representation -- these things are far from perfect.]
Now, see what's missing from this definition? The QUERY LENGTH. There
should be a two in the middle, a la 07E00221F3, dammit. Ron deliberately
takes the length OUT of the definition but silently re-inserts it in the
CAN packet presumably based on the rest of the supplied data, which is one
of the major things that was confusing everyone's understanding of this
stuff. It certainly goes out on the bus and certainly comes back in the
reply -- note how the RXF uses 0461 05F3 [ignoring decimal-shifter bit,
and recall that RXF is one-based where RXD is zero-based], which skips
the two CAN ID bytes and the length? We must account for the OBD-II
length in the receive filters, but must SKIP it entirely in the TXD.
This is absolutely idiotic. Ron is dead wrong when he told me "the Prius
doesn't use the length byte", I see it right there from the scantool.
If I use RXF of 0306 8461 05F3, I now account for the return data length
and still see my injector time. But if I stick the 02 length into TXD,
it doesn't work.
.
If injector time is on the bus as a passively-readable packet, I have no
idea where it would be -- unfortunate, because having instant feedback
about this would be really useful instead of having to guess at a foot
position and wait for the update. More on this in the other thread. It
may be time to revisit the analog "sweet spot" meter idea, though.
.
I fooled around with some of the hybrid parameters, and found that there
are many parameters that are asked for with the SAME PID. Example: MG1
RPM, torque, inverter temperature, and several other things concerning both
MG1 and MG2 are all sent for via 07 E2 02 21 C3. The BUS Xgauge shows a
total, non-parseable mess of bytes in return, and I think I'm seeing the
last packet of a burst. For much of the hybrid ECU stuff, the format seems
to be big blocks of data with info about many things at once, and the poor
scantool writer gets to sit there and sort through it. It gets into the
area where Toyota decided they could do whatever they wanted in terms of
protocol and only grudgingly give out the particulars to those willing to
pay for them, and only in bad translations from Japanese with no further
explanation.
.
_H*