Decoding ISO 9141-2: Success with Arduino and OBD-II

For automotive DIY enthusiasts and professionals alike, accessing vehicle diagnostic data is a crucial step in understanding and resolving car issues. The ISO 9141-2 protocol is a common standard used in many vehicles for On-Board Diagnostics (OBD). If you’ve been struggling to get your Arduino project to communicate using Code Iso 9141-2, you’re not alone. Many hobbyists and even seasoned mechanics can hit roadblocks when trying to interface with this protocol. This article details a successful journey in getting ISO 9141-2 communication working with an Arduino Nano, highlighting a simple yet effective code solution and troubleshooting steps.

Initially, attempts to read data using various code snippets, including modifications of existing OBD-II libraries, proved unsuccessful. Changing parameters and tweaking code based on online suggestions didn’t yield the desired results. The breakthrough came unexpectedly by revisiting the examples provided within the Arduino IDE for the iwanders/OBD9141 library. Specifically, the ISO9141_rreader_softserial.ino example, found under Examples -> OBD9141, turned out to be the key. This example, designed for a software serial implementation, worked almost immediately, requiring only minor adjustments to fit the specific hardware setup.

One of the first observations was the inclusion of code related to an EN_PIN and the SN65HVDA100 transceiver chip in the example code. This chip is often used as a physical layer interface for OBD-II communication. However, for users not employing this specific chip, this part of the code, while present, doesn’t interfere with the functionality. It can be left in place or removed without affecting the core operation of the code iso 9141-2 reader. The setup used in this successful attempt was an Arduino Nano, maintaining the example’s designated Tx/Rx pins (8 and 9). It’s important to remember that when using an Arduino Nano, or similar boards, for OBD-II communication, a software serial library like AltSoftSerial is often necessary. This is because you need one serial port for communication with your computer (via the Serial Monitor) and a separate serial port to communicate with the OBD-II interface and your vehicle’s ECU (Engine Control Unit) using code iso 9141-2.

Ensuring the correct Serial Monitor speed is another critical detail often overlooked. The default speed in the example might be 9600 baud, but if you prefer a faster rate like 115200, remember to adjust both your code and the Serial Monitor setting accordingly.

During initial testing, a peculiar issue emerged: out of three requested PIDs (Parameter IDs) – Throttle, RPM, and Speed – only two would consistently display on the Serial Monitor, typically the first and third in the sequence. The second PID request seemed to be ignored. Experimenting with the order of PID requests didn’t resolve the issue; the second request in line always failed to return data. The solution turned out to be surprisingly simple: adding a 50ms delay between each PID request. This suggests that the ISO 9141-2 protocol, or the specific vehicle’s implementation, necessitates a minimum time interval between consecutive requests. By implementing this delay, all requested PIDs started to return data reliably, provided, of course, that the requested PID is valid and supported by the vehicle. This highlights the importance of timing and potential protocol-specific nuances when working with code iso 9141-2.

Below is the modified Arduino code that successfully read data using code iso 9141-2, incorporating the crucial 50ms delay between PID requests. Note that the ‘EN_PIN’ related code is still present but is inconsequential if you are not using the SN65HVDA100 chip.

#include <Arduino.h> // Be sure that the AltSoftSerial library is available, download it from http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html"
#include <AltSoftSerial.h>
#include <OBD9141.h>

#define RX_PIN 8     // connect to transceiver Rx
#define TX_PIN 9     // connect to transceiver Tx
#define EN_PIN 10    // pin will be set high (connect to EN pin of SN65HVDA100)

AltSoftSerial altSerial;
OBD9141 obd;

void setup() {
  Serial.begin(115200);
  delay(2000);
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, HIGH); // enable the transceiver IC.
  obd.begin(altSerial, RX_PIN, TX_PIN);
}

void loop() {
  Serial.println("Looping");
  bool init_success = obd.init();
  Serial.print("init_success:");
  Serial.println(init_success);
  if (init_success) {
    bool res;
    while(1) {
      // FORMAT: obd.getCurrentPID =>> (address, number of bytes)
      res = obd.getCurrentPID(0x11, 1);
      if (res){
        Serial.print("Result 0x11 (Throttle): "); // 100/255 x data (or A / 2.55) = 0% to 100%
        Serial.println(obd.readUint8()/2.55);
      }
      delay(50);

      res = obd.getCurrentPID(0x0F, 1);
      if (res) {
        Serial.print("Result 0x0F (Air Intake Temp): ");
        Serial.println(obd.readUint8() -40); // Temp = data -40. Need to remove 40 from rtnd data
      }
      delay(50);

      res = obd.getCurrentPID(0x05, 1);
      if (res) {
        Serial.print("Result 0x05 (Engine coolant temperature): ");
        Serial.println(obd.readUint8() -40); // Temp = data -40. Need to remove 40 from rtnd data
      }
      delay(50);

      // 46
      res = obd.getCurrentPID(0x0C, 2);
      if (res) {
        Serial.print("Result 0x0C (RPM): "); // listed as: (256.A)+B /4 (??)
        Serial.println(obd.readUint16()/4);
      }
      delay(50);

      res = obd.getCurrentPID(0x0D, 1);
      if (res) {
        Serial.print("Result 0x0D (Speed): "); // 1:1 with data
        Serial.println(obd.readUint8());
      }
      Serial.println();
      delay(200);
    }
  }
  delay(3000);
}

A point of ongoing investigation is the accuracy of the returned data values and their correct interpretation. The code includes comments referencing formulas derived from the Wikipedia page on OBD-II PIDs. Specifically, discrepancies were noted between the formula provided in the ISO standard for RPM and the division by 4 used in the example code. While initial static testing in the car suggested reasonable RPM values, further verification is needed to ensure data accuracy across all PIDs.

[Image of Arduino Serial Monitor output showing successful data retrieval, similar to the text examples in the original article, with clear labels for Throttle, RPM, Speed, and Temperature values.]

Alt text: Arduino Serial Monitor displaying live OBD-II data including RPM, Throttle, Speed and Temperature readings obtained using ISO 9141-2 code.

The Serial Monitor output during testing showed fluctuating values for Throttle and RPM when the accelerator pedal was manipulated, indicating live data retrieval from the vehicle’s sensors. While the Air Intake Temperature readings seemed slightly higher than expected ambient temperature, and Speed data requires road testing for verification, the successful communication using code iso 9141-2 and data retrieval is a significant step forward.

In conclusion, successfully implementing code iso 9141-2 communication with Arduino for OBD-II diagnostics can be achieved by leveraging existing library examples and paying close attention to timing considerations. The iwanders/OBD9141 library’s ISO9141_rreader_softserial.ino example provides a solid foundation. Remember to consider software serial for Arduino Nano, verify your Serial Monitor speed, and implement delays between PID requests. Further investigation into data accuracy and PID value interpretation will be the next crucial step in refining this OBD-II diagnostic project. This breakthrough provides a valuable starting point for anyone looking to decode their vehicle’s data using Arduino and the ISO 9141-2 protocol.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *