diff options
-rw-r--r-- | libraries/OBD/OBD.cpp | 162 | ||||
-rw-r--r-- | libraries/OBD/OBD.h | 28 |
2 files changed, 90 insertions, 100 deletions
diff --git a/libraries/OBD/OBD.cpp b/libraries/OBD/OBD.cpp index 5ea4c47..9d457bc 100644 --- a/libraries/OBD/OBD.cpp +++ b/libraries/OBD/OBD.cpp @@ -64,53 +64,94 @@ void COBD::Query(unsigned char pid) { char cmd[8]; sprintf_P(cmd, s_cmd_fmt, dataMode, pid); - WriteData(cmd); + write(cmd); } bool COBD::ReadSensor(byte pid, int& result, bool passive) { - if (passive) { - bool hasData; - unsigned long tick = millis(); - while (!(hasData = DataAvailable()) && millis() - tick < OBD_TIMEOUT_SHORT); - if (!hasData) { - errors++; - return false; - } - } else { - Query(pid); + // send a query command + Query(pid); + // wait for reponse + bool hasData; + unsigned long tick = millis(); + do { + DataIdleLoop(); + } while (!(hasData = available()) && millis() - tick < OBD_TIMEOUT_SHORT); + if (!hasData) { + errors++; + return false; } - return GetResponse(pid, result); + // receive and parse the response + return GetResponseParsed(pid, result); } -bool COBD::DataAvailable() +bool COBD::available() { return OBDUART.available(); } -char COBD::ReadData() +char COBD::read() { return OBDUART.read(); } -void COBD::WriteData(const char* s) +void COBD::write(const char* s) { OBDUART.write(s); } -void COBD::WriteData(const char c) +void COBD::write(const char c) { OBDUART.write(c); } -char* COBD::GetResponse(byte pid, char* buffer) +int COBD::GetConvertedValue(byte pid, char* data) +{ + int result; + switch (pid) { + case PID_RPM: + result = GetLargeValue(data) >> 2; + break; + case PID_FUEL_PRESSURE: + result = GetSmallValue(data) * 3; + break; + case PID_COOLANT_TEMP: + case PID_INTAKE_TEMP: + case PID_AMBIENT_TEMP: + result = GetTemperatureValue(data); + break; + case PID_ABS_ENGINE_LOAD: + result = GetLargeValue(data) * 100 / 255; + break; + case PID_MAF_FLOW: + result = GetLargeValue(data) / 100; + break; + case PID_THROTTLE: + case PID_ENGINE_LOAD: + case PID_FUEL_LEVEL: + result = GetPercentageValue(data); + break; + case PID_TIMING_ADVANCE: + result = (GetSmallValue(data) - 128) >> 1; + break; + case PID_DISTANCE: + case PID_RUNTIME: + result = GetLargeValue(data); + break; + default: + result = GetSmallValue(data); + } + return result; +} + +char* COBD::GetResponse(byte& pid, char* buffer) { unsigned long startTime = millis(); byte i = 0; for (;;) { - if (DataAvailable()) { - char c = ReadData(); + if (available()) { + char c = read(); buffer[i] = c; if (++i == OBD_RECV_BUF_SIZE - 1) { // buffer overflow @@ -140,7 +181,9 @@ char* COBD::GetResponse(byte pid, char* buffer) char *p = buffer; while ((p = strstr_P(p, s_response_begin))) { p += 3; - if (pid == 0 || hex2uint8(p) == pid) { + byte curpid = hex2uint8(p); + if (pid == 0) pid = curpid; + if (curpid == pid) { errors = 0; p += 2; if (*p == ' ') @@ -150,81 +193,27 @@ char* COBD::GetResponse(byte pid, char* buffer) return 0; } -bool COBD::GetParsedData(byte pid, char* data, int& result) -{ - switch (pid) { - case PID_RPM: - result = GetLargeValue(data) >> 2; - break; - case PID_FUEL_PRESSURE: - result = GetSmallValue(data) * 3; - break; - case PID_COOLANT_TEMP: - case PID_INTAKE_TEMP: - case PID_AMBIENT_TEMP: - result = GetTemperatureValue(data); - break; - case PID_ABS_ENGINE_LOAD: - result = GetLargeValue(data) * 100 / 255; - break; - case PID_MAF_FLOW: - result = GetLargeValue(data) / 100; - break; - case PID_THROTTLE: - case PID_ENGINE_LOAD: - case PID_FUEL_LEVEL: - result = GetPercentageValue(data); - break; - case PID_SPEED: - case PID_BAROMETRIC: - case PID_INTAKE_MAP: - result = GetSmallValue(data); - break; - case PID_TIMING_ADVANCE: - result = (GetSmallValue(data) - 128) >> 1; - break; - case PID_DISTANCE: - case PID_RUNTIME: - result = GetLargeValue(data); - break; - default: - return false; - } - return true; -} - -bool COBD::GetResponse(byte pid, int& result) +bool COBD::GetResponseParsed(byte& pid, int& result) { char buffer[OBD_RECV_BUF_SIZE]; char* data = GetResponse(pid, buffer); if (!data) { // try recover next time - WriteData('\r'); + write('\r'); return false; } - return GetParsedData(pid, data, result); -} - -bool COBD::GetResponsePassive(byte& pid, int& result) -{ - char buffer[OBD_RECV_BUF_SIZE]; - char* data = GetResponse(0, buffer); - if (!data) { - // try recover next time - return false; - } - pid = hex2uint8(data - 3); - return GetParsedData(pid, data, result); + result = GetConvertedValue(pid, data); + return true; } void COBD::Sleep(int seconds) { char cmd[MAX_CMD_LEN]; strcpy_P(cmd, s_cmd_sleep); - WriteData(cmd); + write(cmd); if (seconds) { delay((unsigned long)seconds << 10); - WriteData('\r'); + write('\r'); } } @@ -249,14 +238,14 @@ bool COBD::Init(bool passive) if (!passive) { char cmd[MAX_CMD_LEN]; strcpy_P(cmd, s_initcmd[i]); - WriteData(cmd); + write(cmd); } n = 0; prompted = 0; currentMillis = millis(); for (;;) { - if (DataAvailable()) { - char c = ReadData(); + if (available()) { + char c = read(); if (c == '>') { buffer[n] = 0; prompted++; @@ -272,7 +261,7 @@ bool COBD::Init(bool passive) //WriteData("\r"); return false; } - DataTimeout(); + InitIdleLoop(); } } } @@ -280,8 +269,9 @@ bool COBD::Init(bool passive) // load pid map memset(pidmap, 0, sizeof(pidmap)); for (byte i = 0; i < 4; i++) { - Query(i * 0x20); - char* data = GetResponse(i * 0x20, buffer); + byte pid = i * 0x20; + Query(pid); + char* data = GetResponse(pid, buffer); if (!data) break; data--; for (byte n = 0; n < 4; n++) { diff --git a/libraries/OBD/OBD.h b/libraries/OBD/OBD.h index acc6735..e97ab67 100644 --- a/libraries/OBD/OBD.h +++ b/libraries/OBD/OBD.h @@ -1,8 +1,7 @@ /************************************************************************* -* Arduino OBD-II UART Adapter Library -* http://www.arduinodev.com/hardware/obd-kit +* OBD-II (ELM327) data accessing library for Arduino * Distributed under GPL v2.0 -* (C)2012~2013 Written by Stanley Huang <stanleyhuangyc@gmail.com> +* Copyright (c) 2012 Stanley Huang <stanleyhuangyc@gmail.com> * All rights reserved. *************************************************************************/ @@ -13,7 +12,7 @@ #define OBD_RECV_BUF_SIZE 64 #ifndef OBDUART -#ifdef __AVR_ATmega32U4__ /* for Leonardo */ +#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) #define OBDUART Serial1 #else #define OBDUART Serial @@ -49,19 +48,15 @@ public: bool ReadSensor(byte pid, int& result, bool passive = false); bool IsValidPID(byte pid); void Sleep(int seconds); - // following APIs are for advanced usages only + // Query and GetResponse for advanced usage only void Query(byte pid); - bool GetParsedData(byte pid, char* data, int& result); - virtual char* GetResponse(byte pid, char* buffer); - virtual bool GetResponse(byte pid, int& result); - virtual bool GetResponsePassive(byte& pid, int& result); - virtual bool DataAvailable(); - virtual char ReadData(); - virtual void WriteData(const char* s); - virtual void WriteData(const char c); + char* GetResponse(byte& pid, char* buffer); + bool GetResponseParsed(byte& pid, int& result); byte dataMode; byte errors; + //char recvBuf[OBD_RECV_BUF_SIZE]; protected: + static int GetConvertedValue(byte pid, char* data); static int GetPercentageValue(char* data) { return (int)hex2uint8(data) * 100 / 255; @@ -78,6 +73,11 @@ protected: { return (int)hex2uint8(data) - 40; } - virtual void DataTimeout() {} + virtual bool available(); + virtual char read(); + virtual void write(const char* s); + virtual void write(const char c); + virtual void InitIdleLoop() {} + virtual void DataIdleLoop() {} byte pidmap[4 * 4]; }; |