Bit bang 5 baud with BS2 (on OBD2 ISO 9141)
Hi all,
This is my first time posting on the forum. I've used the BS2 since 2005 but have not really done a lot with serial communication using SERIN and SEROUT (other than simple LCD displays).
Now I've got a new fun project which is to interface with the OBD2 connector in my Honda Civic. The difficulty right now lies in initializing the ECU, which requires transmitting HEX 33 at 5 baud.
According to the Stamp manual, the baudmode for the SEROUT command for 5 baud (assume 8 bit no parity inverted) would be 199980 which exceeds 65535, so that won't work. So, I thought I would manually create and time bits via the HIGH and LOW commands (which I later found out is called bit-banging), but I'm not confident that the timing is right and I don't have a scope to verify the signal. PULSOUT will not work either, as the bit length is 200ms (max is 131.07ms on the BS2)
I am using a MAX222 line driver to get the outputs up to RS-232 voltage, so the bit bang is sent through this chip, which probably makes things more tricky. So far I have not been able to get a response from the car's ECU... Though there could be other things wrong, does anyone have experience bit-banging at a super low speed like 5 baud? I'd be interested in knowing if there is a better method to pull this off. Thanks everyone!!!
I'm also surprised I was able to get the username "n00b" on the forums... who would have guessed?
-Bobby
This is my first time posting on the forum. I've used the BS2 since 2005 but have not really done a lot with serial communication using SERIN and SEROUT (other than simple LCD displays).
Now I've got a new fun project which is to interface with the OBD2 connector in my Honda Civic. The difficulty right now lies in initializing the ECU, which requires transmitting HEX 33 at 5 baud.
According to the Stamp manual, the baudmode for the SEROUT command for 5 baud (assume 8 bit no parity inverted) would be 199980 which exceeds 65535, so that won't work. So, I thought I would manually create and time bits via the HIGH and LOW commands (which I later found out is called bit-banging), but I'm not confident that the timing is right and I don't have a scope to verify the signal. PULSOUT will not work either, as the bit length is 200ms (max is 131.07ms on the BS2)
I am using a MAX222 line driver to get the outputs up to RS-232 voltage, so the bit bang is sent through this chip, which probably makes things more tricky. So far I have not been able to get a response from the car's ECU... Though there could be other things wrong, does anyone have experience bit-banging at a super low speed like 5 baud? I'd be interested in knowing if there is a better method to pull this off. Thanks everyone!!!
I'm also surprised I was able to get the username "n00b" on the forums... who would have guessed?
-Bobby

Comments
I'll post a schematic soon with labels. One thing to note is I eliminated the capacitor between pin 5 and 6 on the MAX222 in order to "fake" the output of the chip to 0v/+12v logic. Otherwise, it would follow the +/-12v typical RS-232 logic. This choice is based on other OBD2 ISO 9141-2 interpreting chips which don't seem to go negative voltage. This change seems to have no effect when talking between two MAX222 chips (can send and receive data fine at 10400 baud), but I can't tell if the OBD2 interface likes this or not.
At this time I'd like to only get feedback on the timing for a 5 baud bit bang... my wiring and voltage levels could have other problems.
I just don't want to take the easy road out and get an ELM323... If there's a way to initialize the ECU with a BS2 bit bang, I aim to figure it out! Thanks everyone.
'' {$STAMP BS2}' {$PBASIC 2.5} 'This program is designed to initialize a 2000 Honda Civic DX FI-ECU. 'The message sent to the ECU should be HEX 33 (Binary is "00110011") on K line at 5 baud assuming 8 bit no parity inverted 'The message received by the stamp should be HEX 55 at 10400 baud (8 bits no parity true) which I calculate as baudmode=76 'MAX222 inverts signal so that is why I use "true" on the polarity 'It appears from various searches on the internet that ISO9141-2 standard runs on 0v logic high and +12v logic low. 'pin 2 is BS2 TTL signal being output to MAX222 'pin 5 is BS2 TTL signal being input from MAX222 serData VAR Byte 'define serdata LOW 2 'set output low to prepare ECU (+12v is logic low) PAUSE 6000 'wait 6 sec for ECU to reset DEBUG "Start init sequence...",CR HIGH 2 'start bit 200ms (Logic high, 0v) PAUSE 200 LOW 2 'make output low for 400ms (Logic low, +12v) PAUSE 400 HIGH 2 'make output high for 400ms (Logic high, 0v) PAUSE 400 LOW 2 'make output low for 400ms (Logic low, +12v) PAUSE 400 HIGH 2 'make output high for 400ms (Logic high, 0v) PAUSE 400 LOW 2 'Stop bit 200ms (Logic low, +12v) PAUSE 200 HIGH 2 'Make RS-232 output low to prevent collisions SERIN 5,76,5000,nodata,[serdata] 'receive 1 byte data on K line within 5 seconds 'should only take up to 300ms to receive according to ISO standards DEBUG ? serdata,CR 'display received data END nodata: 'SERIN timeout loop DEBUG "no data",CR ENDYour Start bit is 200ms, your data bits high/low are 400ms ea., and your Stop bit is 200ms.
Ordinarily, a Start bit takes the same time as a data bit, likewise a Stop bit though they can range up to 1.5 bit times.
So, I think that your data bits should be 200ms (too).
I think the problem with my setup was the MAX222 simply is not supplying the right voltages for the ISO9141 protocol (0v, +12v). I still plan on posting all the code and (new) schematics once I get a chance. Thanks everyone!!!
$33 = $00110011
N00b,
The byte is transmitted lsb first as:
111111111101100110011111111111111 '
My question has to do with what the program does after the stop bit Usually the RS232 line stays in the STOP state after transmitting a byte. Is there something different about the ECU? This instruction puts the line in the START or BREAK state. You have,
1111111111011001100100000000000000000 ' <--BREAK!
You're right, that was also a flaw in my program. I have to keep reminding myself that the ISO9141 bus idles at +12V = logic 0. I'll post an update later tonight to show what the new program and schematic looks like.
' {$STAMP BS2}' {$PBASIC 2.5} 'This program is designed to initialize a 2000 Honda Civic DX FI-ECU, and read mode 01, PID 00 (Lists the PIDs supported for the ECU) 'Pin 2 high means ECU logic low 0.2v 'Pin 2 low mean ECU logic high +12v serData VAR Byte(3) 'define serdata as array of 3 bytes confirm VAR Byte 'define confirm as byte senddata VAR Byte(5) 'define senddata as array of 5 bytes recdata VAR Byte(8) 'define recdata as array of 5 bytes LOW 2 'ECU idles at logic high +12v 'so, set TTL LOW to idle ECU at 12v 'as a result pin 5 is sensing 12V PAUSE 5000 'If K-line senses 12V for over 5 sec, it requires re-initialization (per ISO standard) DEBUG "Start init sequence...",CR HIGH 2 'start bit, make output high for 200ms (ECU low, 0.2v) PAUSE 200 LOW 2 'make output low for 400ms (ECU high, +12v) PAUSE 400 HIGH 2 'make output high for 400ms (ECU low, 0.2v) PAUSE 400 LOW 2 'make output low for 400ms (ECU high, +12v) PAUSE 400 HIGH 2 'make output high for 400ms (ECU low, 0.2v) PAUSE 400 LOW 2 'Stop bit, make output low 200ms (ECU high, +12v) PAUSE 200 DEBUG "waiting...",CR SERIN 5,76,5000,nodata,[STR serdata\3] 'receive 3 bytes data on K line DEBUG HEX serdata(0),CR 'display received data (hex 55) DEBUG HEX serdata(1),CR 'display received data (hex 08) DEBUG HEX serdata(2),CR 'display received data (hex 08) PAUSE 40 'pause 25-50ms before sending next byte (per ISO standard) SEROUT 2,16460,[$F7] 'send hex F7 (inverse of 08) DEBUG "waiting...",CR SERIN 5,76,5000,nodata,[confirm] 'ECU should send confirmation within 25-50ms DEBUG HEX confirm,CR 'display received data (hex CC) pidrequest: 'loop to request valid PIDs for the ECU PAUSE 20 'must transmit any requests within 55ms-5 seconds (per ISO standard) 'I found I can actually transmit within 20ms... go figure DEBUG "Ask for PIDs...",CR SEROUT 2,16460,[$68] 'Transmit 68 6A F1 01 00 C4 SEROUT 2,16460,[$6A] 'It turns out no pause is necessary between bytes, despite what I read on other sites. SEROUT 2,16460,[$F1] 'Previously I was trying a FOR...NEXT loop, but this did not work for some reason. SEROUT 2,16460,[$01] 'Using 6 serout statements is the only way I could get a response from the ECU. SEROUT 2,16460,[$00] SEROUT 2,16460,[$C4] DEBUG "Receive PIDs...",CR SERIN 5,76,5000,nodata,[STR recdata\8] 'Receive 8 bytes of data DEBUG HEX recdata(0),CR 'display received data (hex 48) DEBUG HEX recdata(1),CR 'display received data (hex 6B) DEBUG HEX recdata(2),CR 'display received data (hex 0E) DEBUG HEX recdata(3),CR 'display received data (hex 41) DEBUG HEX recdata(4),CR 'display received data (hex 00) DEBUG HEX recdata(5),CR 'display received data (hex BE) DEBUG HEX recdata(6),CR 'display received data (hex 3E) DEBUG HEX recdata(7),CR 'display received data (hex B8) END nodata: 'SERIN timeout loop DEBUG "no data",CR ENDSo, lessons learned? First, I had to remember which way the bits are inverting (or not inverting), depending on if I was sending or receiving a message. That was confusing at the beginning. Second, timing is everything (not having a method of flow control or a very finite idea of the ECU timing was frustrating).
One weird thing... the checksum byte returned (B8) doesn't seem to be correct. Adding up bytes 0-6 gives 510, so I think the checksum byte should be 510-255 = 255 (FF). I need to do a little more work to figure that out.
The other disappointment is that only a handful of PIDs are supported for my car (2000 Civic DX). The only somewhat interesting parameter I can read in real time is throttle position sensor. I was hoping to get more things like MAF, intake temperature, etc., but it appears such data is not output by this ECU (I'm sure I can get it if I tap into enough of the wires and use a A/D converter, but that wasn't what I had in mind).
Anyway, I'm just glad I got it working. There did not seem to be any solid "how-to" on Parallax forums for reading OBD2 data, so I'm glad I could share my findings with everyone. I hope other people expand on this topic and post some of their own projects!
can everyone helm me to convert BS2 code to C / arduino code?
I have same case, but I do not familiar with BS2
thank you everyone
BR from java island