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 [down under the switch body] 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.
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 (+) powerNote 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 16 bits at a time 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 1 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 totally 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.
The project to build more Prius Xgauges by observing what some
enhanced-mode scantools send to the car has started up. With
the caveat that there are still some bizarre data formats, I'll
field suggestions as to what other hitherto-mysterious parameters
might be useful -- I've only really just begun looking at this.
To summarize from the bits-n-bytes description above, I believe this pretty closely gives fuel injector time in milliseconds for the Prius:
TXD 07E021F3 RXF 0461 85F3 0000 RXD 3808 MTH 000A 0008 0000 NAM inj
[I separate pieces of RXF and MTH for clarity in seeing what they do, but you'd enter them as one long string.] Depending on small rounding errors which the scantool[s] may or may not have, MTH may want to be 000A 0008 0001 instead. For finer-grained filtering, RXF can look at more of the packet and instead become 0306 8461 05F3 -- doesn't really matter in practice.
Now, here's the fun part -- why it's good to have. As many of us know the Prius does quite a bit to optimize throttle control and load in response to driver demand, but always stay on top of the "mound" on the BSFC chart for best efficiency. This translates to high torque, lowest needed RPM most of the time. Remember the IGN 14 "valley" that one must sort of fight with to optimize during gentle acceleration or SHM? Injector time gives a much easier way to keep track of those boundary conditions some of us like to run in with the engine under good load but at the lowest RPM we can manage without letting it unload.
There seems to be a definite "plateau" of operation beginning around 5.0 milliseconds, when the injector pulse widens out to supply enough fuel to produce high shaft torque. This happens right before RPM begins to increase appreciably to increase overall power output; as RPM increases the injector time slowly widens out further to 6 and slightly beyond, and even up to around 7 as you push 3000 RPM which for many of us is as much "emergency hill-climb warp" as we're willing to give it. Watching injector time isn't so useful on the high side other than to try and keep a bit of a lid on it, but is definitely a significant factor on the low side since it indicates a> whether you're under load or not, and b> about where you are on the "possible RPM" scale inside of which you'll stay under load. The magic area seems to be from 5.0 to 6.something-low milliseconds, and trying to stay down near the low end of that range is yielding some really good segments.
Update: Subsequent studies indicate that the low end of this range, below 5.8 milliseconds or so, also falls off the peak efficiency curve somewhat at true highway speeds. See this later article for more details on power output and how to really optimize highway fuel economy, and for what is said below here apply the caveat that it may be too delicate an approach in many cases.
In other words, it appears to be about as close as an Xgauge gets to being that "sweet spot meter" I was fooling with a couple of years ago. That concept was in fact based on fuel injection, but integrated over time not quite the right way. It's easier to read than the IGN 14 thing since as you unload the engine, IGN can jump back up toward 17-18 as conditions head back basically toward idle and it's sometimes difficult to figure out which side of that "valley" you're on. In addition, IGN 14 doesn't show up at speeds above 53 or so MPH, which if you're out there doin' the 60 @ 60 dance isn't the right way to know your sweet spot. But injector time still shows the loading condition up into higher speed ranges, and tooling along above 60 MPH with the injectors locked in at 5.1 has the iMPG bar pegged right at 75 or 80.
Which segues into some of the equivalent conditions that one might observe in a stock, uninstrumented Prius, making it mostly possible to benefit from these observations even if there's no scangauge or tach to be had. Assuming a speed of around 55-60 MPH, here's a quick chart of rough operating parameters within the relevant range, matched up for comparison:
iMPG RPM inj 70 1500 5.1 - 5.2 50 1800 5.5 - 5.7 [seen over a fairly wide range] 35-40 2000 6.0 - 6.2
It's the same RPM range as we've discussed numerous times as being the most efficient band to stay in for highway travel; there's a reasonable correlation to iMPG at 60% SOC under steady-state conditions. This is about as close to DWL as a Prius gets, in fact. Much under 1500 and the engine rapidly unloads -- I've been seeing this with my vacuum gauge for years, so I'm intimately familiar with that "knee" that happens with insufficient foot pressure. But the injector time really shows that dropoff very sharply, and a quick glance to determine if we're at 5 or better allows riding that RPM down as far as we absolutely dare to hold a speed on the interstates and secondary highways in best fuel-sipping style.
Now, that "loaded RPM" range definitely shifts downward with vehicle speed. Even a fairly gentle startoff from the line yields injector times of high sixes or 7.x at ridiculously low RPMs like 1250, as high torque is produced to help takeoff. Wayne observed this when he was driving the Classic around. Once you hit about 30 MPH, the "I'm just loaded at 40 iMPG" axiom seems to hold true, so if conditions allow acceleration at that sort of rate [it's still pretty slow!] it will do much to *not* destroy your running average. I began playing with this by a bit of guesswork back at the "automotive challenge" event in NJ on the Pine Barrens flatlands -- not being able to watch "inj" at that time but simply trying to hold 40 iMPG and letting the car slowly build speed. Even on those 50 mph roads, I came back showing 72.something average in the MFD after 140 miles. If I'd had the more immediate indication of "inj" at the time I might have done even better.
Now, unfortunately it's not all that immediate since it's an active OBD-II query. I don't know if injector time is one of the bits of data flying around the bus we could listen to -- if it was, the number would change almost instantly. I've already found that placing my foot at the right place involves a little guesswork and then waiting for the update, and adjusting from there. A glance at the tach or the MFD can help confirm what's going on a little faster. Also note well that the injection time figure "freezes" at engine shutdown, and doesn't go back to 0. This is a known issue with several PIDs in the Prius, so something else is needed as an immediate engine-run indicator [RPM, a blinkielight, etc].
What I'd appreciate if some Prius pilots want to try this out, is to see if you don't find some really sweet tipping points around 5.1 ms that's probably the direct equivalent of SHM. And keeping track of this for applying minimum expenditure during low speeds and accelerations can really help overall averages -- like I've said before, there are some big differences to be had depending on how the front end and back end of a trip segment are handled. Hopefully this can help.