From 251bd01111ab0626fb861a391578445d9e6c7d26 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Tue, 10 Oct 2017 23:25:13 +1100 Subject: Added simple OBD data display example sketch --- simple_obd_display/simple_obd_display.ino | 105 ++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 simple_obd_display/simple_obd_display.ino diff --git a/simple_obd_display/simple_obd_display.ino b/simple_obd_display/simple_obd_display.ino new file mode 100644 index 0000000..ca36236 --- /dev/null +++ b/simple_obd_display/simple_obd_display.ino @@ -0,0 +1,105 @@ +/************************************************************************* +* Simple OBD Data Display +* Works with any Arduino board connected with SH1106 128*64 I2C OLED and +* Freematics OBD-II UART Adapter - https://freematics.com/products +* Distributed under public domain +* Written by Stanley Huang +*************************************************************************/ + +#include +#include +#include + +LCD_SH1106 lcd; +COBD obd; + +void reconnect() +{ + lcd.clear(); + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.print("Reconnecting"); + //digitalWrite(SD_CS_PIN, LOW); + for (uint16_t i = 0; !obd.init(); i++) { + if (i == 5) { + lcd.clear(); + } + delay(3000); + } +} + +void showData(byte pid, int value) +{ + switch (pid) { + case PID_RPM: + lcd.setCursor(64, 0); + lcd.setFontSize(FONT_SIZE_XLARGE); + lcd.printInt((unsigned int)value % 10000, 4); + break; + case PID_SPEED: + lcd.setCursor(0, 0); + lcd.setFontSize(FONT_SIZE_XLARGE); + lcd.printInt((unsigned int)value % 1000, 3); + break; + case PID_THROTTLE: + lcd.setCursor(88, 5); + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.printInt(value % 100, 3); + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.print(" %"); + break; + case PID_ENGINE_LOAD: + lcd.setCursor(12, 5); + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.printInt(value, 3); + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.print(" %"); + break; + } +} + +void initScreen() +{ + lcd.clear(); + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(24, 3); + lcd.print("km/h"); + lcd.setCursor(110, 3); + lcd.print("rpm"); + lcd.setCursor(0, 7); + lcd.print("ENGINE LOAD"); + lcd.setCursor(80, 7); + lcd.print("THROTTLE"); +} + +void setup() +{ + lcd.begin(); + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.println("OBD DISPLAY"); + + delay(500); + obd.begin(); + + lcd.println(); + lcd.println("Connecting..."); + while (!obd.init()); + initScreen(); +} + +void loop() +{ + static byte pids[]= {PID_RPM, PID_SPEED, PID_ENGINE_LOAD, PID_THROTTLE}; + static byte index = 0; + byte pid = pids[index]; + int value; + // send a query to OBD adapter for specified OBD-II pid + if (obd.readPID(pid, value)) { + showData(pid, value); + } + index = (index + 1) % sizeof(pids); + + if (obd.errors >= 2) { + reconnect(); + setup(); + } +} -- cgit v1.2.3 From e79cda0d48877f5f0404791a781e82c4e6e6f456 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Thu, 25 Jan 2018 15:04:07 +1100 Subject: Improve VIN reading --- libraries/OBD/OBD.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/libraries/OBD/OBD.cpp b/libraries/OBD/OBD.cpp index 8dbdd29..92b9bdf 100644 --- a/libraries/OBD/OBD.cpp +++ b/libraries/OBD/OBD.cpp @@ -298,21 +298,31 @@ float COBD::getVoltage() bool COBD::getVIN(char* buffer, byte bufsize) { - if (sendCommand("0902\r", buffer, bufsize)) { - char *p = strstr(buffer, "0: 49 02"); - if (p) { - char *q = buffer; - p += 10; - do { - for (++p; *p == ' '; p += 3) { - if (*q = hex2uint8(p + 1)) q++; - } - p = strchr(p, ':'); - } while(p); - *q = 0; - return true; - } - } + for (byte n = 0; n < 5; n++) { + if (sendCommand("0902\r", buffer, bufsize)) { + int len = hex2uint16(buffer); + char *p = strstr_P(buffer + 4, PSTR("0: 49 02 01")); + if (p) { + char *q = buffer; + p += 11; // skip the header + do { + while (*(++p) == ' '); + for (;;) { + *(q++) = hex2uint8(p); + while (*p && *p != ' ') p++; + while (*p == ' ') p++; + if (!*p || *p == '\r') break; + } + p = strchr(p, ':'); + } while(p); + *q = 0; + if (q - buffer == len - 3) { + return true; + } + } + } + delay(100); + } return false; } -- cgit v1.2.3 From bd86ac57fe9fa492e7e40e09d81de31bed1f449c Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Tue, 30 Jan 2018 22:37:56 +1100 Subject: Add support for Freematics OBD-II UART Adapter V2.1 --- libraries/OBD2UART/OBD2UART.cpp | 244 +++++++++++++++------ libraries/OBD2UART/OBD2UART.h | 74 +++---- .../examples/obd_uart_test/obd_uart_test.ino | 81 ++++--- .../examples/orientation_demo/orientation_demo.ino | 98 +++++++++ .../examples/rpm_led_uart/rpm_led_uart.ino | 9 +- libraries/OBD2UART/keywords.txt | 29 +++ libraries/OBD2UART/library.properties | 9 + 7 files changed, 400 insertions(+), 144 deletions(-) create mode 100644 libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino create mode 100644 libraries/OBD2UART/keywords.txt create mode 100644 libraries/OBD2UART/library.properties diff --git a/libraries/OBD2UART/OBD2UART.cpp b/libraries/OBD2UART/OBD2UART.cpp index 0cb72f1..8406251 100644 --- a/libraries/OBD2UART/OBD2UART.cpp +++ b/libraries/OBD2UART/OBD2UART.cpp @@ -17,12 +17,12 @@ uint16_t hex2uint16(const char *p) { char c = *p; uint16_t i = 0; - for (char n = 0; c && n < 4; c = *(++p)) { + for (uint8_t n = 0; c && n < 4; c = *(++p)) { if (c >= 'A' && c <= 'F') { c -= 7; } else if (c>='a' && c<='f') { c -= 39; - } else if (c == ' ') { + } else if (c == ' ' && n == 2) { continue; } else if (c < '0' || c > '9') { break; @@ -44,7 +44,9 @@ byte hex2uint8(const char *p) else if (c1 < '0' || c1 > '9') return 0; - if (c2 >= 'A' && c2 <= 'F') + if (c2 == 0) + return (c1 & 0xf); + else if (c2 >= 'A' && c2 <= 'F') c2 -= 7; else if (c2 >= 'a' && c2 <= 'f') c2 -= 39; @@ -61,24 +63,15 @@ byte hex2uint8(const char *p) byte COBD::sendCommand(const char* cmd, char* buf, byte bufsize, int timeout) { write(cmd); - dataIdleLoop(); + idleTasks(); return receive(buf, bufsize, timeout); } -void COBD::sendQuery(byte pid) +bool COBD::readPID(byte pid, int& result) { char cmd[8]; sprintf(cmd, "%02X%02X\r", dataMode, pid); -#ifdef DEBUG - debugOutput(cmd); -#endif write(cmd); -} - -bool COBD::readPID(byte pid, int& result) -{ - // send a query command - sendQuery(pid); // receive and parse the response return getResult(pid, result); } @@ -107,7 +100,7 @@ byte COBD::readDTC(uint16_t codes[], byte maxCodes) sprintf_P(buffer, n == 0 ? PSTR("03\r") : PSTR("03%02X\r"), n); write(buffer); if (receive(buffer, sizeof(buffer)) > 0) { - if (!strstr(buffer, "NO DATA")) { + if (!strstr_P(buffer, PSTR("NO DATA"))) { char *p = strstr(buffer, "43"); if (p) { while (codesRead < maxCodes && *p) { @@ -300,20 +293,30 @@ float COBD::getVoltage() bool COBD::getVIN(char* buffer, byte bufsize) { - if (sendCommand("0902\r", buffer, bufsize)) { - char *p = strstr(buffer, "0: 49 02"); - if (p) { - char *q = buffer; - p += 10; - do { - for (++p; *p == ' '; p += 3) { - if (*q = hex2uint8(p + 1)) q++; - } - p = strchr(p, ':'); - } while(p); - *q = 0; - return true; - } + for (byte n = 0; n < 5; n++) { + if (sendCommand("0902\r", buffer, bufsize)) { + int len = hex2uint16(buffer); + char *p = strstr_P(buffer + 4, PSTR("0: 49 02 01")); + if (p) { + char *q = buffer; + p += 11; // skip the header + do { + while (*(++p) == ' '); + for (;;) { + *(q++) = hex2uint8(p); + while (*p && *p != ' ') p++; + while (*p == ' ') p++; + if (!*p || *p == '\r') break; + } + p = strchr(p, ':'); + } while(p); + *q = 0; + if (q - buffer == len - 3) { + return true; + } + } + } + delay(100); } return false; } @@ -362,7 +365,7 @@ byte COBD::getVersion() return version; } -byte COBD::receive(char* buffer, byte bufsize, int timeout) +int COBD::receive(char* buffer, int bufsize, unsigned int timeout) { unsigned char n = 0; unsigned long startTime = millis(); @@ -393,7 +396,7 @@ byte COBD::receive(char* buffer, byte bufsize, int timeout) // timeout break; } - dataIdleLoop(); + idleTasks(); } } if (buffer) { @@ -415,48 +418,77 @@ bool COBD::init(OBD_PROTOCOLS protocol) { const char *initcmd[] = {"ATZ\r", "ATE0\r", "ATH0\r"}; char buffer[64]; + byte stage; m_state = OBD_DISCONNECTED; - for (unsigned char i = 0; i < sizeof(initcmd) / sizeof(initcmd[0]); i++) { - write(initcmd[i]); - if (receive(buffer, sizeof(buffer), OBD_TIMEOUT_LONG) == 0) { - return false; + + for (byte n = 0; n < 2; n++) { + stage = 0; + if (n != 0) reset(); + for (byte i = 0; i < sizeof(initcmd) / sizeof(initcmd[0]); i++) { + delay(10); + if (!sendCommand(initcmd[i], buffer, sizeof(buffer), OBD_TIMEOUT_SHORT)) { + continue; + } } - } - if (protocol != PROTO_AUTO) { - sprintf_P(buffer, PSTR("ATSP %u\r"), protocol); - write(buffer); - if (receive(buffer, sizeof(buffer), OBD_TIMEOUT_LONG) == 0 && !strstr(buffer, "OK")) { - return false; + stage = 1; + if (protocol != PROTO_AUTO) { + sprintf(buffer, "ATSP%u\r", protocol); + delay(10); + if (!sendCommand(buffer, buffer, sizeof(buffer), OBD_TIMEOUT_SHORT) || !strstr(buffer, "OK")) { + continue; + } } - } - - // load pid map - memset(pidmap, 0, sizeof(pidmap)); - bool success = false; - for (byte i = 0; i < 4; i++) { - byte pid = i * 0x20; - sendQuery(pid); - if (receive(buffer, sizeof(buffer), OBD_TIMEOUT_LONG) > 0) { - char *p = buffer; - while ((p = strstr(p, "41 "))) { - p += 3; - if (hex2uint8(p) == pid) { - p += 2; - for (byte n = 0; n < 4 && *(p + n * 3) == ' '; n++) { - pidmap[i * 4 + n] = hex2uint8(p + n * 3 + 1); + stage = 2; + delay(10); + if (!sendCommand("010D\r", buffer, sizeof(buffer), OBD_TIMEOUT_LONG) || checkErrorMessage(buffer)) { + continue; + } + stage = 3; + // load pid map + memset(pidmap, 0, sizeof(pidmap)); + bool success = false; + for (byte i = 0; i < 4; i++) { + byte pid = i * 0x20; + sprintf(buffer, "%02X%02X\r", dataMode, pid); + delay(10); + write(buffer); + if (receive(buffer, sizeof(buffer), OBD_TIMEOUT_LONG) > 0) { + if (checkErrorMessage(buffer)) { + break; + } + char *p = buffer; + while ((p = strstr(p, "41 "))) { + p += 3; + if (hex2uint8(p) == pid) { + p += 2; + for (byte n = 0; n < 4 && *(p + n * 3) == ' '; n++) { + pidmap[i * 4 + n] = hex2uint8(p + n * 3 + 1); + } + success = true; } - success = true; } + } else { + break; } } + if (success) { + stage = 0xff; + break; + } } - - if (success) { + if (stage == 0xff) { m_state = OBD_CONNECTED; errors = 0; + return true; + } else { +#ifdef DEBUG + Serial.print("Stage:"); + Serial.println(stage); +#endif + reset(); + return false; } - return success; } void COBD::end() @@ -477,10 +509,64 @@ bool COBD::setBaudRate(unsigned long baudrate) return true; } -bool COBD::memsInit() +void COBD::reset() +{ + char buf[32]; + sendCommand("ATR\r", buf, sizeof(buf)); + delay(3000); + sendCommand("ATZ\r", buf, sizeof(buf)); +} + +void COBD::uninit() +{ + char buf[32]; + sendCommand("ATPC\r", buf, sizeof(buf)); +} + +byte COBD::checkErrorMessage(const char* buffer) +{ + const char *errmsg[] = {"UNABLE", "ERROR", "TIMEOUT", "NO DATA"}; + for (byte i = 0; i < sizeof(errmsg) / sizeof(errmsg[0]); i++) { + if (strstr(buffer, errmsg[i])) return i + 1; + } + return 0; +} + +uint8_t COBD::getPercentageValue(char* data) +{ + return (uint16_t)hex2uint8(data) * 100 / 255; +} + +uint16_t COBD::getLargeValue(char* data) +{ + return hex2uint16(data); +} + +uint8_t COBD::getSmallValue(char* data) +{ + return hex2uint8(data); +} + +int16_t COBD::getTemperatureValue(char* data) +{ + return (int)hex2uint8(data) - 40; +} + +bool COBD::memsInit(bool fusion) { char buf[16]; - return sendCommand("ATTEMP\r", buf, sizeof(buf)) > 0 && !strchr(buf, '?'); + if (!sendCommand("ATTEMP\r", buf, sizeof(buf)) > 0 || strchr(buf, '?')) + return false; + if (fusion) { + m_fusion = true; + return sendCommand("ATQU1\r", buf, sizeof(buf)); + } else { + if (m_fusion) { + m_fusion = false; + sendCommand("ATQU0\r", buf, sizeof(buf)); + } + return true; + } } bool COBD::memsRead(int16_t* acc, int16_t* gyr, int16_t* mag, int16_t* temp) @@ -515,6 +601,20 @@ bool COBD::memsRead(int16_t* acc, int16_t* gyr, int16_t* mag, int16_t* temp) } while (0); if (!success) return false; } + if (mag) { + success = false; + if (sendCommand("ATMAG\r", buf, sizeof(buf)) > 0) do { + char* p = getResultValue(buf); + if (!p) break; + mag[0] = atoi(p++); + if (!(p = strchr(p, ','))) break; + mag[1] = atoi(++p); + if (!(p = strchr(p, ','))) break; + mag[2] = atoi(++p); + success = true; + } while (0); + if (!success) return false; + } if (temp) { success = false; if (sendCommand("ATTEMP\r", buf, sizeof(buf)) > 0) { @@ -529,6 +629,24 @@ bool COBD::memsRead(int16_t* acc, int16_t* gyr, int16_t* mag, int16_t* temp) return true; } +bool COBD::memsOrientation(float& yaw, float& pitch, float& roll) +{ + char buf[64]; + bool success = false; + if (sendCommand("ATORI\r", buf, sizeof(buf)) > 0) do { + Serial.println(buf); + char* p = getResultValue(buf); + if (!p) break; + yaw = (float)atof(p++); + if (!(p = strchr(p, ','))) break; + pitch = (float)atoi(++p); + if (!(p = strchr(p, ','))) break; + roll = (float) atof(++p); + success = true; + } while (0); + return success; +} + #ifdef DEBUG void COBD::debugOutput(const char *s) { diff --git a/libraries/OBD2UART/OBD2UART.h b/libraries/OBD2UART/OBD2UART.h index 62ac18b..2674274 100644 --- a/libraries/OBD2UART/OBD2UART.h +++ b/libraries/OBD2UART/OBD2UART.h @@ -8,8 +8,7 @@ #include #define OBD_TIMEOUT_SHORT 1000 /* ms */ -#define OBD_TIMEOUT_LONG 5000 /* ms */ -#define OBD_TIMEOUT_GPS 200 /* ms */ +#define OBD_TIMEOUT_LONG 10000 /* ms */ #ifndef OBDUART #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168P__) @@ -19,6 +18,10 @@ #endif #endif +#ifdef ESP32 +extern HardwareSerial Serial1; +#endif + // Mode 1 PIDs #define PID_ENGINE_LOAD 0x04 #define PID_COOLANT_TEMP 0x05 @@ -73,23 +76,12 @@ #define PID_ENGINE_REF_TORQUE 0x63 // non-OBD/custom PIDs (no mode number) -#define PID_GPS_LATITUDE 0xA -#define PID_GPS_LONGITUDE 0xB -#define PID_GPS_ALTITUDE 0xC -#define PID_GPS_SPEED 0xD -#define PID_GPS_HEADING 0xE -#define PID_GPS_SAT_COUNT 0xF -#define PID_GPS_TIME 0x10 -#define PID_GPS_DATE 0x11 #define PID_ACC 0x20 #define PID_GYRO 0x21 #define PID_COMPASS 0x22 #define PID_MEMS_TEMP 0x23 #define PID_BATTERY_VOLTAGE 0x24 -// custom PIDs for calculated data -#define PID_TRIP_DISTANCE 0x30 - typedef enum { PROTO_AUTO = 0, PROTO_ISO_9141_2 = 3, @@ -115,13 +107,16 @@ uint8_t hex2uint8(const char *p); class COBD { public: - COBD():dataMode(1),errors(0),m_state(OBD_DISCONNECTED) {} // begin serial UART virtual byte begin(); + // terminate communication channel + virtual void end(); // initialize OBD-II connection virtual bool init(OBD_PROTOCOLS protocol = PROTO_AUTO); + // reset OBD-II connection + virtual void reset(); // un-initialize OBD-II connection - virtual void end(); + virtual void uninit(); // set serial baud rate virtual bool setBaudRate(unsigned long baudrate); // get connection state @@ -144,12 +139,12 @@ public: virtual float getVoltage(); // get VIN as a string, buffer length should be >= OBD_RECV_BUF_SIZE virtual bool getVIN(char* buffer, byte bufsize); - // initialize MEMS sensor - virtual bool memsInit(); + // initialize MEMS sensor (enable or disable sensor fusion by quanterion algorithm) + virtual bool memsInit(bool fusion = false); // read out MEMS data (acc for accelerometer, gyr for gyroscope, temp in 0.1 celcius degree) virtual bool memsRead(int16_t* acc, int16_t* gyr = 0, int16_t* mag = 0, int16_t* temp = 0); - // send query for specified PID - virtual void sendQuery(byte pid); + // get computed orientation values + virtual bool memsOrientation(float& yaw, float& pitch, float& roll); // retrive and parse the response of specifie PID virtual bool getResult(byte& pid, int& result); // determine if the PID is supported @@ -157,37 +152,26 @@ public: // get adapter firmware version virtual byte getVersion(); // set current PID mode - byte dataMode; + byte dataMode = 1; // occurrence of errors - byte errors; + byte errors = 0; // bit map of supported PIDs - byte pidmap[4 * 4]; + byte pidmap[4 * 4] = {0}; protected: virtual char* getResponse(byte& pid, char* buffer, byte bufsize); - virtual byte receive(char* buffer, byte bufsize, int timeout = OBD_TIMEOUT_SHORT); + virtual int receive(char* buffer, int bufsize, unsigned int timeout = OBD_TIMEOUT_SHORT); virtual void write(const char* s); - virtual void dataIdleLoop() {} - void recover(); - void debugOutput(const char* s); - int normalizeData(byte pid, char* data); - OBD_STATES m_state; + virtual uint8_t getPercentageValue(char* data); + virtual uint16_t getLargeValue(char* data); + virtual uint8_t getSmallValue(char* data); + virtual int16_t getTemperatureValue(char* data); + virtual int normalizeData(byte pid, char* data); + virtual byte checkErrorMessage(const char* buffer); + virtual char* getResultValue(char* buf); + OBD_STATES m_state = OBD_DISCONNECTED; private: - virtual uint8_t getPercentageValue(char* data) - { - return (uint16_t)hex2uint8(data) * 100 / 255; - } - virtual uint16_t getLargeValue(char* data) - { - return hex2uint16(data); - } - virtual uint8_t getSmallValue(char* data) - { - return hex2uint8(data); - } - virtual int16_t getTemperatureValue(char* data) - { - return (int)hex2uint8(data) - 40; - } - char* getResultValue(char* buf); + void recover(); + virtual void idleTasks() {} + bool m_fusion = false; }; diff --git a/libraries/OBD2UART/examples/obd_uart_test/obd_uart_test.ino b/libraries/OBD2UART/examples/obd_uart_test/obd_uart_test.ino index 9b11eab..4d30b0e 100644 --- a/libraries/OBD2UART/examples/obd_uart_test/obd_uart_test.ino +++ b/libraries/OBD2UART/examples/obd_uart_test/obd_uart_test.ino @@ -1,25 +1,32 @@ /************************************************************************* -* Testing sketch for Freematics OBD-II UART Adapter +* Testing sketch for Freematics OBD-II UART Adapter V1/V2/V2.1 +* Performs AT command-set test * Reads and prints several OBD-II PIDs value -* Distributed under GPL v2.0 -* Visit http://freematics.com for more information -* Written by Stanley Huang +* Reads and prints motion sensor data if available +* Distributed under BSD +* Visit https://freematics.com/products for more product information +* Written by Stanley Huang *************************************************************************/ -#include #include -// On Arduino Leonardo, Micro, MEGA or DUE, hardware serial can be used for output -// as OBD-II UART adapter uses to Serial1 -// On Arduino UNO and those have no Serial1, we use software serial for output -// as OBD-II UART adapter uses to Serial +// On Arduino Leonardo, Micro, MEGA or DUE, hardware serial can be used for output as the adapter occupies Serial1 +// On Arduino UNO and those have no Serial1, we use software serial for output as the adapter uses Serial +#ifdef ARDUINO_AVR_UNO +#include SoftwareSerial mySerial(A2, A3); -//#define mySerial Serial +#else +#define mySerial Serial +#endif + +#if defined(ESP32) && !defined(Serial1) +HardwareSerial Serial1(1); +#endif COBD obd; bool hasMEMS; -void testOut() +void testATcommands() { static const char cmds[][6] = {"ATZ\r", "ATI\r", "ATH0\r", "ATRV\r", "0100\r", "010C\r", "0902\r"}; char buf[128]; @@ -93,11 +100,12 @@ void readBatteryVoltage() void readMEMS() { - int acc[3]; - int gyro[3]; - int temp; + int16_t acc[3] = {0}; + int16_t gyro[3] = {0}; + int16_t mag[3] = {0}; + int16_t temp = 0; - if (!obd.memsRead(acc, gyro, 0, &temp)) return; + if (!obd.memsRead(acc, gyro, mag, &temp)) return; mySerial.print('['); mySerial.print(millis()); @@ -117,6 +125,13 @@ void readMEMS() mySerial.print('/'); mySerial.print(gyro[2]); + mySerial.print(" MAG:"); + mySerial.print(mag[0]); + mySerial.print('/'); + mySerial.print(mag[1]); + mySerial.print('/'); + mySerial.print(mag[2]); + mySerial.print(" TEMP:"); mySerial.print((float)temp / 10, 1); mySerial.println("C"); @@ -127,23 +142,24 @@ void setup() mySerial.begin(115200); while (!mySerial); - // this will begin serial - byte version = obd.begin(); - - mySerial.print("Freematics OBD-II Adapter "); - if (version > 0) { - mySerial.print("Ver. "); - mySerial.print(version / 10); - mySerial.print('.'); - mySerial.println(version % 10); - } else { - mySerial.println("not detected"); - for (;;); + for (;;) { + delay(1000); + byte version = obd.begin(); + mySerial.print("Freematics OBD-II Adapter "); + if (version > 0) { + mySerial.println("detected"); + mySerial.print("OBD firmware version "); + mySerial.print(version / 10); + mySerial.print('.'); + mySerial.println(version % 10); + break; + } else { + mySerial.println("not detected"); + } } - delay(1000); // send some commands for testing and show response for debugging purpose - testOut(); + testATcommands(); hasMEMS = obd.memsInit(); mySerial.print("MEMS:"); @@ -151,8 +167,9 @@ void setup() // initialize OBD-II adapter do { - mySerial.println("Init..."); + mySerial.println("Connecting..."); } while (!obd.init()); + mySerial.println("OBD connected!"); char buf[64]; if (obd.getVIN(buf, sizeof(buf))) { @@ -160,7 +177,7 @@ void setup() mySerial.println(buf); } - unsigned int codes[6]; + uint16_t codes[6]; byte dtcCount = obd.readDTC(codes, 6); if (dtcCount == 0) { mySerial.println("No DTC"); @@ -176,7 +193,6 @@ void setup() delay(5000); } - void loop() { readPIDSingle(); @@ -186,3 +202,4 @@ void loop() readMEMS(); } } + diff --git a/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino b/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino new file mode 100644 index 0000000..923c6ac --- /dev/null +++ b/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino @@ -0,0 +1,98 @@ +/************************************************************************* +* Testing sketch for Freematics OBD-II UART Adapter V2.1 +* Reads and prints motion sensor data and computed orientation data +* Distributed under BSD +* Visit https://freematics.com/products for more product information +* Written by Stanley Huang +*************************************************************************/ + +#include + +// On Arduino Leonardo, Micro, MEGA or DUE, hardware serial can be used for output as the adapter occupies Serial1 +// On Arduino UNO and those have no Serial1, we use software serial for output as the adapter uses Serial +#ifdef ARDUINO_AVR_UNO +#include +SoftwareSerial mySerial(A2, A3); +#else +#define mySerial Serial +#endif + +#if defined(ESP32) && !defined(Serial1) +HardwareSerial Serial1(1); +#endif + +COBD obd; +bool hasMEMS; + +void setup() +{ + mySerial.begin(115200); + while (!mySerial); + + // this will begin serial + + for (;;) { + delay(1000); + byte version = obd.begin(); + mySerial.print("Freematics OBD-II Adapter "); + if (version > 0) { + mySerial.println("detected"); + break; + } else { + mySerial.println("not detected"); + } + } + + // initialize MEMS with sensor fusion enabled + hasMEMS = obd.memsInit(true); + mySerial.print("MEMS:"); + mySerial.println(hasMEMS ? "OK" : "NO"); + if (!hasMEMS) { + for (;;); + } +} + + +void loop() +{ + int16_t acc[3] = {0}; + int16_t gyro[3] = {0}; + int16_t mag[3] = {0}; + + if (!obd.memsRead(acc, gyro, mag)) return; + + mySerial.print("ACC:"); + mySerial.print(acc[0]); + mySerial.print('/'); + mySerial.print(acc[1]); + mySerial.print('/'); + mySerial.print(acc[2]); + + mySerial.print(" GYRO:"); + mySerial.print(gyro[0]); + mySerial.print('/'); + mySerial.print(gyro[1]); + mySerial.print('/'); + mySerial.print(gyro[2]); + + mySerial.print(" MAG:"); + mySerial.print(mag[0]); + mySerial.print('/'); + mySerial.print(mag[1]); + mySerial.print('/'); + mySerial.print(mag[2]); + + mySerial.println(); + + float yaw, pitch, roll; + if (obd.memsOrientation(yaw, pitch, roll)) { + mySerial.print("Orientation: "); + mySerial.print(yaw, 2); + mySerial.print(' '); + mySerial.print(pitch, 2); + mySerial.print(' '); + mySerial.println(roll, 2); + } + + delay(100); +} diff --git a/libraries/OBD2UART/examples/rpm_led_uart/rpm_led_uart.ino b/libraries/OBD2UART/examples/rpm_led_uart/rpm_led_uart.ino index 3e80ae3..5b7a13e 100644 --- a/libraries/OBD2UART/examples/rpm_led_uart/rpm_led_uart.ino +++ b/libraries/OBD2UART/examples/rpm_led_uart/rpm_led_uart.ino @@ -1,8 +1,9 @@ /************************************************************************* -* Sample sketch based on OBD-II library for Arduino -* Distributed under GPL v2.0 -* Visit http://freematics.com for more information -* (C)2012-2014 Stanley Huang +* Testing sketch for Freematics OBD-II UART Adapter +* Reads engine RPM data from OBD and triggers Arduino onboard LED +* Distributed under BSD +* Visit https://freematics.com/products for more product information +* Written by Stanley Huang *************************************************************************/ #include diff --git a/libraries/OBD2UART/keywords.txt b/libraries/OBD2UART/keywords.txt new file mode 100644 index 0000000..316a4fb --- /dev/null +++ b/libraries/OBD2UART/keywords.txt @@ -0,0 +1,29 @@ +################################################################################ +# Datatypes (KEYWORD1) +################################################################################ +COBD KEYWORD1 + +################################################################################ +# Methods and Functions (KEYWORD2) +################################################################################ +begin KEYWORD2 +end KEYWORD2 +init KEYWORD2 +uninit KEYWORD2 +reset KEYWORD2 + +readPID KEYWORD2 +readDTC KEYWORD2 +clearDTC KEYWORD2 +getVoltage KEYWORD2 +getVIN KEYWORD2 + +memsInit KEYWORD2 +memsRead KEYWORD2 +memsOrientation KEYWORD2 + +################################################################################ +# Constants (LITERAL1) +################################################################################ +OBD_PROTOCOLS LITERAL1 +OBD_STATES LITERAL1 \ No newline at end of file diff --git a/libraries/OBD2UART/library.properties b/libraries/OBD2UART/library.properties new file mode 100644 index 0000000..cbb921d --- /dev/null +++ b/libraries/OBD2UART/library.properties @@ -0,0 +1,9 @@ +name=OBD2UART +version=1.2 +author=Stanley Huang +maintainer=Stanley Huang +sentence=Arduino library for Freematics OBD-II UART Adapter +paragraph=Arduino library for Freematics OBD-II UART Adapter +category=Communication +url=https://freematics.com +includes=OBD2UART.h \ No newline at end of file -- cgit v1.2.3 From ec35ee0fab747dd7a7ef9f0996970b094a00d4f3 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Tue, 30 Jan 2018 22:51:39 +1100 Subject: Add support for Freematics OBD-II UART Adapter V2.1 --- libraries/OBD2UART/OBD2UART.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/OBD2UART/OBD2UART.cpp b/libraries/OBD2UART/OBD2UART.cpp index 8406251..826b3d2 100644 --- a/libraries/OBD2UART/OBD2UART.cpp +++ b/libraries/OBD2UART/OBD2UART.cpp @@ -634,7 +634,6 @@ bool COBD::memsOrientation(float& yaw, float& pitch, float& roll) char buf[64]; bool success = false; if (sendCommand("ATORI\r", buf, sizeof(buf)) > 0) do { - Serial.println(buf); char* p = getResultValue(buf); if (!p) break; yaw = (float)atof(p++); -- cgit v1.2.3 From 25d95246ea97492ac0979d27e807ff3e8e3a9775 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Wed, 31 Jan 2018 11:52:45 +1100 Subject: Update --- .../OBD2UART/examples/orientation_demo/orientation_demo.ino | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino b/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino index 923c6ac..e04949c 100644 --- a/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino +++ b/libraries/OBD2UART/examples/orientation_demo/orientation_demo.ino @@ -22,7 +22,6 @@ HardwareSerial Serial1(1); #endif COBD obd; -bool hasMEMS; void setup() { @@ -44,11 +43,11 @@ void setup() } // initialize MEMS with sensor fusion enabled - hasMEMS = obd.memsInit(true); - mySerial.print("MEMS:"); - mySerial.println(hasMEMS ? "OK" : "NO"); + bool hasMEMS = obd.memsInit(true); + mySerial.print("Motion sensor is "); + mySerial.println(hasMEMS ? "present" : "not present"); if (!hasMEMS) { - for (;;); + for (;;) delay(1000); } } -- cgit v1.2.3 From 33999a3101275925071ad9f5b2b31d914e2c6b94 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Wed, 31 Jan 2018 22:32:00 +1100 Subject: Fix typo --- libraries/OBD2UART/OBD2UART.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/OBD2UART/OBD2UART.cpp b/libraries/OBD2UART/OBD2UART.cpp index 826b3d2..76968b9 100644 --- a/libraries/OBD2UART/OBD2UART.cpp +++ b/libraries/OBD2UART/OBD2UART.cpp @@ -9,10 +9,6 @@ //#define DEBUG Serial -#ifdef ESP32 -extern HardwareSerial Serial1; -#endif - uint16_t hex2uint16(const char *p) { char c = *p; @@ -555,7 +551,7 @@ int16_t COBD::getTemperatureValue(char* data) bool COBD::memsInit(bool fusion) { char buf[16]; - if (!sendCommand("ATTEMP\r", buf, sizeof(buf)) > 0 || strchr(buf, '?')) + if (sendCommand("ATTEMP\r", buf, sizeof(buf)) <= 0 || strchr(buf, '?')) return false; if (fusion) { m_fusion = true; -- cgit v1.2.3 From 8b783513a80861163e4f95a8ffcc60e9a293fc5d Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Tue, 13 Feb 2018 14:44:15 +1100 Subject: Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 006479c..d31d4cd 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ Arduino OBD-II Adapter Library & Sketches ========================================= -(C)2012-2017 Freematics.com +(C)2012-2018 Freematics.com -OBD-II Adapter for Arduino is a product that works as a vehicle OBD-II data bridge for Arduino (literally all embedded platforms) with open-source Arduino library provided. Besides providing easy-to-use OBD-II data access, it also integrates 6-axis MEMS sensor module and a voltmeter for measuring vehicle battery power. The adapter draws power from OBD-II port and convert it to 5V for powering attached device. +OBD-II Adapter for Arduino is a product that works as a vehicle OBD-II data bridge for Arduino (literally all embedded platforms) with open-source Arduino library provided. Besides providing easy-to-use OBD-II data access, it also integrates 9-DOF motion sensor and voltmeter for measuring vehicle battery power. The adapter draws power from OBD-II port and convert it to 5V for powering attached device. -OBD-II Adapter: http://freematics.com/pages/products/arduino-obd-adapter/ +Related Products -OBD-II Telematics DIY Kit: http://freematics.com/pages/products/arduino-telematics-kit-3/ +* [Freematics OBD-II UART Adapter](http://freematics.com/pages/products/arduino-obd-adapter/) +* [OBD-II Telematics Mega Kit](http://freematics.com/pages/products/arduino-telematics-kit-3/) ![Image](http://www.arduinodev.com/wp-content/uploads/2012/03/obdkit1-150x150.jpg) -- cgit v1.2.3 From fca6572ef38a7daf923ac6e8c87d056d1f1c5671 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Tue, 13 Feb 2018 14:45:15 +1100 Subject: Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d31d4cd..7400f33 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ OBD-II Adapter for Arduino is a product that works as a vehicle OBD-II data brid Related Products -* [Freematics OBD-II UART Adapter](http://freematics.com/pages/products/arduino-obd-adapter/) -* [OBD-II Telematics Mega Kit](http://freematics.com/pages/products/arduino-telematics-kit-3/) +* [Freematics OBD-II UART Adapter](https://freematics.com/pages/products/freematics-obd-ii-uart-adapter-mk2/) +* [Freematics OBD-II I2C Adapter](https://freematics.com/pages/products/arduino-obd-adapter/) +* [OBD-II Telematics Mega Kit](https://freematics.com/pages/products/arduino-telematics-kit-3/) ![Image](http://www.arduinodev.com/wp-content/uploads/2012/03/obdkit1-150x150.jpg) -- cgit v1.2.3 From 2f38e4d9e7b63ec843fad7a371d8c3542bf70f78 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Fri, 23 Mar 2018 11:26:56 +1100 Subject: Update README.txt --- nanologger/README.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/nanologger/README.txt b/nanologger/README.txt index 6fbb9b5..115b320 100644 --- a/nanologger/README.txt +++ b/nanologger/README.txt @@ -1,8 +1,5 @@ This is the source code for the Arduino OBD-II data logger, which displays (on a 128x64 OLED display module) and records (to a SD card) a selected set of OBD-II data. -The recorded data is stored in CSV format and the file can be illustrated into a graphic chart by a free service at: -http://freematics.com/chart/ - To compile the code with Arduino IDE, please copy all library files from the libraries directory to Arduino's libraries directory. To open the project file (cbp), please download CodeBlocks Arduino Edition (http://arduinodev.com/codeblocks). -- cgit v1.2.3 From 1298f6387eadbe7518850790b75766af7b571c35 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Fri, 23 Mar 2018 11:27:39 +1100 Subject: Update README.txt --- nanologger/README.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/nanologger/README.txt b/nanologger/README.txt index 115b320..d381889 100644 --- a/nanologger/README.txt +++ b/nanologger/README.txt @@ -2,6 +2,4 @@ This is the source code for the Arduino OBD-II data logger, which displays (on a To compile the code with Arduino IDE, please copy all library files from the libraries directory to Arduino's libraries directory. -To open the project file (cbp), please download CodeBlocks Arduino Edition (http://arduinodev.com/codeblocks). - The source code is distributed under GPL license. -- cgit v1.2.3 From da6126b1c37ed3aa8e095a1dcc8509d4537c4819 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Fri, 23 Mar 2018 11:35:13 +1100 Subject: Create README.md --- nanotimer/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 nanotimer/README.md diff --git a/nanotimer/README.md b/nanotimer/README.md new file mode 100644 index 0000000..2698310 --- /dev/null +++ b/nanotimer/README.md @@ -0,0 +1,3 @@ +This sketch works as a Performance Box. It displays live speed (from OBD-II) of the vehicle and the time used for reaching speed of 60km/h, 100km/h, 200km/h and distance of 400m. Measuring is started automatically (when vehicle starts moving). + +![Freematics Nano Kit running NanoTimer sketch](https://freematics.com/pages/wp-content/uploads/2014/08/DSC04398-1000.jpg) -- cgit v1.2.3