/************************************************************************* * Arduino Library for Freematics OBD-II UART Adapter * Distributed under BSD License * Visit https://freematics.com for more information * (C)2012-2019 Stanley Huang *************************************************************************/ #include #define OBD_TIMEOUT_SHORT 1000 /* ms */ #define OBD_TIMEOUT_LONG 10000 /* ms */ #ifndef OBDUART #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168P__) #define OBDUART Serial #else #define OBDUART Serial1 #endif #endif #ifdef ESP32 extern HardwareSerial Serial1; #endif // Mode 1 PIDs #define PID_ENGINE_LOAD 0x04 #define PID_COOLANT_TEMP 0x05 #define PID_SHORT_TERM_FUEL_TRIM_1 0x06 #define PID_LONG_TERM_FUEL_TRIM_1 0x07 #define PID_SHORT_TERM_FUEL_TRIM_2 0x08 #define PID_LONG_TERM_FUEL_TRIM_2 0x09 #define PID_FUEL_PRESSURE 0x0A #define PID_INTAKE_MAP 0x0B #define PID_RPM 0x0C #define PID_SPEED 0x0D #define PID_TIMING_ADVANCE 0x0E #define PID_INTAKE_TEMP 0x0F #define PID_MAF_FLOW 0x10 #define PID_THROTTLE 0x11 #define PID_AUX_INPUT 0x1E #define PID_RUNTIME 0x1F #define PID_DISTANCE_WITH_MIL 0x21 #define PID_COMMANDED_EGR 0x2C #define PID_EGR_ERROR 0x2D #define PID_COMMANDED_EVAPORATIVE_PURGE 0x2E #define PID_FUEL_LEVEL 0x2F #define PID_WARMS_UPS 0x30 #define PID_DISTANCE 0x31 #define PID_EVAP_SYS_VAPOR_PRESSURE 0x32 #define PID_BAROMETRIC 0x33 #define PID_CATALYST_TEMP_B1S1 0x3C #define PID_CATALYST_TEMP_B2S1 0x3D #define PID_CATALYST_TEMP_B1S2 0x3E #define PID_CATALYST_TEMP_B2S2 0x3F #define PID_CONTROL_MODULE_VOLTAGE 0x42 #define PID_ABSOLUTE_ENGINE_LOAD 0x43 #define PID_AIR_FUEL_EQUIV_RATIO 0x44 #define PID_RELATIVE_THROTTLE_POS 0x45 #define PID_AMBIENT_TEMP 0x46 #define PID_ABSOLUTE_THROTTLE_POS_B 0x47 #define PID_ABSOLUTE_THROTTLE_POS_C 0x48 #define PID_ACC_PEDAL_POS_D 0x49 #define PID_ACC_PEDAL_POS_E 0x4A #define PID_ACC_PEDAL_POS_F 0x4B #define PID_COMMANDED_THROTTLE_ACTUATOR 0x4C #define PID_TIME_WITH_MIL 0x4D #define PID_TIME_SINCE_CODES_CLEARED 0x4E #define PID_ETHANOL_FUEL 0x52 #define PID_FUEL_RAIL_PRESSURE 0x59 #define PID_HYBRID_BATTERY_PERCENTAGE 0x5B #define PID_ENGINE_OIL_TEMP 0x5C #define PID_FUEL_INJECTION_TIMING 0x5D #define PID_ENGINE_FUEL_RATE 0x5E #define PID_ENGINE_TORQUE_DEMANDED 0x61 #define PID_ENGINE_TORQUE_PERCENTAGE 0x62 #define PID_ENGINE_REF_TORQUE 0x63 // non-OBD/custom PIDs (no mode number) #define PID_ACC 0x20 #define PID_GYRO 0x21 #define PID_COMPASS 0x22 #define PID_MEMS_TEMP 0x23 #define PID_BATTERY_VOLTAGE 0x24 typedef enum { PROTO_AUTO = 0, PROTO_ISO_9141_2 = 3, PROTO_KWP2000_5KBPS = 4, PROTO_KWP2000_FAST = 5, PROTO_CAN_11B_500K = 6, PROTO_CAN_29B_500K = 7, PROTO_CAN_29B_250K = 8, PROTO_CAN_11B_250K = 9, } OBD_PROTOCOLS; // states typedef enum { OBD_DISCONNECTED = 0, OBD_CONNECTING = 1, OBD_CONNECTED = 2, OBD_FAILED = 3 } OBD_STATES; uint16_t hex2uint16(const char *p); uint8_t hex2uint8(const char *p); class COBD { public: // 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 uninit(); // set serial baud rate virtual bool setBaudRate(unsigned long baudrate); // get connection state virtual OBD_STATES getState() { return m_state; } // read specified OBD-II PID value virtual bool readPID(byte pid, int& result); // read multiple (up to 8) OBD-II PID values, return number of values obtained virtual byte readPID(const byte pid[], byte count, int result[]); // set device into low power mode virtual void enterLowPowerMode(); // wake up device from low power mode virtual void leaveLowPowerMode(); // send AT command and receive response (return bytes received) virtual byte sendCommand(const char* cmd, char* buf, byte bufsize, int timeout = OBD_TIMEOUT_LONG); // read diagnostic trouble codes (return number of DTCs read) virtual byte readDTC(uint16_t codes[], byte maxCodes = 1); // clear diagnostic trouble code virtual void clearDTC(); // get battery voltage (works without ECU) 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 (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); // 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 virtual bool isValidPID(byte pid); // get adapter firmware version virtual byte getVersion(); // set current PID mode byte dataMode = 1; // occurrence of errors byte errors = 0; // bit map of supported PIDs byte pidmap[4 * 8] = {0}; protected: virtual char* getResponse(byte& pid, char* buffer, byte bufsize); virtual int receive(char* buffer, int bufsize, unsigned int timeout = OBD_TIMEOUT_SHORT); virtual void write(const char* s); 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: void recover(); virtual void idleTasks() {} bool m_fusion = false; };