From 3df4070034d4fc9dc8464d08fab53b65e3729a2e Mon Sep 17 00:00:00 2001
From: Stanley Huang <stanleyhuangyc@gmail.com>
Date: Fri, 26 Feb 2016 13:42:19 +1100
Subject: Added multiple OBD-II PIDs reading API

---
 libraries/OBD/OBD.cpp | 60 ++++++++++++++++++++++++++++++++++++++++-----------
 libraries/OBD/OBD.h   | 19 +++++++++-------
 2 files changed, 59 insertions(+), 20 deletions(-)

(limited to 'libraries/OBD')

diff --git a/libraries/OBD/OBD.cpp b/libraries/OBD/OBD.cpp
index e4d546c..6ede386 100644
--- a/libraries/OBD/OBD.cpp
+++ b/libraries/OBD/OBD.cpp
@@ -1,8 +1,8 @@
 /*************************************************************************
 * Arduino Library for OBD-II UART/I2C Adapter
-* Distributed under GPL v2.0
+* Distributed under BSD License
 * Visit http://freematics.com for more information
-* (C)2012-2015 Stanley Huang <stanleyhuangyc@gmail.com>
+* (C)2012-2016 Stanley Huang <stanleyhuangyc@gmail.com>
 *************************************************************************/
 
 #include <Arduino.h>
@@ -81,6 +81,25 @@ bool COBD::read(byte pid, int& result)
 	return getResult(pid, result);
 }
 
+byte COBD::read(const byte pid[], byte count, int result[])
+{
+	// send a multiple query command
+	char buffer[128];
+	char *p = buffer;
+	byte results = 0;
+	for (byte n = 0; n < count; n++) {
+		p += sprintf(p, "%02X%02X\r\n", dataMode, pid[n]);		
+	}
+	write(buffer);
+	// receive and parse the response
+	for (byte n = 0; n < count; n++) {
+		byte curpid = pid[n];
+		if (getResult(curpid, result[n]))
+			results++;
+	}
+	return results;
+}
+
 void COBD::clearDTC()
 {
 	char buffer[32];
@@ -239,7 +258,7 @@ float COBD::getVoltage()
 bool COBD::getVIN(char* buffer, byte bufsize)
 {
 	if (sendCommand("0902\r", buffer, bufsize)) {
-	    char *p = strstr(buffer, "49 02");
+        char *p = strstr(buffer, "0: 49 02");
         if (p) {
             char *q = buffer;
             p += 10;
@@ -321,23 +340,30 @@ bool COBD::init(OBD_PROTOCOLS protocol)
 
 	m_state = OBD_CONNECTING;
 
+	write("ATI\r");
+	if (receive(buffer, sizeof(buffer), 100)) {
+		char *p = strstr(buffer, "OBDUART");
+		if (p) {
+			p += 9;
+			version = (*p - '0') * 10 + (*(p + 2) - '0');
+		}
+	}
+	if (version == 0) {
+		m_state = OBD_FAILED;
+		return false;
+	}
+
 	for (unsigned char i = 0; i < sizeof(initcmd) / sizeof(initcmd[0]); i++) {
 #ifdef DEBUG
 		debugOutput(initcmd[i]);
 #endif
 		write(initcmd[i]);
 		if (receive(buffer, sizeof(buffer), OBD_TIMEOUT_LONG) == 0) {
-			if (i == 0) {
-				// workaround for longer initialization time
-				delay(2000);
-			} else {
-				m_state = OBD_DISCONNECTED;
-				return false;
-			}
+			m_state = OBD_DISCONNECTED;
+			return false;
 		}
 		delay(50);
 	}
-	//while (available()) read();
 
 	if (protocol != PROTO_AUTO) {
 		setProtocol(protocol);
@@ -358,7 +384,6 @@ bool COBD::init(OBD_PROTOCOLS protocol)
 		}
 		delay(100);
 	}
-	//while (available()) read();
 
 	m_state = OBD_CONNECTED;
 	errors = 0;
@@ -471,6 +496,17 @@ byte COBDI2C::receive(char* buffer, byte bufsize, int timeout)
 	return 0;
 }
 
+byte COBDI2C::read(const byte pid[], byte count, int result[])
+{
+	byte results = 0; 
+	for (byte n = 0; n < count; n++) {
+		if (read(pid[n], result[n])) {
+			results++;
+		}
+	}
+	return results;
+}
+
 void COBDI2C::setPID(byte pid, byte obdPid[])
 {
 	byte n = 0;
diff --git a/libraries/OBD/OBD.h b/libraries/OBD/OBD.h
index dd1cbf6..c42b450 100644
--- a/libraries/OBD/OBD.h
+++ b/libraries/OBD/OBD.h
@@ -1,8 +1,8 @@
 /*************************************************************************
 * Arduino Library for OBD-II UART/I2C Adapter
-* Distributed under GPL v2.0
+* Distributed under BSD License
 * Visit http://freematics.com for more information
-* (C)2012-2015 Stanley Huang <stanleyhuangyc@gmail.com>
+* (C)2012-2016 Stanley Huang <stanleyhuangyc@gmail.com>
 *************************************************************************/
 
 #include <Arduino.h>
@@ -11,7 +11,7 @@
 #define OBD_MODEL_I2C 1
 
 #define OBD_TIMEOUT_SHORT 1000 /* ms */
-#define OBD_TIMEOUT_LONG 10000 /* ms */
+#define OBD_TIMEOUT_LONG 15000 /* ms */
 #define OBD_TIMEOUT_GPS 200 /* ms */
 #define OBD_SERIAL_BAUDRATE 38400
 
@@ -90,7 +90,8 @@ typedef enum {
 typedef enum {
     OBD_DISCONNECTED = 0,
     OBD_CONNECTING = 1,
-    OBD_CONNECTED = 2
+    OBD_CONNECTED = 2,
+	OBD_FAILED = 3
 } OBD_STATES;
 
 uint16_t hex2uint16(const char *p);
@@ -100,10 +101,7 @@ class COBD
 {
 public:
 	COBD():dataMode(1),errors(0),m_state(OBD_DISCONNECTED) {}
-	/*
-       Serial baudrate is only adjustable for Arduino OBD-II Adapters V2
-       Check out http://freematics.com/pages/products/arduino-obd-adapter
-	*/
+	// begin serial UART
 	virtual void begin();
 	// initialize OBD-II connection
 	virtual bool init(OBD_PROTOCOLS protocol = PROTO_AUTO);
@@ -115,6 +113,8 @@ public:
 	virtual OBD_STATES getState() { return m_state; }
 	// read specified OBD-II PID value
 	virtual bool read(byte pid, int& result);
+	// read multiple (up to 8) OBD-II PID values, return number of values obtained
+	virtual byte read(const byte pid[], byte count, int result[]);
 	// set device into
 	virtual void sleep();
 	// set working protocol (default auto)
@@ -141,6 +141,8 @@ public:
 	byte errors;
 	// bit map of supported PIDs
 	byte pidmap[4 * 4];
+	// adapter version
+	byte version;
 protected:
 	virtual char* getResponse(byte& pid, char* buffer, byte bufsize);
 	virtual byte receive(char* buffer, byte bufsize, int timeout = OBD_TIMEOUT_SHORT);
@@ -197,6 +199,7 @@ public:
 	void begin();
 	void end();
 	bool read(byte pid, int& result);
+	byte read(const byte pid[], byte count, int result[]);
 	void write(const char* s);
 	// API not applicable
 	bool setBaudRate(unsigned long baudrate) { return false; }
-- 
cgit v1.2.3