Forum >Replies by budmc77
userhead budmc77
Replies (2)
  • You Reply: Thanks but I'm still getting the same results even with a different sketch name. Any other suggestions?
  • You Reply: Stanley,
        I'm still getting the error even with the updated library. The cpp and header is in my Arudino library's folder and I know its recognizing it because if I comment out #include <OBD.h> I get the error...
    [code]
    rpm_led:11: error: 'COBD' does not name a type
    rpm_led.ino: In function 'void setup()':
    rpm_led:18: error: 'obd' was not declared in this scope
    rpm_led.ino: In function 'void loop()':
    rpm_led:26: error: 'obd' was not declared in this scope
    rpm_led:26: error: 'PID_RPM' was not declared in this scope[/code]

    as oppose to

    [code]rpm_led.ino: In function 'void setup()':
    rpm_led:18: error: 'class COBD' has no member named 'begin'
    rpm_led:20: error: 'class COBD' has no member named 'init'
    rpm_led.ino: In function 'void loop()':
    rpm_led:26: error: 'class COBD' has no member named 'readSensor'
    [/code]


    Any suggestions?

    OBD.h 
    [code]/*************************************************************************
    * Arduino Library for OBD-II UART Adapter
    * Distributed under GPL v2.0
    * Copyright (c) 2012~2013 Stanley Huang <[email protected]>
    * All rights reserved.
    *************************************************************************/

    #define OBD_TIMEOUT_SHORT 2000 /* ms */
    #define OBD_TIMEOUT_LONG 7000 /* ms */
    #define OBD_TIMEOUT_INIT 3000 /* ms */
    #define OBD_SERIAL_BAUDRATE 38400
    #define OBD_RECV_BUF_SIZE 64

    #ifndef OBDUART
    #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
    #define OBDUART Serial1
    #else
    #define OBDUART Serial
    #endif
    #endif

    // mode 0 pids
    #define PID_RPM 0x0C
    #define PID_SPEED 0x0D
    #define PID_THROTTLE 0x11
    #define PID_ENGINE_LOAD 0x04
    #define PID_COOLANT_TEMP 0x05
    #define PID_INTAKE_TEMP 0x0F
    #define PID_MAF_FLOW 0x10
    #define PID_ABS_ENGINE_LOAD 0x43
    #define PID_AMBIENT_TEMP 0x46
    #define PID_FUEL_PRESSURE 0x0A
    #define PID_INTAKE_MAP 0x0B
    #define PID_BAROMETRIC 0x33
    #define PID_TIMING_ADVANCE 0x0E
    #define PID_FUEL_LEVEL 0x2F
    #define PID_RUNTIME 0x1F
    #define PID_DISTANCE 0x31

    unsigned int hex2uint16(const char *p);
    unsigned char hex2uint8(const char *p);

    class COBD
    {
    public:
    COBD():dataMode(1),errors(0) {}
    void begin();
    bool init(bool passive = false);
    bool readSensor(byte pid, int& result, bool passive = false);
    bool isValidPID(byte pid);
    void sleep(int seconds);
    // Query and GetResponse for advanced usage only
    void sendQuery(byte pid);
    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 normalizeData(byte pid, char* data);
    static int getPercentageValue(char* data)
    {
    return (int)hex2uint8(data) * 100 / 255;
    }
    static int getLargeValue(char* data)
    {
    return hex2uint16(data);
    }
    static int getSmallValue(char* data)
    {
    return hex2uint8(data);
    }
    static int getTemperatureValue(char* data)
    {
    return (int)hex2uint8(data) - 40;
    }
    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];
    byte vin[17];
    };[/code]

    OBD.cpp
    [code]/*************************************************************************
    * Arduino Library for OBD-II UART Adapter
    * Distributed under GPL v2.0
    * Copyright (c) 2012~2013 Stanley Huang <[email protected]>
    * All rights reserved.
    *************************************************************************/

    #include <Arduino.h>
    #include <avr/pgmspace.h>
    #include "OBD.h"

    #define MAX_CMD_LEN 6

    const char PROGMEM s_initcmd[][MAX_CMD_LEN] = {"ATZ\r","ATE0\r","ATL1\r"};
    const char PROGMEM s_searching[] = "SEARCHING";
    const char PROGMEM s_cmd_fmt[] = "%02X%02X 1\r";
    const char PROGMEM s_cmd_sleep[] = "atlp\r";
    const char PROGMEM s_cmd_vin[] = "0902\r";

    unsigned int hex2uint16(const char *p)
    {
    char c = *p;
    unsigned int i = 0;
    for (char 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 == ' ') {
                continue;
            } else if (c < '0' || c > '9') {
    break;
            }
    i = (i << 4) | (c & 0xF);
    n++;
    }
    return i;
    }

    unsigned char hex2uint8(const char *p)
    {
    unsigned char c1 = *p;
    unsigned char c2 = *(p + 1);
    if (c1 >= 'A' && c1 <= 'F')
    c1 -= 7;
    else if (c1 >='a' && c1 <= 'f')
        c1 -= 39;
    else if (c1 < '0' || c1 > '9')
    return 0;

    if (c2 >= 'A' && c2 <= 'F')
    c2 -= 7;
    else if (c2 >= 'a' && c2 <= 'f')
        c2 -= 39;
    else if (c2 < '0' || c2 > '9')
    return 0;

    return c1 << 4 | (c2 & 0xf);
    }

    void COBD::sendQuery(unsigned char pid)
    {
    char cmd[8];
    sprintf_P(cmd, s_cmd_fmt, dataMode, pid);
    write(cmd);
    }

    bool COBD::readSensor(byte pid, int& result, bool passive)
    {
    // send a query command
    sendQuery(pid);
    // wait for reponse
    bool hasData;
    unsigned long tick = millis();
    do {
    dataIdleLoop();
    } while (!(hasData = available()) && millis() - tick < OBD_TIMEOUT_SHORT);
    if (!hasData) {
            write('\r');
    errors++;
    return false;
    }
    // receive and parse the response
    return getResponseParsed(pid, result);
    }

    bool COBD::available()
    {
    return OBDUART.available();
    }

    char COBD::read()
    {
    char c = OBDUART.read();
    return c;
    }

    void COBD::write(const char* s)
    {
    OBDUART.write(s);
    }

    void COBD::write(const char c)
    {
    OBDUART.write(c);
    }

    int COBD::normalizeData(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();
    static const char responseSign[3] = {'4', '1', ' '};
    byte i = 0;

    for (;;) {
    if (available()) {
    char c = read();
    buffer[i] = c;
    if (++i == OBD_RECV_BUF_SIZE - 1) {
        // buffer overflow
        break;
    }
    if (c == '>' && i > 6) {
    // prompt char reached
    break;
    }
    } else {
    buffer[i] = 0;
    unsigned int timeout;
    if (dataMode != 1 || strstr_P(buffer, s_searching)) {
    timeout = OBD_TIMEOUT_LONG;
    } else {
    timeout = OBD_TIMEOUT_SHORT;
    }
    if (millis() - startTime > timeout) {
    // timeout
    errors++;
    break;
    }
    dataIdleLoop();
    }
    }
    buffer[i] = 0;

    if (i > 6) {
    char *p = buffer;
    while ((p = strstr(p, responseSign))) {
        p += 3;
        byte curpid = hex2uint8(p);
        if (pid == 0) pid = curpid;
        if (curpid == pid) {
            errors = 0;
            p += 2;
            if (*p == ' ')
                return p + 1;
        }
    };
    }
    return 0;
    }

    bool COBD::getResponseParsed(byte& pid, int& result)
    {
    char buffer[OBD_RECV_BUF_SIZE];
    char* data = getResponse(pid, buffer);
    if (!data) {
    // try recover next time
    write('\r');
    return false;
    }
    result = normalizeData(pid, data);
    return true;
    }

    void COBD::sleep(int seconds)
    {
    char cmd[MAX_CMD_LEN];
    strcpy_P(cmd, s_cmd_sleep);
    write(cmd);
    if (seconds) {
    delay((unsigned long)seconds << 10);
    write('\r');
    }
    }

    bool COBD::isValidPID(byte pid)
    {
    if (pid >= 0x7f)
    return false;
    pid--;
    byte i = pid >> 3;
    byte b = 0x80 >> (pid & 0x7);
    return pidmap[i] & b;
    }

    void COBD::begin()
    {
    OBDUART.begin(OBD_SERIAL_BAUDRATE);
    }

    bool COBD::init(bool passive)
    {
    unsigned long currentMillis;
    unsigned char n;
    char prompted;
    char buffer[OBD_RECV_BUF_SIZE];

    for (unsigned char i = 0; i < sizeof(s_initcmd) / sizeof(s_initcmd[0]); i++) {
    if (!passive) {
    char cmd[MAX_CMD_LEN];
    strcpy_P(cmd, s_initcmd[i]);
    write(cmd);
    }
    n = 0;
    prompted = 0;
    currentMillis = millis();
    for (;;) {
    if (available()) {
    char c = read();
    if (n > 2 && c == '>') {
        buffer[n] = 0;
        prompted++;
    } else if (n < OBD_RECV_BUF_SIZE - 1) {
        buffer[n++] = c;
    }
    } else if (prompted) {
    break;
    } else {
    unsigned long elapsed = millis() - currentMillis;
    if (elapsed > OBD_TIMEOUT_INIT) {
    // init timeout
    //WriteData("\r");
    return false;
    }
    initIdleLoop();
    }
    }
    }
    while (available()) read();

    // load pid map
    memset(pidmap, 0, sizeof(pidmap));
    for (byte i = 0; i < 4; i++) {
            byte pid = i * 0x20;
            sendQuery(pid);
            char* data = getResponse(pid, buffer);
            if (!data) break;
            data--;
            for (byte n = 0; n < 4; n++) {
                if (data[n * 3] != ' ')
                    break;
                pidmap[i * 4 + n] = hex2uint8(data + n * 3 + 1);
            }
    }
    while (available()) read();

    errors = 0;
    return true;
    }[/code]

    OBD.ino
    [code]/*************************************************************************
    * Sample sketch based on OBD-II library for Arduino
    * Distributed under GPL v2.0
    * Copyright (c) 2012-2013 Stanley Huang <[email protected]>
    * All rights reserved.
    *************************************************************************/

    #include <Arduino.h>
    #include "OBD.h"

    COBD obd;

    void setup()
    {
      // we'll use the debug LED as output
      pinMode(13, OUTPUT); 
      // start communication with OBD-II UART adapter
      obd.begin();
      // initiate OBD-II connection until success
      while (!obd.init()); 
    }

    void loop()
    {
      int value;
      if (obd.readSensor(PID_RPM, value)) {
        // RPM is read and stored in 'value'
        // light on LED when RPM exceeds 5000
        digitalWrite(13, value > 5000 ? HIGH : LOW);
      }
    }[/code]