Clock pod mod with Subarb Select Monitor ECU polling and Arduino
+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 15 of 27

This is a discussion on Clock pod mod with Subarb Select Monitor ECU polling and Arduino within the Tutorials & DIY forums, part of the Tech & Modifying & General Repairs category; The check engine light: what does it mean!?! I check my engine often; it is always in the same place. ...

  1. #1
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Clock pod mod with Subaru Select Monitor ECU polling and Arduino

    The check engine light: what does it mean!?!
    I check my engine often; it is always in the same place. Go away, stupid light.

    As my car continues to age ungracefully, I am seeing this light come on with increasing frequency. When Iím out driving I donít necessarily have my laptop on me and a car parts store may not be nearby- a quick code check is not available. Should I have my car towed for what has lately been a P0420?
    I donít think so.
    Thus, I have been motivated to integrate the simple CEL code-reading functionality of learning view into my car.
    But why stop there: if I am going to be communicating with the ECU to pull the codes, why not build a sensor/memory polling mechanism too?
    Thus, my project is a simple LCD display, powered by an Arduino Uno which communicates over the OBD II connection using the Subaru Select Monitor (SSM) protocol.



    The plan for the end product is to
    -Integrate with the carís design in an unobtrusive manner: in the clock pod
    -replicate the original function of the clock pod: display the time
    - monitor a few interesting parameters:

    1) intake air temperature: I chose this since my car, unlike many new cars, does not have an exterior temperature thermometer
    2) Injector duty cycle: I have been having fuel learning issues, so I want to know if Iím reaching into the upper ranges of my injectors. Plus this is a pseudo-measure of in-use power.
    3) boost: my car came without a boost gauge.
    -read and display check engine light codes when the light is on in the dash display.

    This thread is a documentation of the development process rather than a tutorial; however I do intend to include all of the details which would enable anyone else to replicate this mod.
    Last edited by Obeisance; 09-05-2014 at 06:05 PM.
    David - '05 WRX

  2. Remove Advertisements
    ClubWRX.net
    Advertisements
     

  3. #2
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Integration with the Car

    I want this mod to look nice (note: this doesnít mean that Iím going to do a clean job, but the intention is good). The stock clock pod is an excellent size to fit a small LCD.


    I chose to use the Sparkfun Serial LCD Kit because the size of the LCD almost perfectly fits into the opening.
    I trimmed slots for the PCB to fit into, careful to maintain the clips for the original clock pod in case I ever want to revert, and twist tied the LCD in place. I also made a simple bezel with paint and some plastic packaging, and placed this in front of the LCD.

    One more thing: since the clock pod face plate was very well attached (I used much more force removing this clipped in piece than I would have liked), I trimmed the points off of the front clips using a hack saw (they still clip, but not quite as difficult to remove now).
    I installed the Arduino (with the custom shield, more on this below) and LCD into the clock area by running the USB cable down to the 12V power port (to power the arduino), running a wire down to the OBD II port (for signal), and connecting a lead to the ACC (+12V) line of the clock power dongle (as a signal pull-up line).
    I just closed the cover over this, leaving the parts to slide around- after all, what is one more rattle?

    Although the Arduino UNO can be powered with anywhere between 5-19V (i.e., it could be powered through the clock dongle), I chose to power it though USB by splicing a 12V to USB adapter into the 12V power/cig lighter. I chose this route so that I could program the Arduino (this is done over USB) by simply lifting the shifter boot and pulling out the USB cable.


    As a temporary solution, I spliced a line into the OBD II K-line (ISO 9141-2 comms) thinking that this would allow for simple communications. It turns out that the communications donít work without problems yet: I need to have my VAG-Com cable plugged in or else the communications wonít work. This means that my circuit is not finished.
    David - '05 WRX

  4. #3
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Hardware

    I found a few references which show that SSM uses a version of ISO 9141 communication- hence it shares data send and receive on a single line, serial communications (UART) at 4800 baud. It communicates at 12V, but the Arduino communicates at 5V.
    Although the Arduino has libraries built in which allow for serial communication, it is designed with separate transmission (Tx) and receive (Rx) lines. These lines idle with high voltage, and pull low to signal. In order to share them, and to communicate at 12V I’ve designed a simple circuit:

    I use the 12V from the ACC pin in the clock pod as an OBD signal pull up, 5V from the arduino as voltage pull up for the transistors, and I use the ground in the arduino as well as an extra connection to the ground wire in the clock pod harness.

    Currently, I’m using the software serial library in order to have multiple serial ports on the Arduino- this enables me to use separate serial communication to command the LCD, to troubleshoot with the Serial monitor in the Arduino (as well as program the Arduino without unplugging it) and to run the SSM communications.

    I also purchased a simple real time clock kit from digispark. It communicates using the I2C bus on the arduino, and is a simple solution which allows me to keep track of time, even when power is removed (+1: now I don't lose time when the battery is pulled; -1: now I have to use a laptop to set the time on the clock in the car).

    A note on soldering: it seems that my messy soldering (lots of flux everywhere) creates rather dirty circuits which can drastically affect the performance of the communication or of the crystal on the clock module. I washed the circuit with soapy toothbrush scrubbing so that everything worked.

    This is all fine for now, but the SSM communications only work in short bursts (I can only send a few hundred packets before there are reading mistakes): I suspect that there is some kind of extra capacitance in this circuit which causes a delay in voltage recovery, but have not tried to confirm this hypothesis. This is not a crippling problem, since I can just pause between each data point request.
    Last edited by Obeisance; 08-16-2014 at 05:50 AM.
    David - '05 WRX

  5. #4
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Communication Ė reverse engineering the reverse engineered software

    Before taking on this project, I knew nothing about serial communication. I tried to find tutorials on teh interwebs, but I didn’t easily find anything. Even on the romraider forums. Thus, I sought to intercept the packets which the romraider logger and learning view sent out when it was trying to communicate with the car. This way, I could at least try and send the same packets.
    My first stroke of luck was the log file which learning view leaves: it showed the ECU init packet as well as the response (and even the packet which needs to be sent to read CELs):
    WRITE 6 bytes: 80 10 F0 01 BF 40
    READ 68 bytes: 80 10 F0 01 BF 40 80 F0 10 39 FF A2 10 0F 3E 14 48 40 06 73 FA EB A2 2B C1 02 AA 00 10 00 60 CE 54 F8 B1 E4 80 00 E0 00 00 00 00 00 DC 00 00 45 1F 00 00 02 00 00 00 03 00 00 E0 00 00 00 00 00 00 00 00 8F
    ECU supported (ECUID:3E14484006 CALID:A4TF800F DESC:05 USDM Impreza WRX MT)
    Thus, I connected the Arduino to the K-line (pin 7) of the vag com cable, and powered it (line 16) and tried to pretend that the Arduino was the ECU:

    I even spoofed the ECU response, and was able to get learning view to communicate with the Arduino.
    I took another step, and was able to read packets from romraider (now as decimals instead of hexadecimal bytes:
    IAT: 128 16 240 8 168 0 0 0 18 0 0 100 166
    IDC: 128 16 240 14 168 0 0 0 32 0 0 14 0 0 15 0 0 100 215
    Boost (manifold relative pressure direct): 128 16 240 11 168 0 2 24 32 2 24 33 0 0 100 12

    As it turns out, the logger definitions show these addresses, and how to convert them to numbers:
    <parameter id="P11" name="Intake Air Temperature" desc="P11" ecubyteindex="9" ecubit="5" target="1">
    <address>0x000012</address>
    <conversions>
    <conversion units="C" expr="x-40" format="0" gauge_min="-20" gauge_max="60" gauge_step="10" />
    <conversion units="F" expr="32+9*(x-40)/5" format="0" gauge_min="0" gauge_max="140" gauge_step="20" />
    </conversions>
    </parameter>
    This shows that (hex) 0x000012, or (dec) 0 0 18 is the address for the IAT. The byte (decimal) returned should have 40 subtracted from it in order to give the IAT in Celcius.

    My circuit is even able to eavesdrop on the response from the ECU when installed in the car:
    Romraider request for IAT: 128 16 240 5 168 0 0 0 18 63
    ECU response: 128 240 16 2 232 84 190
    That gives 84 – 40 = 44 C as the intake temperature (a tad hot, but this was after a long drive and the engine bay had a bit of heatsoak).

    I’ve used this process to design the packet I sent to ask for the IAT, Manifold relative pressure (MRP), the injector duty cycle (IDC), and the CEL light status:
    It turns out that IAT requests one address, IDC requests 3 (two for engine speed, one for the injector pulse width that includes the latency), MRP requests two (manifold pressure and atmos pressure), and the CEL status requests one value.
    ECU poll: 128 16 240 23 168 0 2 24 32 2 24 33 0 0 18 0 0 32 0 0 14 0 0 15 0 1 150 154
    Bytes Translated: [begin packet, to ECU, from diagnostics tool, 23 bytes of data, A8- the read single address byte, set to 1 for fast polling, MRP, MRP, MRP, MRP, MRP, MRP, IAT, IAT, IAT, IDC, IDC, IDC, IDC, IDC, IDC, IDC, IDC, IDC, CEL, CEL, CEL, checksum]
    Last edited by Obeisance; 07-07-2014 at 09:14 PM.
    David - '05 WRX

  6. #5
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Programming

    This is an unpolished version (no clean up of unclever/messy code, but it works as intended). It turns out that the limited memory in the Arduino UNO is a bit of a hinderance. In order to overcome this, I’ve attempted to use program memory to store the CEL character strings. Further, I’ve borrowed some code which should enable me to watch how much RAM of the 2K I have free during the run (large arrays and many variables can eat this up fast).

    Also, Thank goodness for the romraider logger definitions and that community, since they've already answered many of my issues through their development.

    Updated: 2014-07-26

    https://drive.google.com/file/d/0ByG...it?usp=sharing

    https://drive.google.com/file/d/0ByG...it?usp=sharing
    Last edited by Obeisance; 07-26-2014 at 01:50 PM.
    David - '05 WRX

  7. #6
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Troubleshooting the circuit

    I'm surprise that I've received no response for this post; I'm proud to have been able to come even this far on this project.

    That's not to say that there are not better implementations of a similar idea: RomRaider ‚€Ę View topic - Arduino Based SSM Gauge

    Anyhow, I was looking at the cables in the OBD II port of my car, as well as the circuit in the Vag Com cable to see if I could understand why the cable allowed my circuit to communicate with the car.



    I noticed that not all of the cables are hooked up. In fact, although I had previously realized that the vag com cable could communicate with pin 7 or pin 15 (they seemed to send and receive the same bytes), the OBD port in the car does not have a connection with pin 15!. By looking at the two circuits, I can conclude that the power, ground and pin 7 are all that are involved in the communication.

    This means that I have narrowed down my sources of error:
    1) Perhaps my V+ in the clock pod is not correct, or maybe the pullup should be at the OBD port (the vag com cable effectively does this)
    2) perhaps my ground at the cigarette lighter is not the same ground as the ECU/OBD comms (not much of a chance of this, but the cable provides a common ground between them)
    3) There is still a chance that the comparator circuit is active in the communication.

    I can test these ideas with a multimeter. I will report back.
    David - '05 WRX

  8. #7
    Registered User gregroot198521's Avatar
    Join Date
    Feb 2011
    Location
    El Paso, TX
    Posts
    842
    Hmm, dig this, I'll have to do a real read up again later though.
    Hawkeye Alliance #1050
    Build Thread
    http://i1108.photobucket.com/albums/...ps665d9b9d.jpg
    Always dirty, never scurred......

  9. #8
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330
    Alright, I finally got around to checking the OBD II port with a multimeter and here's what I found:

    V+ (pin 16) is 12.XX V=battery voltage above ground (pin 4/5) and pin 4/5 matches chassis ground (why wouldn't it). No big surprises here. I measured Pin 7 vs 4/5 and got 6.XXV, and vs pin 16 and got -5.XX V, but I still had the arduino signaling turned on. When adruino signaling is disabled, I get -0.23 V vs pin 16 and 11.88 V vs gnd. (this means that the signaling is reaching the OBD port just fine, I believe)

    Placing a 1 kOhm or 10 kOhm resistor as a jump (pull-up) between 4 and 7 or 16 and 7 does not enable the communication to pass through, so it appears that the comparator is active rather than a voltage drop over the signal line causing the failure in communication.

    Also, I double checked the VAG com cable, and the only chip in it which is powered via OBD is the comparator (the FTDI chip is powered via USB). Ugh.
    David - '05 WRX

  10. #9
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330
    Alright, so I figured out my communication issue: one of my transistors was leaking current. At first I thought it was my shoddy soldering, so I took apart my circuit, and put it back together on another PCB.



    This didn't fix things, and I eventually found the bad transistor.



    Now, I've re-installed the arduino and it communicates without any issues. I've even got the CEL reader to work.

    The Boost/IDC gauge is not the fastest (there is a lag of a couple hundred milliseconds between my input to the car and the gauge displaying the response), but it does what I need it to.

    I've updated the code above.

    For future plans, I may end up adding a mechanism so that I won't have to unplug it to use the OBD port. I may also change to fast polling to try and increase the response time.

    The potential for using an arduino in the car is fantastic: I've seen implementations where the cruise control stalk on the steering wheel is used to select different logging parameters, and one could even write an interpretation code to use romraider's logger definitions so that this would not have to be inputted manually. In any case, I'm quite pleased with the result so far.
    David - '05 WRX

  11. #10
    Registered User
    Join Date
    Jan 2011
    Location
    Western NY
    Posts
    227
    Good job! This looks very interesting. I like the display on the new wrx and fxt, wish my 14 would display simple things like boost, coolant temp etc.

    Sent from my SAMSUNG-SGH-I747 using Tapatalk

  12. #11
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330
    Alright! I guess that my project was not done.

    I had designed the code so that whenever the CEL came on, the code would stop polling the ECU for data parameters and instead ask once for CEL codes based upon this line in the romraider logger def. v253:

    <switch id="S155" name="Malfunction Indicator Light (MIL) ON Flag" desc="S155" byte="0x000196" bit="7" ecubyteindex="56" target="1" />

    I asked for the memory address 0x000196, looked at bit 7 of the response, and if that bit was 1, I would consider the CEL on.

    Code:
    MILbyte = bitRead(MILbyte,7); //the 7th bit of this address byte indicates whether the MIL is on
    Well, I finally cleared my CEL and found that the arduino acted as if there was still a CEL. This means that this memory address is not an indication of whether or not I have a CEL and my code fails because of it. Either that or the bit index is off (if romraider counts starting at 1 and not 0, like bitRead) and I am asking about the 8th bit instead of the 7th. I'll have to give this a try.

    I then went to the Romraider page to find an updated logger definition, v263.
    In v253, the only mention of "MIL" (in the context of the MIL on, not mile) was in the line I posted above. In v263, there is more, so this is a developing part of romraider. I need to restructure my code. Maybe I'll change it to 1) ask for CEL codes only upon startup, 2) ask for the air temperature every 1000 poll points (so that the boost and IDC parameters are read faster).

    edit: some romraider logger defns. ask for a "bit = 0" thus I do not expect that my problem is from an indexing mismatch.
    Last edited by Obeisance; 08-08-2014 at 09:21 AM.
    David - '05 WRX

  13. #12
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    ECU communication and display latency

    Since I have to re-write to accommodate my inability to ask the ECU if the CEL is on, I would like to address the delay that the gauge has.

    I have come up with three major sources of delay, and will focus upon reducing two of them which are based upon serial comms. timing.

    1) Communicating with the LCD at 9600 baud
    2) Communicating with the ECU at 4800 baud
    3) Code inefficiency in math and algorithm

    The code originally polled the ECU each time it wanted a data point, and received a response. Then, it updated the parameters and displayed them on the LCD.

    I was polling the ECU for three parameters using seven addresses of three bytes each. Including the packet header, this is 28 bytes sent. The ECU would then respond with 13 bytes. Thus, each round trip parameter update took at least : (28+13)(bytes)*8(bits/byte)/4800(bits/s) = 68 ms.

    I had set the LCD to communicate at 9600 bits/sec using 8 bit bytes. Each time the LCD was updated included sending commands to move a cursor around, to display the data and to input special characters. I have not calculated the exact number of bytes sent, but I can assume it is not too many more than a full byte for each location on the LCD (32). Thus, I expect a full refresh of the LCD to take about 27 ms. This is about 37.5 Hz, just faster than a 30 fps perception limit.

    These processes happen in series, so their times are additive: 27 + 68 -> 95 ms/update, or about 10 frames per sec, which is easily perceived as a delay (not even counting the inefficiencies in programming).

    Here is how I intend to reduce the delay:
    1) shorten the number of polling bytes
    2) increase LCD communication speed

    Since I cannot figure out how to ask the ECU if the MIL is on, I will not even poll for that address. Additionally, I don't need to update the intake air temperature every cycle (since it is pretty constant over minutes), so I won't poll it every cycle either. This means I can reduce the number of bytes sent and received per cycle to about 33, giving a round trip time of 55 ms. This is still a bit slow, so I can enable fast polling mode by sending a "1" beore asking for addresses. This will make the ECU continue to send the response to the initial poll without having to keep asking. This reduces the number of bytes to 11, and the update time to 18 ms. That is about 54 Hz.

    The LCD communications can be sped up by changing the serial comms speed; since the LCD and arduino are adjustable, I'm not limited (as I am with the requirement for SSM to have 4800 baud). I can change the baud rate to 57600 bits/s to get a full LCD refresh time down to 4.5 ms, or about 225 Hz.

    Combined, I expect these enhancements to reduce the full cycle response time from 95 ms to 22 ms, or 43 Hz, well into a range where it will appear a fluid refresh. Assuming that my programming is not poor and that the arduino can keep up with the constant feedout of data from the ECU, hopefully this will all work out.
    David - '05 WRX

  14. #13
    Į\_(ツ)_/Į Rambo's Avatar
    Join Date
    Oct 2010
    Location
    Portland, OR
    Posts
    5,132
    I Support ClubWRX
    Very interesting. I had the same idea as you for this project, but you've taken it much farther than I ever did. I ended up using my arduino and LCD as the brains for a pachinko machine.
    Isaac -- 2003 WRX sedan Stg II - Gave its life for mine 6/2013.
    2007 Outback 3.0R wagon
    Proud owner of a N.E.R.D, Member 1.38◊10-23

    The pursuit of knowledge is hopeless and eternal... Hooray!!! - Professor Farnsworth

  15. #14
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330
    Quote Originally Posted by Rambo View Post
    Very interesting. I had the same idea as you for this project, but you've taken it much farther than I ever did. I ended up using my arduino and LCD as the brains for a pachinko machine.
    I remember seeing your post about your plan for this idea; if you're still interested you could always do something like it in the outback, since romraider has some outback ECU definitions and since the arduino is pretty cheap. It's been a fun project!
    David - '05 WRX

  16. #15
    Registered User Obeisance's Avatar
    Join Date
    Apr 2012
    Location
    not Ann Arbor
    Posts
    330

    Slightly faster polling

    updated code: https://drive.google.com/file/d/0ByG...it?usp=sharing

    edit: link to real time clock library, which is necessary for this code to work: https://github.com/adafruit/RTClib

    Well, it turns out that my expectation about how long it takes the code to run was way off. I used arduino's timing functions to estimate the time it takes for a full polling cycle.

    254 ms/cycle: My original code
    194 ms/cycle: When I switched the LCD to 57600 baud
    86 ms/cycle: above+ switching to the fast polling
    181 ms/cycle: no fast polling, but shorter data packets
    77 ms/cycle: above+ diagnostic serial at 57600 baud instead of 9600
    68 ms/cycle: above+but further shorten the packet so IAT is only polled every 60s

    This shows me three things:
    1) I underestimated the time that the LCD refresh takes (shortening it gained me 60 ms)
    2) I underestimated the time that the Serial diagnostics comms takes, thus by measuring the system I am influencing it (shortening it gained me about 100 ms)
    3) Although fast polling drastically reduces the cycle time, something about my setup causes loss of accurate byte transmission after about 5 read cycles (I suspect that the resistors are not right and the voltage cannot recover, hence data bytes are incorrectly read)

    In any case, I now have a v2 of the code; here are the changes:
    1) Reduced cycle time (increased temporal resolution for IDC and MRP, reduced for IAT)
    2) Included 20 new start up messages and 3 animations
    3) CEL codes are polled at startup and not at any other time
    Last edited by Obeisance; 08-22-2014 at 02:34 PM.
    David - '05 WRX

+ Reply to Thread
Page 1 of 2 12 LastLast

Quick Reply Quick Reply

Register Now

Please enter the name by which you would like to log-in and be known on this site.
If you do not want to register, fill this field only and the name will be used as user name for your post.

Please enter a password for your user account. Note that passwords are case-sensitive.

Please enter a valid email address for yourself. We strongly suggest that you stay away from using aol, yahoo, msn, and hotmail accounts. Sometimes the mail server blocks the emails from our server. As a result you will not receive any notifications including the confirmation email.

Log-in

Human Verification

In order to verify that you are a human and not a spam bot, please enter the answer into the following box below based on the instructions contained in the graphic.


Posting Permissions

  • You may post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts
  •