ISO9141 (automotive communication) on a microcontroller - Page 1
Forum section: electronics / general

author: cyclin_al
author_rank: Frequent Contributor
timestamp: June 28, 2018, 04:57:45 am
content: I have seen a number of projects and simulators doing automotive-related projects with CANbus. This is inspiring me to look into something similar for my car, which uses an older protocol ISO-9141.For a CANbus example, there is something called Carloop (carloop.io) which is basically a CAN transceiver and a STM32F205 microprocessor.I imagine doing something similar, using the same STM32F205 processor module and a E-L9637D K-Line transceiver chip.The microprocessor has built-in CANbus support, which means that ISO-9141 probably involves bit-banging or similar effort.My questions are is this a reasonable approach? Do I have a decent chance of success? Are there resources or advice from anyone who has worked with this protocol? Are there certain things I should look out for?I realize my questions are general at this point, but I expect I will get more specific and technical as I get into this.At this point, equally general advice is appreciated. My background is engineering, but I have been away from actual technical work for close to 20 years; I can appreciate this project will be slow, but I am willing to dig into it over time.Thanks in advance!

author: mikerj
author_rank: Super Contributor
timestamp: June 28, 2018, 04:15:29 pm
content: ISO-9141 and ISO-14230 can be implemented with a UART, the only bit bashing that may be required is the slow initialisation (5bps) which may be outside the range of the baud rate divisor.The official protocol standard document is not free, but there are plenty of code examples around. It can be quite easily implemented on a 8 bit micro so there should be no problems with an STM32.

author: carl0s
author_rank: Unknown
timestamp: June 28, 2018, 10:08:39 pm
content: Yes just use the L9637D with a 510 ohm pull up resistor on a UART. Some guy is even selling little breakout boards with the chip and a small SMD pull up across the pins on eBay.You will get an echo (read what you send), as its single wire. You are supposed to read this in and verify each byte received matches what was sent - collision detection. In my code though I simply run a counter of bytes sent, and then I dump that number of bytes from the serial input buffer.I'm probably going to re-do my code under FreeRTOS, because I have so many timers running on the loops to prevent any blocking (my code does K-Line, as well as read another uart stream from a Zeitronix AFR controller, and logs to SD at the same time), but it works well even without an RTOS. I do fast init for the K-Line, where you just drop the TX low for 25ms. You disable UART, drop the tx pin low for 25ms, then bring it high again, then re-enable UART. The 25ms drop can be picked up as a stray '0' on the serial receive buffer though, so I throw away that byte too.After fast init I then I ask the ECU for its limits in terms of timing (what I call the kwp_wait_time.. time between one request and another, or a response and another request, as well as varying the inter-byte delay etc.), and I then set the comms to use those timings. Actually no that's not true.. That's what I intend to do. I actually asked my ECU for the limits once, ages ago, and I use those as static values. I request a switch to the faster timing, and as long as its accepted, I switch to them.The KWP packet starts with source, dest, etc, and a length byte (which can be part of the FMT byte, or can be separate). I read the length, and if the length is bigger than a constant I call 'KWP_PARTIAL_RECEIVE_SIZE' or something, then what I do is I then leave the receive function, and come back when the serial buffer has that many bytes in it. So I can get on with other stuff. This worked really well.My code is on a PC in the garage that's switched off and had its network cable pulled back into the house. I've not looked at it for a few months now since basically cracking it. I'm trying to learn about other stuff now and build a usable workspace at home before I get back to it. Also at this stage I don't want to just give all my code away, no matter how crappy it might be (I may look to sell a completed datalogger or two), but I would gladly give you the gist of it when I can get to it.

author: carl0s
author_rank: Unknown
timestamp: June 28, 2018, 10:30:17 pm
content: Also, I built mine on an Adafruit Feather M0. I have a Blue Pill stm32f103 here though, and will probably be trying to move it to that. I think I am all in for stm32 now.

author: firehopper
author_rank: Frequent Contributor
timestamp: June 29, 2018, 12:28:40 am
content: look for a elm 327 or something bridge chip?

author: carl0s
author_rank: Unknown
timestamp: June 29, 2018, 01:19:06 am
content: Quote from: firehopper on June 29, 2018, 12:28:40 amThat's a bad idea. ELM just does OBD. You will be able to query one PID at at time at about 4Hz. If you want to query 3 PIDs, you'll see ~1.3HzUsing KWP and manufacturer specific requests, via $22 (read data by common identifier), you can get ~63 bytes per request. i got those 63 bytes at ~20Hz if I recall correctly. it's not CANbus, but it's better than OBD.For the BMW, there are lots of commonidentifier codes, same for VAG, and Suzuki bikes etc. One is 'analog values', and gives 63 bytes in the response - some are 32 bit words etc though, but still there's about 40 engine parameters - temperatures, TPS, wheel speeds, injector duration, spark advance, etc. Another is DigitalValues. This says if the side-stand is down on a bike, or if operating in closed loop, etc. I am pulling in both of those requests so I end up with ~12Hz overall or something. I can't quite remember.I seem to remember getting up to 33Hz with the smaller digital values request, but it was unstable, and I need to make two different requests alternately (digital and analog). It is only 10400bps though and you have to make the request each time. Also I was using a 10 meter OBD cable from the house to the garage which may have added to the instability.ELM327 was hopeless. In fact I started my project with the Freematics OBD2 thing and it was a total dead end for a data logger or anything that you want a decent update-rate with.Specs here:http://www.internetsomething.com/kwp/

author: cyclin_al
author_rank: Frequent Contributor
timestamp: July 01, 2018, 04:44:26 am
content: Thanks for the great advice @mikerj and @carl0s. That is promising and better than I hoped to be able to use a UART. Thanks also for that reference material; it will be invaluable to this project.I had looked at the elm327, which was interesting in that it is multi-protocol, but it was limited to the OBD PIDs only. I am looking for full access to the K-Line, which is beyond the elm327. Although, once the K-Line is working, then it would not be difficult to do an elm327 emulator (covering ISO9141, KWP2000, KWP fast init and CANbus).How close is the KWP protocol to the ISO9141? When I searched for code examples for ISO9141, I only found this one (which is not yet working): github.com/iwanders/OBD9141. Update: just found two others on github; need to look into those. I know now to also search for KWP-based code examples, but my current knowledge is that they are not the same.

author: carl0s
author_rank: Unknown
timestamp: July 02, 2018, 11:47:49 am
content: Quote from: cyclin_al on July 01, 2018, 04:44:26 amKWP / K-Line on BMW seems to follow the spec perfectly. I also found examples on other forums of people making gear-indicators for Kawasaki and Suzuki bikes, and, while I don't think they realised it, their code pretty much followed the spec too (e.g. positive response being request + 0x40). That code you have just linked to, shows this in the comments:QuoteAgain, that is all in the docs (part-3 is what you want) ;Also, you can see that in his comments there, he is doing a 0x01 service ID request. This comes under the OBD standard J1979. So those will be universal, basic, PID polling type requests.At least that code is clean though. Mine is very much a 'learning C/C++ and asking a lot of questions on IRC'. I have so many global variables :-/edit: ah, I just realised - that project there is called OBD-9141. It is just meant to cover basic OBD stuff. More optimisation can/should be done when you get into manufacturer specific data responses of ~63 bytes per response etc (e.g. the partial-receive/buffering I mentioned previously). I got my data by sniffing and pulling apart the BMW diagnostics s/w by the way. For VAG, there's loads of info. What vehicle are you working with?

author: carl0s
author_rank: Unknown
timestamp: July 02, 2018, 11:52:50 am
content: Quote from: cyclin_al on July 01, 2018, 04:44:26 amKWP is the keyword protocol (ISO 14230). This runs over the physical K-Line (ISO 9141). That's my understanding anyway.https://en.wikipedia.org/wiki/Keyword_Protocol_2000

author: mikerj
author_rank: Super Contributor
timestamp: July 02, 2018, 04:46:57 pm
content: Quote from: carl0s on July 02, 2018, 11:52:50 amNot quite; ISO 14230 and 9141 share the same physical K-line interface, but each specification defines it's own protocols and initialisation schemes (which are similar, but not the same).

author: jnz
author_rank: Frequent Contributor
timestamp: July 02, 2018, 09:03:44 pm
content: Quote from: mikerj on July 02, 2018, 04:46:57 pmISO14230 does not have to use K-line at all.See: Keyword 2000 Over CAN (Every Chrysler vehicle from 2007-2015ish)

author: cyclin_al
author_rank: Frequent Contributor
timestamp: July 03, 2018, 02:22:44 pm
content: @carl0s, The forums associated with the code that I linked to indicated that the code was not working. Given what you have said, the code must be very close or has been fixed. I will give it a fair chance then, and take a dive in.@jnz, I have to disagree about your statement on Chrysler vehicles. I have a 2015 RAM 1500 that uses CANbus on the main CANbus (at the OBD connector) and on the secondary CANbus (accessed in the dashboard, beside/behind the radio/infotainment unit). That worked just fine using the CANbus support on the STM32F205 and a TJA1049 transceiver.@mikerj, it is also my understanding that the ISO9141 and the KWP protocols are different but similar, and they all use the K-Line hardware layer.As for manufacturer specific codes, I am working with a 2004 Subaru Impreza (north American). I actually have a second car for parts, and can pull out the modules to make a bench

author: mikerj
author_rank: Super Contributor
timestamp: July 09, 2018, 10:30:21 pm
content: Quote from: jnz on July 02, 2018, 09:03:44 pmISO14230 defines the physical layer, so if it's using CAN then it's not ISO14230. ISO15765 covers the use of KWP2000 (the application layer of ISO14230) over CAN.

author: RussEnterprises
author_rank: Newbie
timestamp: July 15, 2018, 09:54:17 pm
content: Cyclin_al,I was working on a project several years ago where I needed to use an Arduino to log ODB-II data from a '99 Mazda that used ISO-9141. I found another project at the time that was using ODB-II to collect fuel usage data, so I used part of that as the basis for my project. The ISO-9141 code in that project didn't work (at least not with my car), but I was able to make some changes and get it working. My project used an MC33290 for the K-Line interface, if I remember correctly, initialization was done with bit-banging, and then everything was handled by the UART.Here's a link to the project, it appears that they included my changes to the ISO-9141 code:https://github.com/Magister54/opengauge/tree/master/obduinoIt's pretty old, but it worked at the time, so it might be helpful to you.Russ

author: cyclin_al
author_rank: Frequent Contributor
timestamp: July 21, 2018, 03:47:00 am
content: @RussEnterprises,Thank you! That Arduino project on Github is pretty much exactly what I was looking for. It should give me all the information I need since it had the K-Line interface actually working. I think I can turn this into a library for K-Line, and make it more general than just the OBD2 PIDs. Of course, once that is working then it would be easy to expand with an OBD2 object or an ELM emulator object.I have decided that I will be focusing on using the Particle Photon/Electron/RedbearDuo modules. These use the STM32F205 and the Wiring language. In theory, whatever I come up with could be ported back to an Arduino library fairly easily.