Here is a video of the prototype:
This hack will come in handy if you want to mount, say, an SV650 gen2 gauge on a gen1 bike. Without the data stream from the ECM, the gen2 gauge will be stuck displaying "CHEC", and no way to show engine coolant temperate. Documented here is a way to fix that.
Other potential use for the circuit is to make dual use of the temp readout. Bike voltage could be displayed, or Distance Till Empty (only down to 68 miles as that is the lowest display value) if connected to a fuel gauge (in the works :naughty
.
This mod works on the SV650, and may work on other Suzuki gauges, like the GSXR, but I have not tested those.
Step 1 to make this work was deciphering the data stream from the ECM. Using a logic analyzer it was determined that the ECM transmits an 8 byte message once every 100mS (ten times a second). The 8 byte message consist of 7 data bytes, followed by 1 check byte. Bytes are transmitted 10mS apart, with a 30mS gap between message repeat.
See the PIC source code below for the data format.
The challenging part of making this work was figuring out the code for the check byte at the end of the data stream. It's typical to use a CRC (Cyclical Redundant Check; there is a good description on Wikipedia if you're interested). I tested all the common 8 bit CRCs but none matched. Am I doing it right? Are the bytes reversed? Is the bit order correct...?
Without the proper code byte at the end of the data stream it's impossible to make "CHEC" go way. Having the proper data is not enough. The code byte at the end must match too.
I was about to give up, defeated, when it dawned on me that the check byte might not be a CRC at all. A simpler method is to use CheckSum (check the easy things first, right?!). CRC performs division, CheckSum is simple addition. After a few checks, turns out it was CheckSum not CRC! Haha, I was thrilled!
In hindsight it makes sense that the check byte was not CRC. CRC is quick calculation in hardware, but without a dedicated circuit (SV's ECM probably doesn't have one) it takes many cycles in software. A software checksum is a faster to perform than a CRC and would leave precious processing time for the ECM to perform other functions. Checksum it is.
Here is the prototype I'm sending to brle7817 to test with his GSXR gauge. The potentiometer (variable resistor) sticking out the top is for testing and gets removed when the real ECT thermistor is hooked up.
Schematic
MikroElektronika BASIC Source Code
Intel Hex File, Programming data for PIC 16F1847, if you'd like to burn a copy of the chip for yourself.
This hack will come in handy if you want to mount, say, an SV650 gen2 gauge on a gen1 bike. Without the data stream from the ECM, the gen2 gauge will be stuck displaying "CHEC", and no way to show engine coolant temperate. Documented here is a way to fix that.
Other potential use for the circuit is to make dual use of the temp readout. Bike voltage could be displayed, or Distance Till Empty (only down to 68 miles as that is the lowest display value) if connected to a fuel gauge (in the works :naughty
This mod works on the SV650, and may work on other Suzuki gauges, like the GSXR, but I have not tested those.
Step 1 to make this work was deciphering the data stream from the ECM. Using a logic analyzer it was determined that the ECM transmits an 8 byte message once every 100mS (ten times a second). The 8 byte message consist of 7 data bytes, followed by 1 check byte. Bytes are transmitted 10mS apart, with a 30mS gap between message repeat.
See the PIC source code below for the data format.
The challenging part of making this work was figuring out the code for the check byte at the end of the data stream. It's typical to use a CRC (Cyclical Redundant Check; there is a good description on Wikipedia if you're interested). I tested all the common 8 bit CRCs but none matched. Am I doing it right? Are the bytes reversed? Is the bit order correct...?
Without the proper code byte at the end of the data stream it's impossible to make "CHEC" go way. Having the proper data is not enough. The code byte at the end must match too.
I was about to give up, defeated, when it dawned on me that the check byte might not be a CRC at all. A simpler method is to use CheckSum (check the easy things first, right?!). CRC performs division, CheckSum is simple addition. After a few checks, turns out it was CheckSum not CRC! Haha, I was thrilled!
In hindsight it makes sense that the check byte was not CRC. CRC is quick calculation in hardware, but without a dedicated circuit (SV's ECM probably doesn't have one) it takes many cycles in software. A software checksum is a faster to perform than a CRC and would leave precious processing time for the ECM to perform other functions. Checksum it is.
Here is the prototype I'm sending to brle7817 to test with his GSXR gauge. The potentiometer (variable resistor) sticking out the top is for testing and gets removed when the real ECT thermistor is hooked up.
Schematic
MikroElektronika BASIC Source Code
Code:
program SV650_ECM_Serial_Hack
'Date: March 14, 2012
'Part: PIC16F1847
'Design: TeeRiver, at SVRider.com
'Ver:1.0
'Use: SV650 Gen2 ECM Serial Stream Emulator
dim ecm_serial_byte as byte[8] '8 bytes, 0 thru 7
dim check_sum as byte
dim index as byte
dim adc_value as word
const dealer_mode = 0
const temp = 0 '0 thru 1023
const C11 = 0 'Undefined for SV650
const C12_CKP = 0
const C13_IAP = 0
const C14_TPS = 0
const C15_ECTS = 0
const C21_IATS = 0
const C22_CAM = 0 'Not used on SV650
const C23_TOS = 0
const C24_IG_Coil_1 = 0
const C25_IG_Coil_2 = 0
const C28_STVA = 0
const C29_STPS = 0
const C31_GPS = 0
const C32_FI_1 = 0
const C33_FI_2 = 0
const C41_FP_Relay = 0
const C42_IG_Switch = 0
const C43 = 0 'Undefined for SV650
const C44 = 0 'Undefined for SV650
const C49_PAIR = 0
const Adj_TPS_0 = 0
const Adj_TPS_1 = 0
'##############################################################################
sub procedure Boot_up()
'Set internal oscillator
OSCCON = %01110000 '8MHz
'Set all PIC I/O to DIGITAL, except for ADC1
ANSELA = %11100010' Configure all 5 PortA AN pins (A4:A0) as DIGITAL I/O
ANSELB = %00000001' Configure all 7 PortB AN pins (B7:B1) as DIGITAL I/O
'Set I/O port direction
TRISB = %11101011 'B4 is test strobe, B2 is UART TX
TRISA = %11111111
'Initialize the UART
UART1_Init(7800)
end sub 'Boot_up
'###############################################################################
main:
Boot_up()
'Initialize ECM Data Stream
for index = 0 to 7
ecm_serial_byte[index] = $00
next index
'Assign Error Code bits to data stream
ecm_serial_byte[1].4 = dealer_mode
ecm_serial_byte[3].0 = C11 'Undefined for SV650
ecm_serial_byte[3].1 = C12_CKP
ecm_serial_byte[3].2 = C13_IAP
ecm_serial_byte[3].3 = C14_TPS
ecm_serial_byte[3].4 = C15_ECTS
ecm_serial_byte[3].5 = C21_IATS
ecm_serial_byte[3].6 = C22_CAM 'Not used on SV650
ecm_serial_byte[3].7 = C23_TOS
ecm_serial_byte[2].0 = C24_IG_Coil_1
ecm_serial_byte[2].1 = C25_IG_Coil_2
ecm_serial_byte[4].5 = C28_STVA
ecm_serial_byte[4].6 = C29_STPS
ecm_serial_byte[2].2 = C31_GPS
ecm_serial_byte[2].3 = C32_FI_1
ecm_serial_byte[2].4 = C33_FI_2
ecm_serial_byte[2].7 = C41_FP_Relay
ecm_serial_byte[1].0 = C42_IG_Switch
ecm_serial_byte[1].5 = C43 'Undefined for SV650
ecm_serial_byte[4].3 = C44 'Undefined for SV650
ecm_serial_byte[4].7 = C49_PAIR
ecm_serial_byte[1].1 = Adj_TPS_0
ecm_serial_byte[1].2 = Adj_TPS_1
ecm_serial_byte[0] = temp >> 2
ecm_serial_byte[1].7 = temp.1
ecm_serial_byte[1].6 = temp.0
while true
portb.4 = 1 'Test strobe
'Read the ECT thermistor
adc_value = ADC_Read(1)
'Assign thermisor adc voltage to serial data stream
ecm_serial_byte[0] = adc_value >> 2
ecm_serial_byte[1].7 = adc_value.1
ecm_serial_byte[1].6 = adc_value.0
'Calculate the checksum.
check_sum = 0
for index = 0 to 6
check_sum = check_sum + ecm_serial_byte[index]
next index
'Calculate two's compliment
check_sum = 256 - check_sum
'Send the datastream
for index = 0 to 6
UART1_Write(ecm_serial_byte[index])
delay_ms(10)
next index
UART1_Write(check_sum)
'Inter-message gap
delay_ms(30)
portb.4 = 0
wend
End.
Intel Hex File, Programming data for PIC 16F1847, if you'd like to burn a copy of the chip for yourself.
Code:
:02000000E028F6
:0C0006000E30FD00FD0B05280000080076
:1000120048302000B7000030B8004530B900003049
:0E002200BA00F03021009E009D011D14080060
:10003000D6302000A1000030A2004230A3000030E2
:10004000A400FF30B300FF30B4000030B500003032
:10005000B600FF30AF00FF30B0000030B10000301C
:10006000B200FF30BB00FF30BC000030BD000030EC
:10007000BE0023009E1690309D0021008D140D11AE
:100080002000911E472823001908F000402808008E
:10009000833021009D0520004508F000F035F03543
:1000A000700821009D0403209D149D1C5928000008
:1000B00055281C08F100F0011B0870042000C60040
:1000C0007108C7000030C7044608F0004708F10077
:0200D000080026
:1000D2002000F801F9011030FC00710DF80DF90D46
:1000E2007408F8027508031C750FF90203188028BA
:1000F2007408F80775080318750FF9070310F00D57
:08010200F10DFC0B6E28080052
:10010A00092020004208C50048207008C300710871
:10011A00C40021001D1020004308F0004408F1002B
:02012A000800CB
:10012C00703021009900E23023008C0001308D00EA
:10013C00FB3021008D00FF308C0023009F159C01AB
:0C014C00FF309B009C011E1518200800CD
:100158002000FB01FA01F9018030F800F10CF00CE5
:10016800031CBF287408F90775080318750FFA07E8
:100178000318FB0A0310F01FC7287408FA0775084C
:100188000318750FFB07FB0CFA0CF90CF80C031C91
:10019800B2287B08F3007A08F2007908F1007808A1
:0401A800F00008005B
:1001AC0023009E18DB280000D628200042082300DC
:0401BC009A0008009D
:1001C00096202000BF0125308600003087003F08C0
:1001D00086070318870A81013F08073A0319F228A6
:1001E000BF0AE32826122810A8102811A8112812E7
:1001F000A8122813A8132710A710A9122913271132
:10020000A7112712A7132610A612A911A913A61029
:100210002611A501A61326130D160130C200852054
:100220007008AD007108AE006430F400F501AC2038
:100230007008C0007108C1002D08F0002E08F10000
:100240005E30F400F501AC2070084002F000710847
:10025000413BF1006430F400F501692070082D077E
:10026000F30071082E3DF4007308AD007408AE0071
:100270007308F0007408F100F136F00CF136F00C60
:100280007008A500AD184629A6134729A6172D18F2
:100290004B2926134C292617A001BF0125308400C5
:1002A000003085003F0884070318850A0008A0076E
:1002B0003F08063A03195E29BF0A4E292008003C70
:1002C000A000BF0125308400003085003F0884076E
:1002D0000318850A0008C200D6201A30FC00F83046
:1002E000FD00FD0B7129FC0B7129000020003F0867
:1002F000063A03197D29BF0A62292008C200D620C8
:100300004E30FC00EB30FD00FD0B8429FC0B8429F2
:0803100020000D120C298B29BD
:020000040001F9
:04000E00A43F1316E2
:00000001FF