The code has been tested with the ScanGaugeII. Although only a few of the built-in display items are useful -- throttle position, temperature and load.
ScanGauge MPG gauge: improve your fuel economy - EcoModder.com
My board also monitors RPM, so I get that output as well.
There appears to be a way to display arbitrary PIDs (parameters) with the ScanGauge, but I haven't explored that yet. I structured the code so that the OBD2 reporting part was easy to understand and change, thus it should be easy to report other internal parameters.
The only hardware note is that the ScanGauge does not supply a CAN terminating resistor. CAN bus should have one on each end, and the diagnostic device is sometimes considered an end point. CAN does work if there is only a single terminator. It won't work with none, for instance if your circuit expects the resistor to be the other device. (I skipped putting the resistor on one of my test boards that I expected to be a "middle" node.)
The other minor note is that the ScanGauge report the voltage supplied to it, not the voltage reported by the controller. My controller code measures and reports the 5V supply, so it's not a subtle difference.
A note to Paul: My controller code uses the same approach as the Cougar firmware, measuring the motor current on alternate A/D measurement cycles. But on the "odd" cycles I sequentially sample
all of the ADC channels and store the result in an array adc_raw[]. I initially had a bitmap to skip 'unused' ones, but deleted that code because the optimization was pointless for performance. By making all of the conversions available over CAN, the firmware doesn't need to be changed when a temperature or voltage sensor channel is added.
The only special case is measuring Vcc (nominally 5V) by getting an A/D conversion of the internal 1.1V precision reference and inverting it for the report. I do this only once, at start-up, since changing Vref results in a noisy next conversion.
case 0x42: {
/* Control module voltage: 12V expected, we report 5V supply. */
uint16_t voltage;
/* Measure the 1.1V ref, round a bit to allow exactly 5.000V */
voltage = 1125000L / rt_data.raw_1_1V;
can_cmd.dataA = voltage >> 8;
can_cmd.dataB = voltage;
break;
}