OBD1 data reader for Toyota

I have just finished building a project from a Russian website, using Arduino Uno, bluetooth HC06 to read OBD 1 data from 1990's Toyota and display data on the Torque app.

Links

(You will need google translator)

I was hoping someone can view the sketch and help me if it needs improvement.
I'm a car enthusiast with basic electronic skills and no experience with writing software.

I can't upload the sketch file ????

Thanks

That is text, not code.
Use autoformat in the IDE, mark it and use code tags, </>, when pasting it here.

#include <MsTimer2.h>
//For reading
#define ENGINE_DATA_PIN 2  // pin 2
#define ENGINE_DATA_INT 0  // for interrupts
#define OBD_DATA true
#define MY_HIGH HIGH  //LOW //if you use only one wire,
#define MY_LOW LOW    //HIGH //swap high and low, if twisted pair, then leave as is
#define TOYOTA_MAX_BYTES 24

volatile uint8_t ToyotaNumBytes, ToyotaID;
volatile uint8_t ToyotaData[TOYOTA_MAX_BYTES];
volatile uint16_t ToyotaFailBit = 0;





// make your life easier
#define OBD_INJ 1       //Injector pulse width (INJ)
#define OBD_IGN 2       //Ignition timing angle (IGN)
#define OBD_IAC 3       //Idle Air Control (IAC)
#define OBD_RPM 4       //Engine speed (RPM)
#define OBD_MAP 5       //Manifold Absolute Pressure (MAP)
#define OBD_ECT 6       //Engine Coolant Temperature (ECT)
#define OBD_TPS 7       // Throttle Position Sensor (TPS)
#define OBD_SPD 8       //Speed (SPD)
#define OBD_OXSENS 9    // Lambda 1
#define OBD_OXSENS2 10  //Lambda 2???????????

float g_power = 0.135;  // injector performance at 3S FE in 15 sec //FOR ANOTHER AUTO, CHANGE THIS PARAMETER!!!!!!!!!!!!!!
float g_fors_cnt = 4;   // number of injectors //FOR ANOTHER CAR, CHANGE THIS PARAMETER!!!!!!!!!!!!!!
float g_fors_col = 1;   // number of openings per 2 revolutions //FOR ANOTHER AUTO, CHANGE THIS PARAMETER!!!!!!!!!!!!!!
float per_sec;          // revolutions per second
float oborot_cnt;       // speed
float fors_time;        // nozzle opening time in sec
float rashod;           //car consumption
float per_hous;         // consumption per hour
float time_100km;       // time it takes to travel 100 km
int per_100km;          // cost per hundred
int timers = 1;
int full_time = 0;
float tmLast = 0;
float tmNow = 0;
float dPeriod;

boolean OBDConnected;
unsigned long OBDLastSuccessPacket;

//For transfer to Torque

String inputString = "";
boolean stringComplete = false;

void timer() {
  full_time++;
}

void setup() {
  MsTimer2::set(1000, timer);

  Serial.begin(9600);
  inputString.reserve(200);
  Serial.println(">");
  // login setup
  pinMode(ENGINE_DATA_PIN, INPUT);  // facelift
  //interrupt setting
  attachInterrupt(ENGINE_DATA_INT, ChangeState, CHANGE);
  //initial timer settings from the moment of switching on
}


void loop() {

  if ((ToyotaData[OBD_RPM] > 0) && timers == 1) {
    MsTimer2::start();
    timers = 0;
  } else if ((ToyotaData[OBD_RPM] < 1) && timers == 0) {
    MsTimer2::stop();
    timers = 1;
    full_time = 0;
  }
  //read protocol
  if (ToyotaNumBytes > 0) {

    // set last success
    OBDLastSuccessPacket = millis();
    // set connected to true
    OBDConnected = true;
    // reset the counter.
    ToyotaNumBytes = 0;
  }  // end if (ToyotaNumBytes > 0)
  // We make indirect calculations
  //actual temperature
  int OBD_ECTi;
  if (ToyotaData[OBD_ECT] >= 244)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 244) * 10.0) + 174.0;
  else if (ToyotaData[OBD_ECT] >= 238)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 238) * 4.0) + 145.0;
  else if (ToyotaData[OBD_ECT] >= 228)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 228) * 2.1) + 122.0;
  else if (ToyotaData[OBD_ECT] >= 210)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 210) * 1.11) + 102.0;
  else if (ToyotaData[OBD_ECT] >= 180)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 180) * 0.666) + 82.0;
  else if (ToyotaData[OBD_ECT] >= 135)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 135) * 0.444) + 62.0;
  else if (ToyotaData[OBD_ECT] >= 82)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 82) * 0.377) + 42.0;
  else if (ToyotaData[OBD_ECT] >= 39)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 39) * 0.465) + 22.0;
  else if (ToyotaData[OBD_ECT] >= 15)
    OBD_ECTi = ((ToyotaData[OBD_ECT] - 15) * 0.833) + 2.0;
  else
    OBD_ECTi = (ToyotaData[OBD_ECT] * 2.0) + (-28.0);


  /* -----------------------------  I DON'T KNOW HOW TO CALCULATE THE EXPENSE CORRECTLY, IF ANYONE PROMPTS, HERE IS MY email Bondy)_13@list.ru --------------------------------         */

  tmLast = 1;
  tmNow = 2;
  dPeriod = (tmNow - tmLast) / ToyotaData[OBD_SPD];

  // revolutions per second
  per_sec = (ToyotaData[OBD_RPM] * 25) / 60.0;
  // how many turns were made
  oborot_cnt = per_sec * dPeriod;
  // nozzle opening time in sec
  fors_time = (oborot_cnt / 2) * g_fors_col * g_fors_cnt * (ToyotaData[OBD_INJ] / 10) / 1000.0;
  // how much was spent in the last time interval
  rashod = fors_time * (g_power / 15.0);
  // how much will be spent per hour
  per_hous = rashod * 3600 / dPeriod;
  // how long does it take to travel 100 km (in seconds)
  time_100km = (100.0 / ToyotaData[OBD_SPD]) * 3600.0;
  // consumption per 100 km
  per_100km = 0.0;
  if (ToyotaData[OBD_SPD] > 0) {
    per_100km = rashod * time_100km / dPeriod;
  }

  /*---------------------------------------------------------------------------------------------------------------------------------------------      */


  //check for lost connection
  if (OBDLastSuccessPacket + 3500 < millis() && OBDConnected) {
    OBDConnected = false;
  }  // end if lost connection

  //transfer to Torque
  if (stringComplete) {
    int len = inputString.length();
    String ans = "4" + inputString.substring(1, 2) + " ";

    if (len > 4) ans = ans + inputString.substring(3, 5) + " ";
    else if (len > 3) ans = ans + inputString.substring(2, 4) + " ";
    else if (len > 2) ans = ans + inputString.substring(3, 4) + " ";

    if (inputString.substring(0, 3) == "ATZ") Serial.println("ELM327 v1.4");
    else if (inputString.substring(0, 3) == "ATI") Serial.println("ELM327 v1.4");
    else if (inputString.substring(0, 2) == "DP") Serial.println("SAE J1850 PWM");
    else if (inputString.substring(0, 3) == "DP1") Serial.println("SAE J1850 PWM");
    else if (inputString.substring(0, 4) == "AT@1") Serial.println("made Alexey Bondarenko");
    else if (inputString.substring(0, 4) == "ATTP1") Serial.println("OK");
    else if (inputString.substring(0, 2) == "AT") Serial.println("OK");
    else if (inputString.substring(0, 4) == "0100") Serial.println("41 00 08 38 80 02");  //supported pids of group 1
    else if (inputString.substring(0, 4) == "0101") Serial.println("41 01 00 00 00 00");
    else if (inputString.substring(0, 4) == "0120") Serial.println("41 20 00 00 00 00");               // supported pids of the 2nd group
    else if (inputString.substring(0, 4) == "0140") Serial.println("41 40 00 00 80 00");               // supported pids of the 3rd group
    else if (inputString.substring(0, 4) == "0151") Serial.println("41 51 01 00 00 00");               // type of fuel, there is gasoline at the moment, diesel will "41 51 04 00 00 00"
    else if (inputString.substring(0, 4) == "0160") Serial.println("41 60 00 00 00 00");               // supported pids of the 4th group
    else if (inputString.substring(0, 4) == "0180") Serial.println("41 80 00 00 00 00");               // supported pids of the 5th group
    else if (inputString.substring(0, 4) == "01A0") Serial.println("41 A0 80 00 00 00");               //supported pids of the 6th group
    else if (inputString.substring(0, 4) == "01C0") Serial.println("41 C0 00 00 00 00");               // supported pids of the 7th group
    else if (inputString.substring(0, 2) == "03") Serial.println("43 03 00 00 00 00\r\n43 13 00 00");  //type of error in the car ....
    else if (inputString.substring(0, 4) == "0902") Serial.println("49 02 1Z3768470804");              // car serial number... VIN
    //coolant temperature output
    if ((OBD_ECTi > (-16)) && (OBD_ECTi < 16)) {
      if (inputString.substring(0, 4) == "0105") Serial.print("41 05 "), Serial.print("0"), Serial.println(OBD_ECTi, HEX);
    } else {
      if (inputString.substring(0, 4) == "0105") Serial.print("41 05 "), Serial.println(OBD_ECTi, HEX);
    }
    //Correct engine speed
    if ((ToyotaData[OBD_RPM] * 100 / 4) < 1001) {
      if (inputString.substring(0, 4) == "010C") Serial.print("41 0C "), Serial.print("0"), Serial.println(ToyotaData[OBD_RPM] * 100, HEX);
    } else {
      if (inputString.substring(0, 4) == "010C") Serial.print("41 0C "), Serial.println(ToyotaData[OBD_RPM] * 100, HEX);  //engine speed
    }

    // damper angle
    if (ToyotaData[OBD_TPS] < 10) {
      if (inputString.substring(0, 4) == "0111") Serial.print("41 11 "), Serial.print("0"), Serial.println(ToyotaData[OBD_TPS] * 255 / 100, HEX);  // damper angle
    } else {
      if (inputString.substring(0, 4) == "0111") Serial.print("41 11 "), Serial.println(ToyotaData[OBD_TPS] * 255 / 100, HEX);
    }

    //Vehicle speed
    if (ToyotaData[OBD_SPD] < 16) {
      if (inputString.substring(0, 4) == "010D") Serial.print("41 0D "), Serial.print("0"), Serial.println(ToyotaData[OBD_SPD], HEX);  //////Vehicle speed
    } else {
      if (inputString.substring(0, 4) == "010D") Serial.print("41 0D "), Serial.println(ToyotaData[OBD_SPD], HEX);  //////Vehicle speed
    }

    //Time since engine start
    if (full_time < 16) {
      if (inputString.substring(0, 4) == "011F") Serial.print("41 1F 00 "), Serial.print("0"), Serial.println(full_time, HEX);
    } else if ((full_time > 15) && (256 > full_time)) {
      if (inputString.substring(0, 4) == "011F") Serial.print("41 1F 00 "), Serial.println(full_time, HEX);
    } else if ((full_time > 255) && (4096 > full_time)) {
      if (inputString.substring(0, 4) == "011F") Serial.print("41 1F 0"), Serial.println(full_time, HEX);
    } else if (full_time > 4096) {
      if (inputString.substring(0, 4) == "011F") Serial.print("41 1F "), Serial.println(full_time, HEX);
    }

    //ignition timing
    if ((ToyotaData[OBD_IGN] + 50) < 10) {
      if (inputString.substring(0, 4) == "010E") Serial.print("41 0E "), Serial.print("0"), Serial.println((ToyotaData[OBD_IGN] + 50), HEX);
    } else {
      if (inputString.substring(0, 4) == "010E") Serial.print("41 0E "), Serial.println((ToyotaData[OBD_IGN] + 50), HEX);
    }
    // injector time
    if (ToyotaData[OBD_INJ] < 16) {
      if (inputString.substring(0, 4) == "01E4") Serial.print("41 E4 "), Serial.print("0"), Serial.println(ToyotaData[OBD_INJ], HEX);
    } else {
      if (inputString.substring(0, 4) == "01E4") Serial.print("41 E4 "), Serial.println(ToyotaData[OBD_INJ], HEX);
    }
    //intake manifold pressure
    if (ToyotaData[OBD_MAP] < 16) {
      if (inputString.substring(0, 4) == "010B") Serial.print("41 0B "), Serial.print("0"), Serial.println(ToyotaData[OBD_MAP], HEX);
    } else {
      if (inputString.substring(0, 4) == "010B") Serial.print("41 0B "), Serial.println(ToyotaData[OBD_MAP], HEX);
    }
    //Fan rotation
    if (ToyotaData[OBD_IAC] < 16) {
      if (inputString.substring(0, 4) == "01A2") Serial.print("41 A2 "), Serial.print("0"), Serial.println(ToyotaData[OBD_IAC], HEX);
    } else {
      if (inputString.substring(0, 4) == "01A2") Serial.print("41 A2 "), Serial.println(ToyotaData[OBD_IAC], HEX);
    }
    //Consumption per hour
    if (per_hous < 16) {
      if (inputString.substring(0, 4) == "01A3") Serial.print("41 A3 "), Serial.print("0"), Serial.println(per_hous, HEX);
    } else {
      if (inputString.substring(0, 4) == "01A3") Serial.print("41 A3 "), Serial.println(per_hous, HEX);
    }
    //consumption per 100 km
    if (per_100km < 16) {
      if (inputString.substring(0, 4) == "01A4") Serial.print("41 A4 "), Serial.print("0"), Serial.println(per_100km, HEX);
    } else {
      if (inputString.substring(0, 4) == "01A4") Serial.print("41 A4 "), Serial.println(per_100km, HEX);
    }
    // Lambda

    if (OBD_OXSENS) {
      if (inputString.substring(0, 4) == "0114") Serial.print("41 14 "), Serial.print(OBD_OXSENS, HEX), Serial.println(" 00");
    }

    Serial.println(">");
    inputString = "";
    stringComplete = false;
  }
}



// GET DATA FROM OBD
float getOBDdata(int OBDdataIDX) {
  // define return value
  float returnValue;
  switch (OBDdataIDX) {
    case 0:  // UNKNOWN
      returnValue = ToyotaData[0];
      break;
    case OBD_INJ:  //  Injector pulse width (INJ) - in milisec
      returnValue = ToyotaData[OBD_INJ] / 10;
      break;
    case OBD_IGN:  // Ignition timing angle (IGN) - degree- BTDC
      returnValue = ToyotaData[OBD_IGN] - 90;
      break;
    case OBD_IAC:  //Idle Air Control (IAC) - Step # X = 125 = open 100%
      returnValue = ToyotaData[OBD_IAC] / 125 * 100;
      break;
    case OBD_RPM:  //Engine speed (RPM)
      returnValue = ToyotaData[OBD_RPM] * 25;
      break;
    case OBD_MAP:  //Manifold Absolute Pressure (MAP) - kPa Abs
      returnValue = ToyotaData[OBD_MAP];
      break;
    case OBD_ECT:  // Engine Coolant Temperature (ECT)
      if (ToyotaData[OBD_ECT] >= 244)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 244) * 10.0) + 132.0;
      else if (ToyotaData[OBD_ECT] >= 238)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 238) * 4.0) + 103.0;
      else if (ToyotaData[OBD_ECT] >= 228)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 228) * 2.1) + 80.0;
      else if (ToyotaData[OBD_ECT] >= 210)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 210) * 1.11) + 60.0;
      else if (ToyotaData[OBD_ECT] >= 180)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 180) * 0.666) + 40.0;
      else if (ToyotaData[OBD_ECT] >= 135)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 135) * 0.444) + 20.0;
      else if (ToyotaData[OBD_ECT] >= 82)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 82) * 0.377) + 0.0;
      else if (ToyotaData[OBD_ECT] >= 39)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 39) * 0.465) + (-20.0);
      else if (ToyotaData[OBD_ECT] >= 15)
        returnValue = ((float)(ToyotaData[OBD_ECT] - 15) * 0.833) + (-40.0);
      else
        returnValue = ((float)ToyotaData[OBD_ECT] * 2.0) + (-70.0);

      break;
    case OBD_TPS:  // Throttle Position Sensor (TPS) - DEGREE
      returnValue = ToyotaData[OBD_TPS] / 2;
      break;
    case OBD_SPD:  // Speed (SPD) - km/h
      returnValue = ToyotaData[OBD_SPD];
      break;
    case OBD_OXSENS:  // Lambda
      returnValue = ToyotaData[9] * 5 / 256 / 3.9215686274509807 * 200;
      break;
    case OBD_OXSENS2:  // Lambda2
      returnValue = ToyotaData[10] * 5 / 256 / 3.9215686274509807 * 200;
      break;
      break;
    case 11:  // FLAG #1
      returnValue = ToyotaData[11];
      break;
    case 12:  // FLAG # 2
      returnValue = ToyotaData[12];
      break;
    default:  // DEFAULT CASE (in no match to number)
      // send "error" value
      returnValue = 9999.99;
  }  // end switch
  // send value back
  return returnValue;
}  // end void getOBDdata

// VOID CHANGE
void ChangeState() {
  //Serial.print(digitalRead(ENGINE_DATA_PIN));
  static uint8_t ID, EData[TOYOTA_MAX_BYTES];
  static boolean InPacket = false;
  static unsigned long StartMS;
  static uint16_t BitCount;

  int state = digitalRead(ENGINE_DATA_PIN);

  if (InPacket == false) {
    if (state == MY_HIGH) {
      StartMS = millis();
    } else {  // else  if (state == MY_HIGH)
      if ((millis() - StartMS) > (15 * 8)) {
        StartMS = millis();
        InPacket = true;
        BitCount = 0;
      }                                              // end if  ((millis() - StartMS) > (15 * 8))
    }                                                // end if  (state == MY_HIGH)
  } else {                                           // else  if (InPacket == false)
    uint16_t bits = ((millis() - StartMS) + 1) / 8;  // The +1 is to cope with slight time errors
    StartMS = millis();
    // process bits
    while (bits > 0) {
      if (BitCount < 4) {
        if (BitCount == 0)
          ID = 0;
        ID >>= 1;
        if (state == MY_LOW)  // inverse state as we are detecting the change!
          ID |= 0x08;
      } else {  // else    if (BitCount < 4)
        uint16_t bitpos = (BitCount - 4) % 11;
        uint16_t bytepos = (BitCount - 4) / 11;
        if (bitpos == 0) {

          // Start bit, should be LOW
          if ((BitCount > 4) && (state != MY_HIGH)) {  // inverse state as we are detecting the change!
            ToyotaFailBit = BitCount;
            InPacket = false;
            break;
          }  // end if ((BitCount > 4) && (state != MY_HIGH))

        } else if (bitpos < 9) {  //else TO  if (bitpos == 0)

          EData[bytepos] >>= 1;
          if (state == MY_LOW)  // inverse state as we are detecting the change!
            EData[bytepos] |= 0x80;

        } else {  // else if (bitpos == 0)

          // Stop bits, should be HIGH
          if (state != MY_LOW) {  // inverse state as we are detecting the change!
            ToyotaFailBit = BitCount;
            InPacket = false;
            break;
          }  // end if (state != MY_LOW)

          if ((bitpos == 10) && ((bits > 1) || (bytepos == (TOYOTA_MAX_BYTES - 1)))) {
            ToyotaNumBytes = 0;
            ToyotaID = ID;
            for (int i = 0; i <= bytepos; i++)
              ToyotaData[i] = EData[i];
            ToyotaNumBytes = bytepos + 1;
            if (bits >= 16)  // Stop bits of last byte were 1's so detect preamble for next packet
              BitCount = 0;
            else {
              ToyotaFailBit = BitCount;
              InPacket = false;
            }
            break;
          }
        }
      }
      ++BitCount;
      --bits;
    }  // end while
  }    // end (InPacket == false)
}  // end void change

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    if (inChar == '\n') continue;
    if (inChar == '\r') {
      stringComplete = true;
      if (inputString == "") inputString = "NULL";
      inputString.toUpperCase();
      continue;
    }
    inputString += inChar;
  }
}

Just reposted.
Is it correct?

Perfect.
Can You elaborate why You can't download the sketch? Short of coffee? Joking!

I can't upload the file to the forum because I'm a new member.
That's why I copied and paste the sketch.

Now I get it. My mistake, thought of "not able to download". Sorry.
Yes, there are some restrictions for new members but You passed that gate by now.
What is the outcome when You run Your project?
Any code, long or short, crappy or elegant, but doing the job is a good code. There are lots of elegant code failing....

The only improvements would be changing functions or adding new functions. If it works, just feel satisfied!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.