Giter Club home page Giter Club logo

elmduino's Introduction

ELMduino

GitHub version arduino-library-badge

This is a simple yet powerful library to effortlessly interface your Arduino with an ELM327 OBD-II scanner. With this library, you can query any and all OBD-II supported PIDs to collect a wide variety of car data (i.e. speed, rpm, engine temp, etc). Also, you can use ELMduino to view and clear your car's trouble codes - no need to go to AutoZone anymore!

Example Project:

youtube

Install:

Install ELMduino using the Arduino IDE's Libraries Manager (search "ELMduino.h")

Note:

If you're having difficulty in connecting/keeping connection to your ELM327, try using 38400 baud instead of 115200. If you still have trouble, try all other possible bauds. Lastly, if using BluetoothSerial on an ESP32, try using the ELM327's MAC address instead of the device name "OBDII" and remove paired devices using this sketch.

Concept of Execution

The library is non-blocking. This means when you query a PID e.g. myELM327.rpm(), the code does not wait around for the response, which would block your other code in the main loop from executing. With ELMDuino, your main loop can continue do other tasks. To make this work, you need to repeatedly call the PID query function and check the non-blocking receive state (myELM327.nb_rx_state) until it is equal to ELM_SUCCESS. If the status is not ELM_SUCCESS, the library could still be waiting for a response to be received. This is indicated by myELM327.nb_rx_state being equal to ELM_GETTING_MSG. If the status is not equal to either of these values (ELM_SUCCESS or ELM_GETTING_MSG), it indicates an error has occurred. You can call myELM327.printError() to check what the problem was. See the simple example below which queries the engine speed in RPM.

Just to be clear, do not try to query more than one PID at a time. You must wait for the current PID query to complete before starting the next one.

Example Code:

#include "ELMduino.h"




#define ELM_PORT Serial1




const bool DEBUG        = true;
const int  TIMEOUT      = 2000;
const bool HALT_ON_FAIL = false;




ELM327 myELM327;




typedef enum { ENG_RPM,
               SPEED } obd_pid_states;
obd_pid_states obd_state = ENG_RPM;

float rpm = 0;
float mph = 0;




void setup()
{
  Serial.begin(115200);
  ELM_PORT.begin(115200);

  Serial.println("Attempting to connect to ELM327...");

  if (!myELM327.begin(ELM_PORT, DEBUG, TIMEOUT))
  {
    Serial.println("Couldn't connect to OBD scanner");

    if (HALT_ON_FAIL)
      while (1);
  }

  Serial.println("Connected to ELM327");
}




void loop()
{
  switch (obd_state)
  {
    case ENG_RPM:
    {
      rpm = myELM327.rpm();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
        Serial.print("rpm: ");
        Serial.println(rpm);
        obd_state = SPEED;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = SPEED;
      }
      
      break;
    }
    
    case SPEED:
    {
      mph = myELM327.mph();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
        Serial.print("mph: ");
        Serial.println(mph);
        obd_state = ENG_RPM;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = ENG_RPM;
      }
      
      break;
    }
  }
}

List of Supported OBD PID Processing Functions:

bool begin(Stream& stream, const bool& debug = false, const uint16_t& timeout = 1000, const char& protocol = '0', const uint16_t& payloadLen = 40, const byte& dataTimeout = 0);
bool initializeELM(const char& protocol = '0', const byte& dataTimeout = 0);
void flushInputBuff();
uint64_t findResponse();
bool queryPID(const uint8_t& service, const uint16_t& pid, const uint8_t& num_responses = 1);
bool queryPID(char queryStr[]);
float processPID(const uint8_t& service, const uint16_t& pid, const uint8_t& num_responses, const uint8_t& numExpectedBytes, const float& scaleFactor = 1, const float& bias = 0);
void sendCommand(const char *cmd);
int8_t sendCommand_Blocking(const char *cmd);
int8_t get_response();
bool timeout();
float conditionResponse(const uint8_t& numExpectedBytes, const float& scaleFactor = 1, const float& bias = 0);

float batteryVoltage(void);
int8_t get_vin_blocking(char vin[]);
bool resetDTC();
void currentDTCCodes(const bool& isBlocking = true);

uint32_t supportedPIDs_1_20();

uint32_t monitorStatus();
uint16_t freezeDTC();
uint16_t fuelSystemStatus();
float engineLoad();
float engineCoolantTemp();
float shortTermFuelTrimBank_1();
float longTermFuelTrimBank_1();
float shortTermFuelTrimBank_2();
float longTermFuelTrimBank_2();
float fuelPressure();
uint8_t manifoldPressure();
float rpm();
int32_t kph();
float mph();
float timingAdvance();
float intakeAirTemp();
float mafRate();
float throttle();
uint8_t commandedSecAirStatus();
uint8_t oxygenSensorsPresent_2banks();
uint8_t obdStandards();
uint8_t oxygenSensorsPresent_4banks();
bool auxInputStatus();
uint16_t runTime();


uint32_t supportedPIDs_21_40();

uint16_t distTravelWithMIL();
float fuelRailPressure();
float fuelRailGuagePressure();
float commandedEGR();
float egrError();
float commandedEvapPurge();
float fuelLevel();
uint8_t warmUpsSinceCodesCleared();
uint16_t distSinceCodesCleared();
float evapSysVapPressure();
uint8_t absBaroPressure();
float catTempB1S1();
float catTempB2S1();
float catTempB1S2();
float catTempB2S2();

uint32_t supportedPIDs_41_60();

uint32_t monitorDriveCycleStatus();
float ctrlModVoltage();
float absLoad();
float commandedAirFuelRatio();
float relativeThrottle();
float ambientAirTemp();
float absThrottlePosB();
float absThrottlePosC();
float absThrottlePosD();
float absThrottlePosE();
float absThrottlePosF();
float commandedThrottleActuator();
uint16_t timeRunWithMIL();
uint16_t timeSinceCodesCleared();
float maxMafRate();
uint8_t fuelType();
float ethanolPercent();
float absEvapSysVapPressure();
float evapSysVapPressure2();
float absFuelRailPressure();
float relativePedalPos();
float hybridBatLife();
float oilTemp();
float fuelInjectTiming();
float fuelRate();
uint8_t emissionRqmts();


uint32_t supportedPIDs_61_80();

float demandedTorque();
float torque();
uint16_t referenceTorque();
uint16_t auxSupported();
void printError();

List of OBD Protocols:

const char AUTOMATIC                  = '0';
const char SAE_J1850_PWM_41_KBAUD     = '1';
const char SAE_J1850_PWM_10_KBAUD     = '2';
const char ISO_9141_5_BAUD_INIT       = '3';
const char ISO_14230_5_BAUD_INIT      = '4';
const char ISO_14230_FAST_INIT        = '5';
const char ISO_15765_11_BIT_500_KBAUD = '6';
const char ISO_15765_29_BIT_500_KBAUD = '7';
const char ISO_15765_11_BIT_250_KBAUD = '8';
const char ISO_15765_29_BIT_250_KBAUD = '9';
const char SAE_J1939_29_BIT_250_KBAUD = 'A';
const char USER_1_CAN                 = 'B';
const char USER_2_CAN                 = 'C';

List of standard PIDs:

const uint8_t SUPPORTED_PIDS_1_20              = 0;   // 0x00 - bit encoded
const uint8_t MONITOR_STATUS_SINCE_DTC_CLEARED = 1;   // 0x01 - bit encoded
const uint8_t FREEZE_DTC                       = 2;   // 0x02 -
const uint8_t FUEL_SYSTEM_STATUS               = 3;   // 0x03 - bit encoded
const uint8_t ENGINE_LOAD                      = 4;   // 0x04 - %
const uint8_t ENGINE_COOLANT_TEMP              = 5;   // 0x05 - °C
const uint8_t SHORT_TERM_FUEL_TRIM_BANK_1      = 6;   // 0x06 - %
const uint8_t LONG_TERM_FUEL_TRIM_BANK_1       = 7;   // 0x07 - %
const uint8_t SHORT_TERM_FUEL_TRIM_BANK_2      = 8;   // 0x08 - %
const uint8_t LONG_TERM_FUEL_TRIM_BANK_2       = 9;   // 0x09 - %
const uint8_t FUEL_PRESSURE                    = 10;  // 0x0A - kPa
const uint8_t INTAKE_MANIFOLD_ABS_PRESSURE     = 11;  // 0x0B - kPa
const uint8_t ENGINE_RPM                       = 12;  // 0x0C - rpm
const uint8_t VEHICLE_SPEED                    = 13;  // 0x0D - km/h
const uint8_t TIMING_ADVANCE                   = 14;  // 0x0E - ° before TDC
const uint8_t INTAKE_AIR_TEMP                  = 15;  // 0x0F - °C
const uint8_t MAF_FLOW_RATE                    = 16;  // 0x10 - g/s
const uint8_t THROTTLE_POSITION                = 17;  // 0x11 - %
const uint8_t COMMANDED_SECONDARY_AIR_STATUS   = 18;  // 0x12 - bit encoded
const uint8_t OXYGEN_SENSORS_PRESENT_2_BANKS   = 19;  // 0x13 - bit encoded
const uint8_t OXYGEN_SENSOR_1_A                = 20;  // 0x14 - V %
const uint8_t OXYGEN_SENSOR_2_A                = 21;  // 0x15 - V %
const uint8_t OXYGEN_SENSOR_3_A                = 22;  // 0x16 - V %
const uint8_t OXYGEN_SENSOR_4_A                = 23;  // 0x17 - V %
const uint8_t OXYGEN_SENSOR_5_A                = 24;  // 0x18 - V %
const uint8_t OXYGEN_SENSOR_6_A                = 25;  // 0x19 - V %
const uint8_t OXYGEN_SENSOR_7_A                = 26;  // 0x1A - V %
const uint8_t OXYGEN_SENSOR_8_A                = 27;  // 0x1B - V %
const uint8_t OBD_STANDARDS                    = 28;  // 0x1C - bit encoded
const uint8_t OXYGEN_SENSORS_PRESENT_4_BANKS   = 29;  // 0x1D - bit encoded
const uint8_t AUX_INPUT_STATUS                 = 30;  // 0x1E - bit encoded
const uint8_t RUN_TIME_SINCE_ENGINE_START      = 31;  // 0x1F - sec

const uint8_t SUPPORTED_PIDS_21_40             = 32;  // 0x20 - bit encoded
const uint8_t DISTANCE_TRAVELED_WITH_MIL_ON    = 33;  // 0x21 - km
const uint8_t FUEL_RAIL_PRESSURE               = 34;  // 0x22 - kPa
const uint8_t FUEL_RAIL_GUAGE_PRESSURE         = 35;  // 0x23 - kPa
const uint8_t OXYGEN_SENSOR_1_B                = 36;  // 0x24 - ratio V
const uint8_t OXYGEN_SENSOR_2_B                = 37;  // 0x25 - ratio V
const uint8_t OXYGEN_SENSOR_3_B                = 38;  // 0x26 - ratio V
const uint8_t OXYGEN_SENSOR_4_B                = 39;  // 0x27 - ratio V
const uint8_t OXYGEN_SENSOR_5_B                = 40;  // 0x28 - ratio V
const uint8_t OXYGEN_SENSOR_6_B                = 41;  // 0x29 - ratio V
const uint8_t OXYGEN_SENSOR_7_B                = 42;  // 0x2A - ratio V
const uint8_t OXYGEN_SENSOR_8_B                = 43;  // 0x2B - ratio V
const uint8_t COMMANDED_EGR                    = 44;  // 0x2C - %
const uint8_t EGR_ERROR                        = 45;  // 0x2D - %
const uint8_t COMMANDED_EVAPORATIVE_PURGE      = 46;  // 0x2E - %
const uint8_t FUEL_TANK_LEVEL_INPUT            = 47;  // 0x2F - %
const uint8_t WARM_UPS_SINCE_CODES_CLEARED     = 48;  // 0x30 - count
const uint8_t DIST_TRAV_SINCE_CODES_CLEARED    = 49;  // 0x31 - km
const uint8_t EVAP_SYSTEM_VAPOR_PRESSURE       = 50;  // 0x32 - Pa
const uint8_t ABS_BAROMETRIC_PRESSURE          = 51;  // 0x33 - kPa
const uint8_t OXYGEN_SENSOR_1_C                = 52;  // 0x34 - ratio mA
const uint8_t OXYGEN_SENSOR_2_C                = 53;  // 0x35 - ratio mA
const uint8_t OXYGEN_SENSOR_3_C                = 54;  // 0x36 - ratio mA
const uint8_t OXYGEN_SENSOR_4_C                = 55;  // 0x37 - ratio mA
const uint8_t OXYGEN_SENSOR_5_C                = 56;  // 0x38 - ratio mA
const uint8_t OXYGEN_SENSOR_6_C                = 57;  // 0x39 - ratio mA
const uint8_t OXYGEN_SENSOR_7_C                = 58;  // 0x3A - ratio mA
const uint8_t OXYGEN_SENSOR_8_C                = 59;  // 0x3B - ratio mA
const uint8_t CATALYST_TEMP_BANK_1_SENSOR_1    = 60;  // 0x3C - °C
const uint8_t CATALYST_TEMP_BANK_2_SENSOR_1    = 61;  // 0x3D - °C
const uint8_t CATALYST_TEMP_BANK_1_SENSOR_2    = 62;  // 0x3E - °C
const uint8_t CATALYST_TEMP_BANK_2_SENSOR_2    = 63;  // 0x3F - °C

const uint8_t SUPPORTED_PIDS_41_60             = 64;  // 0x40 - bit encoded
const uint8_t MONITOR_STATUS_THIS_DRIVE_CYCLE  = 65;  // 0x41 - bit encoded
const uint8_t CONTROL_MODULE_VOLTAGE           = 66;  // 0x42 - V
const uint8_t ABS_LOAD_VALUE                   = 67;  // 0x43 - %
const uint8_t FUEL_AIR_COMMANDED_EQUIV_RATIO   = 68;  // 0x44 - ratio
const uint8_t RELATIVE_THROTTLE_POSITION       = 69;  // 0x45 - %
const uint8_t AMBIENT_AIR_TEMP                 = 70;  // 0x46 - °C
const uint8_t ABS_THROTTLE_POSITION_B          = 71;  // 0x47 - %
const uint8_t ABS_THROTTLE_POSITION_C          = 72;  // 0x48 - %
const uint8_t ACCELERATOR_PEDAL_POSITION_D     = 73;  // 0x49 - %
const uint8_t ACCELERATOR_PEDAL_POSITION_E     = 74;  // 0x4A - %
const uint8_t ACCELERATOR_PEDAL_POSITION_F     = 75;  // 0x4B - %
const uint8_t COMMANDED_THROTTLE_ACTUATOR      = 76;  // 0x4C - %
const uint8_t TIME_RUN_WITH_MIL_ON             = 77;  // 0x4D - min
const uint8_t TIME_SINCE_CODES_CLEARED         = 78;  // 0x4E - min
const uint8_t MAX_VALUES_EQUIV_V_I_PRESSURE    = 79;  // 0x4F - ratio V mA kPa
const uint8_t MAX_MAF_RATE                     = 80;  // 0x50 - g/s
const uint8_t FUEL_TYPE                        = 81;  // 0x51 - ref table
const uint8_t ETHANOL_FUEL_PERCENT             = 82;  // 0x52 - %
const uint8_t ABS_EVAP_SYS_VAPOR_PRESSURE      = 83;  // 0x53 - kPa
const uint8_t EVAP_SYS_VAPOR_PRESSURE          = 84;  // 0x54 - Pa
const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_1_3 = 85;  // 0x55 - %
const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_1_3  = 86;  // 0x56 - %
const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_2_4 = 87;  // 0x57 - %
const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_2_4  = 88;  // 0x58 - %
const uint8_t FUEL_RAIL_ABS_PRESSURE           = 89;  // 0x59 - kPa
const uint8_t RELATIVE_ACCELERATOR_PEDAL_POS   = 90;  // 0x5A - %
const uint8_t HYBRID_BATTERY_REMAINING_LIFE    = 91;  // 0x5B - %
const uint8_t ENGINE_OIL_TEMP                  = 92;  // 0x5C - °C
const uint8_t FUEL_INJECTION_TIMING            = 93;  // 0x5D - °
const uint8_t ENGINE_FUEL_RATE                 = 94;  // 0x5E - L/h
const uint8_t EMISSION_REQUIREMENTS            = 95;  // 0x5F - bit encoded

const uint8_t SUPPORTED_PIDS_61_80             = 96;  // 0x60 - bit encoded
const uint8_t DEMANDED_ENGINE_PERCENT_TORQUE   = 97;  // 0x61 - %
const uint8_t ACTUAL_ENGINE_TORQUE             = 98;  // 0x62 - %
const uint8_t ENGINE_REFERENCE_TORQUE          = 99;  // 0x63 - Nm
const uint8_t ENGINE_PERCENT_TORQUE_DATA       = 100; // 0x64 - %
const uint8_t AUX_INPUT_OUTPUT_SUPPORTED       = 101; // 0x65 - bit encoded

List of AT Commands:

(https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf)

const char * const DISP_DEVICE_DESCRIPT       = "AT @1";     // General
const char * const DISP_DEVICE_ID             = "AT @2";     // General
const char * const STORE_DEVICE_ID            = "AT @3 %s";  // General
const char * const REPEAT_LAST_COMMAND        = "AT \r";     // General
const char * const ALLOW_LONG_MESSAGES        = "AT AL";     // General
const char * const AUTOMATIC_RECEIVE          = "AT AR";     // OBD
const char * const ADAPTIVE_TIMING_OFF        = "AT AT0";    // OBD
const char * const ADAPTIVE_TIMING_AUTO_1     = "AT AT1";    // OBD
const char * const ADAPTIVE_TIMING_AUTO_2     = "AT AT2";    // OBD
const char * const DUMP_BUFFER                = "AT BD";     // OBD
const char * const BYPASS_INIT_SEQUENCE       = "AT BI";     // OBD
const char * const TRY_BAUD_DIVISOR           = "AT BRD %s"; // General
const char * const SET_HANDSHAKE_TIMEOUT      = "AT BRT %s"; // General
const char * const CAN_AUTO_FORMAT_OFF        = "AT CAF0";   // CAN
const char * const CAN_AUTO_FORMAT_ON         = "AT CAF1";   // CAN
const char * const CAN_EXTENDED_ADDRESS_OFF   = "AT CEA";    // CAN
const char * const USE_CAN_EXTENDED_ADDRESS   = "AT CEA %s"; // CAN
const char * const SET_ID_FILTER              = "AT CF %s";  // CAN
const char * const CAN_FLOW_CONTROL_OFF       = "AT CFC0";   // CAN
const char * const CAN_FLOW_CONTROL_ON        = "AT CFC1";   // CAN
const char * const SET_ID_MASK                = "AT CM %s";  // CAN
const char * const SET_CAN_PRIORITY           = "AT CP %s";  // CAN
const char * const SHOW_CAN_STATUS            = "AT CS";     // CAN
const char * const CAN_SILENT_MODE_OFF        = "AT CSM0";   // CAN
const char * const CAN_SILENT_MODE_ON         = "AT CSM1";   // CAN
const char * const CALIBRATE_VOLTAGE_CUSTOM   = "AT CV %s";  // Volts
const char * const RESTORE_CV_TO_FACTORY      = "AT CV 0000"; // Volts
const char * const SET_ALL_TO_DEFAULTS        = "AT D";      // General
const char * const DISP_DLC_OFF               = "AT D0";     // CAN
const char * const DISP_DLC_ON                = "AT D1";     // CAN
const char * const MONITOR_FOR_DM1_MESSAGES   = "AT DM1";    // J1939
const char * const DISP_CURRENT_PROTOCOL      = "AT DP";     // OBD
const char * const DISP_CURRENT_PROTOCOL_NUM  = "AT DPN";    // OBD
const char * const ECHO_OFF                   = "AT E0";     // General
const char * const ECHO_ON                    = "AT E1";     // General
const char * const FLOW_CONTROL_SET_DATA_TO   = "AT FC SD %s"; // CAN
const char * const FLOW_CONTROL_SET_HEAD_TO   = "AT FC SH %s"; // CAN
const char * const FLOW_CONTROL_SET_MODE_TO   = "AT FC SM %s"; // CAN
const char * const FORGE_EVENTS               = "AT FE";     // General
const char * const PERFORM_FAST_INIT          = "AT FI";     // ISO
const char * const HEADERS_OFF                = "AT H0";     // OBD
const char * const HEADERS_ON                 = "AT H1";     // OBD
const char * const DISP_ID                    = "AT I";      // General
const char * const SET_ISO_BAUD_10400         = "AT IB 10";  // ISO
const char * const SET_ISO_BAUD_4800          = "AT IB 48";  // ISO
const char * const SET_ISO_BAUD_9600          = "AT IB 96";  // ISO
const char * const IFR_VAL_FROM_HEADER        = "AT IFR H";  // J1850
const char * const IFR_VAL_FROM_SOURCE        = "AT IFR S";  // J1850
const char * const IFRS_OFF                   = "AT IFR0";   // J1850
const char * const IFRS_AUTO                  = "AT IFR1";   // J1850
const char * const IFRS_ON                    = "AT IFR2";   // J1850
const char * const IREAD_IGNMON_INPUT_LEVEL   = "AT IGN";    // Other
const char * const SET_ISO_SLOW_INIT_ADDRESS  = "AT IIA %s"; // ISO
const char * const USE_J1939_ELM_DATA_FORMAT  = "AT JE";     // J1850
const char * const J1939_HEAD_FORMAT_OFF      = "AT JHF0";   // J1850
const char * const J1939_HEAD_FORMAT_ON       = "AT JHF1";   // J1850
const char * const USE_J1939_SAE_DATA_FORMAT  = "AT JS";     // J1850
const char * const SET_J1939_TIMER_X_TO_1X    = "AT JTM1";   // J1850
const char * const SET_J1939_TIMER_X_TO_5X    = "AT JTM5";   // J1850
const char * const DISP_KEY_WORDS             = "AT KW";     // ISO
const char * const KEY_WORD_CHECKING_OFF      = "AT KW0";    // ISO
const char * const KEY_WORD_CHECKING_ON       = "AT KW1";    // ISO
const char * const LINEFEEDS_OFF              = "AT L0";     // General
const char * const LINEFEEDS_ON               = "AT L1";     // General
const char * const LOW_POWER_MODE             = "AT LP";     // General
const char * const MEMORY_OFF                 = "AT M0";     // General
const char * const MEMORY_ON                  = "AT M1";     // General
const char * const MONITOR_ALL                = "AT MA";     // OBD
const char * const MONITOR_FOR_PGN            = "AT MP %s";  // J1939
const char * const MONITOR_FOR_RECEIVER       = "AT MR %s";  // OBD
const char * const MONITOR_FOR_TRANSMITTER    = "AT MT %s";  // OBD
const char * const NORMAL_LENGTH_MESSAGES     = "AT NL";     // OBD
const char * const SET_PROTO_OPTIONS_AND_BAUD = "AT PB %s";  // OBD
const char * const PROTOCOL_CLOSE             = "AT PC";     // OBD
const char * const ALL_PROG_PARAMS_OFF        = "AT PP FF OFF";   // PPs
const char * const ALL_PROG_PARAMS_ON         = "AT PP FF ON";    // PPs
const char * const SET_PROG_PARAM_OFF         = "AT PP %s OFF";   // PPs
const char * const SET_PROG_PARAM_ON          = "AT PP %s ON";    // PPs
const char * const SET_PROG_PARAM_VAL         = "AT PP %s SV %s"; // PPs
const char * const DISP_PP_SUMMARY            = "AT PPS";    // PPs
const char * const RESPONSES_OFF              = "AT R0";     // OBD
const char * const RESPONSES_ON               = "AT R1";     // OBD
const char * const SET_RECEIVE_ADDRESS_TO     = "AT RA %s";  // OBD
const char * const READ_STORED_DATA           = "AT RD";     // General
const char * const SEND_RTR_MESSAGE           = "AT RTR";    // CAN
const char * const READ_VOLTAGE               = "AT RV";     // Volts
const char * const PRINTING_SPACES_OFF        = "AT S0";     // OBD
const char * const PRINTING_SPACES_ON         = "AT S1";     // OBD
const char * const STORE_DATA_BYTE            = "AT SD ";    // General
const char * const SET_HEADER                 = "AT SH %s";  // OBD
const char * const PERFORM_SLOW_INIT          = "AT SI";     // ISO
const char * const SET_PROTOCOL_TO_AUTO_H_SAVE = "AT SP A%c"; // OBD
const char * const SET_PROTOCOL_TO_H_SAVE     = "AT SP %c";  // OBD
const char * const SET_PROTOCOL_TO_AUTO_SAVE  = "AT SP 00";  // OBD
const char * const SET_REC_ADDRESS            = "AT SR %s";  // OBD
const char * const SET_STANDARD_SEARCH_ORDER  = "AT SS";     // OBD
const char * const SET_TIMEOUT_TO_H_X_4MS     = "AT ST %s";  // OBD
const char * const SET_WAKEUP_TO_H_X_20MS     = "AT SW %s";  // ISO
const char * const SET_TESTER_ADDRESS_TO      = "AT TA %s";  // OBD
const char * const TRY_PROT_H_AUTO_SEARCH     = "AT TP A%s"; // OBD
const char * const TRY_PROT_H                 = "AT TP %s";  // OBD
const char * const VARIABLE_DLC_OFF           = "AT V0";     // CAN
const char * const VARIABLE_DLC_ON            = "AT V1";     // CAN
const char * const SET_WAKEUP_MESSAGE         = "AT WM";     // ISO
const char * const WARM_START                 = "AT WS";     // General
const char * const RESET_ALL                  = "AT Z";      // General

elmduino's People

Contributors

av4625 avatar drmpf avatar idavidka avatar isikugurlu avatar jakubdziworski avatar jimwhitelaw avatar junofield avatar patfelst avatar powerbroker2 avatar tiny-spider avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elmduino's Issues

can it run on ESP32?

Hi,
was really happy to find this one, intending to do a "My own CO2 footprint" project.
Could you please help me in providing an Arduino example running on an ESP32 - which has Bluetooth build in. When I compile the sample sketch, it simply gives "serial3 unknown" error. Sorry for being only a hobby programmer....

Make Lib use a WiFi Telnet

Hi,

it is me again... I finally got one thing working: Use a ESP32 to connect it to a WiFi OBD adapter:

#include <WiFi.h>

#include <HTTPClient.h>

#include <elapsedMillis.h>

elapsedMillis printTime = 1000;

//#define ELM_PORT client
#define DEBUG_PORT Serial

WiFiClient telnet;
const int telnetPort = 35000;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  
  WiFi.begin("WiFi_OBDII", NULL);
  while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
    
  
  if (!telnet.connect("192.168.0.10", telnetPort)) {
     Serial.println("connection failed");
     return;
  } else {
    telnet.print("AT Z");
    telnet.print('\r');
  }  
}

void loop() {
  // put your main code here, to run repeatedly:
  //EMPFANGEN
  while (telnet.available() > 0) {
     char c = telnet.read();

     if(c == '>') {
        Serial.println();        
     } else {
      Serial.write(c);
     }
  }
  //SENDEN
  if (printTime > 1000) {
  if (telnet.connect("192.168.0.10", telnetPort)) {
    telnet.print("AT RV");
    telnet.print('\r'); 
    printTime = 0;
  } else {
    Serial.println("connection failed");
  }}  
}

[This is my fast and dirty 'does it work' code]

Basically those adapters provide an open WiFi network ("WiFi_OBDII") with a telnet server at port 35000.

This telnet server passes through the serial interface. If you send a AT Z, you will get your response.

May it be possible to use this connection for your (by the way great) library?

Best regards

Pascal

ESP32 Connection

I used the following to connect to my ELM327, to this Point ist al working good but the readout is ERROR: 7 and it wont be displaying my rpm.
I also check my ELM327 with torque app and it all Works fine.

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


uint32_t rpm = 0;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("Carly Adapter"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }

  Serial.println("Connected to ELM327");
}


void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
  {
    Serial.print(F("\tERROR: "));
    Serial.println(myELM327.status);
    delay(100);
  }
}

DISP_ID is incorrect

const char * const DISP_ID = "AT HI"; // General

ELM327 datasheet page 17

I
[ Identify yourself ]
Issuing this command causes the chip to identify
itself, by printing the startup product ID string (currently
‘ELM327 v2.0’). Software can use this to determine
exactly which integrated circuit it is talking to, without
having to reset the IC.

Some basic setup questions

Hey! I really appreciate the support. I'm new to the arduino universe, but I'm a big car enthusiast and very interested in making some basic displays for a track car I'm building. I bought one of the inexpensive bluetooth ELM327 modules and desoldered the bluetooth component so I could pass the serial TX/RX data to the arduino through pins 2 and 3 like in one of the examples.

I have a (probably very basic, simple) question about the baud rate settings. How did you determine to use 115200 for both the serial and ELMserial ports? I found a few resources that said ELM327's have a baud rate of 38400, but if I used those values, it obviously didn't work. I was just curious about those settings.

The other issue I had was when I did get the serial port to work (after it printed the "connected to elm327"), I would get around 10 values printed for the RPM (all which read 0), then it would go into the timeout error and just print that endlessly.

I was wondering if you could help point me in the right direction. I don't have any experience with data communication, so it's proving to be a bit of a steep learning curve, so any advice/guidance is very much appreciated.

How to send an AT command and get response via WiFi?

I have a successful connection to my OBD dongle, but could not get a response on my 'AT Z' command using a terminal program. I use ESP8266_WiFi.ino.

Connected to Wifi
IP address:
192.168.0.1
connected

Thank you for any help.

home-testing Elmduino (OBD emulator?)

Hi,
Thank you for ELMduino. I'm already using it in my car with custom PIDs (discussion already closed as testing went fine). Since I don't drive the car much lately and the condition I'm waiting for has not occurred since I did my setup I cannot really prove it works. I mean - 4 out of 5 values I'm reading are ok, changing etc. But the one I'm most interested in (DPF burn status 0/1) happens once 300-700km driven.
I did already small instructable & shared with community. The only one person testing this solution said It didn't show the status properly (DPF burn was 0, while Torque showed 1 at the same time)

My question is - is there any quick ESP32/Arduino Bluetooth emulator that we program to feed other ESP32 running Elmduino to test ? I'm specially intersted in this one custom PID

Some information about my wifi dongle problems

Hi maintainers. This is just a short information about my previous wifi obd dongle problems. Hope this help someone out, for further debugging and tests. The root cause is not ELMduino, this library work as expected.

I've submitted a pull request for the connected state problem a while ago. And what i can say, WIFI_MODE doesn't fix anything :) Sorry for the wrong input last time.

Here is my summary of what is going wrong on the side of Wifi. I've debugged days with a lot of different adapters.

ESP32 and ESP8266 both have unreliable wifi network

This is the base problem. All ESP32 and ESP8266 modules i've tested (5 different) have the same issues. Sending a raw AT Command works fine. Like for example AT @1. Receiving the answer as difficult.

  1. Most of the time, you get back what you have sent. For example AT @1 including some weird characters at the end, mostly ?.
  2. Once in a while, you get the correct answer, in the case of the example AT command, this is something like OBDII RS232 to xxx Interpreter. You can improve this behaviour when setting setNoDelay(true) on the WifiClient -> https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-class.html#setnodelay
  3. I wrote a testscript that just send this one command in a interval of 1 second. 76 of 100 received trash data. Only 24 received correct data.
  4. It doesnt matter how long you wait for data to be received, after the trash data is received, which curiously correctly is terminated with an >, there is no more data the comes down the line. Only after sending another AT command, you get back data.

ESP32 BluetoothSerial

Same code as above for Wifi (Except the wifi client changes with BT Serial), work without problems and 100 of 100 requests receive correct data.

Testscenario - All show similar results

  • 3 different ESP32 and 2 different ESP8266 modules
  • 7 different OBD2 Wifi dongles, from cheap to more expensive
  • I have also tested all wifi adapters with a smartphone app that can send serial messages. Here it work without any problems. So all tested wifi adapters are generally fine and work as expected.

Conclusion

Don't use OBD2 WIFI adapters on ESP32 or ESP8266. You will have troubles.

I wanted to write down my testing hell of the last days, to help others with my experience.

Have nice holidays. Cya.

Timeout Issue

Hello. I'm sorry to open another issue on this topic, I've been trying to figure this out for a few days now and can't. Probably my inexperience. Anyway my hardware is:

  • Arduino Mega
  • HC05
  • Bafx ELM327

I'm able to connect and retrieve data using AT commands, but I get timeout errors after connecting using the example code. Any ideas?

how to read OBDII voltage in sketch on Arduino IDE

I been scratch my head regarding how to put a "read voltage"(ATRV) command in sketch in order to display the result in serial monitor.

I already try ATRV command on ESP32_test.ino sample & it work, it show ">atrvatrv12.1V" on serial monitor. But when I issue "ATRV" command in sketch on ESP32_Bluetooth_Serial.ino sample, it show 0.
the command in sketch as below

Serial.print("Batt: "); 
myELM327.sendCommand("ATRV");
Serial.println(myELM327.findResponse());
Serial.println("V");

it will show below result:
Batt: 0
V
in serial monitor.

By the way, I still at beginner stage for my Arduino command. FYI, I'm using OBDLink LX as my OBDII bluetooth dongle & ESP32.

more on custom PIDs - splitting response

This is continuation of issue 4
some custom PIDs return values and suggested calculation for result is divided in two parts A and B (all examples for Torque app)
see example of calculations suggested -> here
if A256+B makes all sense as it's simply conversion of longer response to decimal (I guess)
such a calculation :
(A
33.55/255+B*0.13/255)-12
is impossible to get with current findResponse()

Would it be possible to return A and B separately so calculation could be done on them ?

currently the most complex query & response for me is
Distance Since Last DPF Regeneration Dist. DPF 223039 A*256+B 0 65535 km 7E0
myELM327.queryPID(34, 12345) //0x22 and 0x3039 => 34 and 12345

ERROR 7 On ESP32 Wrover Board

Arduino IDE Version: 1.8.5
ELMduino Library Version: 2.0.11 (Latest at the time of opening this issue)
ESP32 Build Tools Version: 1.0.4 (Latest at the time of opening this issue)
ESP32 Board Used: Wroom 32 ESP32 Dev Board
ELM327 Module: Generic Bluetooth ELM327

Issue description
Getting ERROR 7 on the serial console while running the ESP32_Bluetooth_Serial.io example, Used the file ESP32_Bluetooth_Serial.ino that came with the library, only changes were updating the Bluetooth name of the ELM327 module & commenting the following lines since LED_BUILTIN is not defined for this particular ESP32 board:

pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);

No issues with compilation or connection with the ELM327 module, ESP32 is connecting fine with the module quickly its a generic known working device, Torque works fine.

Tried sending AT commands using the minimal example & it worked fine, module responds back with values for AT commands.

Attaching the screenshot of the serial monitor:
aa

Help with Reading speed (KPH) instead of RPM

Hi,
I am a beginner here.

I am interested in using the ESP32_Bluetooth_Serial code. However I want to read speed (KPH) instead of rpm, so can you please help me change the necessary parameters to read the car speed?
(I am getting confused whether to use the term "speed" or "kph")

ESP8266

I want to read PIDs over my ESP8266 WiFi Modul.
How can i implement your ELM Duino to read Pids over the wifi connection ?
When i enter 010C in my serial monitor iam get the right answer from the ELM327 so the connection should be fine ?
But now i dont no know how i can use ur ELMDuino sketch to simplify things and get the data to be print in to my serial monitor ?

`#include <ESP8266WiFi.h>

const char* ssid = "WiFi_OBDII";
const char* password = "your-password";

//IP Adress of your ELM327 Dongle
IPAddress server(192, 168, 0, 10);

boolean last_in = false;

WiFiClient client;

void setup() {
Serial.begin(115200);
delay(10);

// Connecting to ELM327 WiFi
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid);
// WiFi.begin(ssid, password); //Use this line if your ELM327 has a password protected WiFi

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("Connected to Wifi");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

if (client.connect(server, 35000)) {
Serial.println("connected");
Serial.println("<ATZ");
// Make a Request
client.println("ATZ");
}
else {
Serial.println("connection failed");
ESP.reset();
}
}

void loop() {
if (!client.connected()) {
Serial.println("CLIENT DISCONNECTED - RESET!");
client.stop();
ESP.reset();
}
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
if (!last_in) {
Serial.println("");
Serial.print(">");
last_in = true;
}
char c = client.read();
/Serial.print(" 0x");
Serial.print(c, HEX);
/
Serial.print(c);
}

// as long as there are bytes in the serial queue,
// read them and send them out the socket if it's open:
while (Serial.available() > 0) {
if (last_in) {
Serial.println("");
Serial.print("<< ");
last_in = false;
}
char inChar = Serial.read();
if (client.connected()) {
client.print(inChar);
}
}
}`

Possible integer overflow?

Hi!

I am currently having rare weird issues in my program. For me, some numbers in other variables in a struct changes with no obvious reasons. I am reading kph and store that return value into a struct property.

As i am no c++ expert, i want to kindly ask the question, if this can overflow in some cases.

It is fact that kph sometimes gives extraordinary high numbers when something weird is happening on the OBD device.

So, lets face the code: - I use this function

int32_t ELM327::kph()

I noticed that it casts to int32_t. This function internally calls findResponse which returns a uint64_t.

uint64_t ELM327::findResponse()

So it ends up in a uint64_t to int32_t cast - Is it technically possible that this does overflow and effect other memory in code?

Connection problem

Hey.
I have a problem logging in ESP32 to ELM327. After uploading the code, it worked for several days, then ESP32 stopped connecting with LM. I noticed that you need to log in to another ELM237 device using the pairing code "1234" and the connection is made but only until the first restart. Then repeat the whole procedure - enter the pairing code "1234" on another device. Something is working incorrectly I have two ESP32 and ELM237 and in all cases it is so bad for this I exclude a hardware problem.
I check the operation on the unmodified test code and the adapter name is OBDII.
How it looks can be seen in the video: https://youtu.be/d-oBFSECpDg

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


uint32_t rpm = 0;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("OBDII"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }
  
  Serial.println("Connected to ELM327");
}


void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
  {
    Serial.print(F("\tERROR: "));
    Serial.println(myELM327.status);
    delay(100);
  }
}

getResponse and calculate resonseByte A and B

Hello powerbroker2
I'm really sorry for bothering you for keep asking questions...
I do appreciate that

Actually It is really easy to use 'findResponse' to get the values
To get more values from PID I should find out some splited values like
Distance traveled since codes cleared (256*A+B)

I have already checked the close issues about the splited values you wrote... but as mentioned, I'm not a programmer

I added to this my cpp file first.

uint16_t ELM327::runtime()
{
	if (queryPID(SERVICE_01, RUN_TIME_SINCE_ENGINE_START))

		return (uint16_t)findResponse();

	return ELM_GENERAL_ERROR;
}
//then can you tell me how to use responseByte_1 and responseByte_0 using 'findResponse' to calculate the 'runtime' value?

this is my sketch below
uint16_t runtime = 0;

uint16_t tempRUN_TIME_SINCE_ENGINE_START = myELM327.runtime();

    byte B = myELM327.responseByte_0;
    byte A = myELM327.responseByte_1; // I don't have any idea how to use this...

  runtime = (uint16_t)tempRUN_TIME_SINCE_ENGINE_START;
        Serial.print("Engine Runtime : "); Serial.print(runtime); Serial.println("seconds"); // 256*A+B is the correct runtime value

I'm really sorry for my ignorance.. plz give me a little help plz... as I metioned I'm not a programmer... sorry again.

Supported PIDs decoder

In Issue #33 somebody was wanting to use a PID which happened to be unsupported by their vehicle. To get a list of PIDs supported by your vehicle, run this code. I have this function in the main loop().

/*
-----------------
  Detect if user has pressed 'd' key on serial monitor keyboard, if yes
  End the bluetooth connection and halt the processor
  If 'P' is pressed, outputs the PIDs that the vehicle supports.
-----------------
*/
void quit_prog_if_keypressed() {
  if (Serial.available()) {
    char c = Serial.read();
    if (c == 'd') {
      Serial.println("Disconnecting bluetooth connection");
      SerialBT.disconnect();
      //Serial.println("Closing bluetooth connection");
      //SerialBT.end();
      Serial.println("Halting program ... ");

      #ifdef lcd_20x4_line_char
      lcd.clear();
      lcd.setCursor(0,0);
      //         01234567890123456789
      lcd.print("Disconnect Bluetooth");
      lcd.setCursor(0,1);
      //         01234567890123456789
      lcd.print("Halting program ...");
      #endif

      while(1);
    }
    else if (c == 'P') {
      char cmd[100] = {0};
      // Print supported PIDS
      Serial.println("\n\nPrint supported PIDs *** Turn engine ON ***");
      Serial.println("Turning ECU filter off ATCRA");
      boost.send_command("ATCRA");
      Serial.println("Turning headers ON ATH1");
      boost.send_command("ATH1");
      Serial.println("Turning line feeds ON ATL1");
      boost.send_command("ATL1");
      Serial.println("Turning spaces ON ATS1\n");
      boost.send_command("ATS1");
      
      Serial.println("=================================");
      for (int i=0;i<6;i++) {
        uint8_t pid = i * 32;
        Serial.printf("Supported PIDs: 01%02X\n", pid);
        sprintf(cmd, "01%02X", pid);
        boost.send_command(cmd);
        Serial.printf("%s", boost.OBD_response);
        delay(100);
      }
      Serial.println("=================================\n");
      Serial.println("Disconnecting bluetooth connection");
      SerialBT.disconnect();
      Serial.println("Halting program ... ");
      while(1);
    }
  }
}

Note that the command "ATCRA" turns off the filter which prevents responses from the second ECU (with response address 7E9) in my car. If this is left on, you get duplicated responses to some PIDs (as your code deals with).

FYI to apply the filter to prevent responses from the 7E9 ECU, issue this command during initialize:
send_command("ATCRA7E8"); // Set CAN hardware filter to receive from address 7E8 only

Sample output from a 2019 BMW is:

Supported PIDs: 0100
7E8 06 41 00 BF BF A8 93 
7E9 06 41 00 98 18 80 01 

Supported PIDs: 0120
7E8 06 41 20 A0 07 B1 19 
7E9 06 41 20 80 00 00 01 

Supported PIDs: 0140
7E8 06 41 40 FE D0 85 11 
7E9 06 41 40 C0 00 00 00 

Supported PIDs: 0160
7E8 06 41 60 64 00 00 01 

Supported PIDs: 0180
7E8 06 41 80 00 04 00 0D 

Supported PIDs: 01A0
7E8 06 41 A0 04 00 00 00 

And then paste the above output into this google spreadsheet I put together. It's not that pretty in terms of user input....but anyway, put it in cell J16 (the black cells). Then edit cell B15 to point to the group of 32 PIDs you're interested in. Or alternatively, just paste a single line response into Cell J16.

https://docs.google.com/spreadsheets/d/1R2C8_kY6fuFpd4JJyIrWOXqAQGgxm2MHYHXRt3qiKCc/edit?usp=sharing

Where column E says "Yes" it means that PID is supported by the vehicle.

Response byte ordering.

Have been using the latest version 2.4.1 which now has the monitorStatus method.

Reading the https://en.wikipedia.org/wiki/OBD-II_PIDs#Service_01_PID_01

This refers to byte 1, bit 7 being the MIL status bit.

A request for this PID returns 4 bytes of data (Big-endian).

When using Bit-Encoded-Notation, quantities like C4 means bit 4 from data byte C. Each bit is numerated from 0 to 7, so 7 is the most significant bit and 0 is the least significant bit (See below).

The first byte(A) contains two pieces of information. Bit A7 (MSB of byte A, the first byte) indicates whether or not the MIL (check engine light) is illuminated.

I tried to read this out of response_byte0, but the data didn't look right. Worked out that its actually in response_byte3 as this is the 4th byte from the right in binary terms.

My question is.

  1. Is Wikipedia wrong labeling this as byte A and referring to it as the first byte and its should be should it be byte D last byte?
  2. Should the response bytes be stored in the same order??
  3. Are both correct but it just needs to be made clear that response bytes in the library are reversed and in little endian?

printerror interval & ELM NO DATA error

hi mr.powerbroker2

First of all while I'm coding my project, suddenly the printerror interval increased compared to your example code "softwareserial_test"
what would be the problem....possibly, Is it the reason that void_loop processing was increased?

second of all this below is my sketch code,, For the last time ELM327 successfully received the data from the car obd2, meanwhile suddenly when I connect to obd2 port, ELM NO DATA error occurs... I don;t even know what the f is happening. obd2 vcc normally works, and it doesn't seem to be the obd2 cable problem. Can u give me a advice plz??
thanks ><

and asking for another little help.... I want my green and red LED to indicate current status e.g. ELM327 CONNECTED, VALUES ARE RECEIVING, PRINTERROR.... It's a little bit hard for me.. actually i'm not a programmer.. plz understand

#include <SoftwareSerial.h>
#include "ELMduino.h"

SoftwareSerial mySerial(2, 3); // RX, TX
#define ELM_PORT mySerial
#define BUZZER 10

ELM327 myELM327;

int green = 8;
int red = 9;

uint32_t rpm = 0;
uint32_t kph = 0;
uint32_t engineload = 0;
uint32_t enginetemp = 0;
uint32_t throttleposition = 0;
uint32_t intakeairtemp = 0;
int32_t fueltype = 0;

const int beepFrequencyS1 = 1500; //1000Hz, 연결성공시 부저 주파수1
const int beepFrequencyS2 = 2500; //1000Hz, 연결성공시 부저 주파수2
const int beepFrequencyF = 750; //500Hz, 연결실패시 부저 주파수
const int beepDurationS = 250; //1.0sec ,성공시 지속시간, (31~65535 Hz)
const int beepDurationF = 250; //0.25sec ,실패시 지속시간,

unsigned long pre_time = 0;
unsigned long cur_time = 0;
int ledState = LOW;

void setup()
{
pinMode(green, OUTPUT);
pinMode(red, OUTPUT);
pre_time = millis();
#if LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#endif

Serial.begin(38400);
ELM_PORT.begin(38400);

Serial.println("Attempting to connect to ELM327...");

if (!myELM327.begin(ELM_PORT))
{
    Serial.println("Couldn't connect to OBD scanner");
    do {
        digitalWrite(red, HIGH);
        digitalWrite(green, LOW);
        tone(BUZZER, beepFrequencyF, beepDurationF);
        delay(850); //ELM327 연결 실패시 0.85초 간격으로 Fail 부저 울림
    } while (1);
}

Serial.println("Connected to ELM327");
digitalWrite(green, HIGH);
digitalWrite(red, LOW);
tone(BUZZER, beepFrequencyS1, beepDurationS);
delay(600);
tone(BUZZER, beepFrequencyS1, beepDurationS);
delay(600);
tone(BUZZER, beepFrequencyS1, beepDurationS);
delay(600);
tone(BUZZER, beepFrequencyS2, beepDurationS);
delay(600);
noTone(10);

//ELM327 연결 성공시 Success 부저 4회 울림, led green ON

}

void loop()
{
cur_time = millis();
float tempRPM = myELM327.rpm();
int32_t tempVEHICLE_SPEED = myELM327.kph();
float tempENGINE_LOAD = myELM327.engineload();
float tempENGINE_COOLANT_TEMP = myELM327.enginetemp();
float tempTHROTTLE_POSITION = myELM327.throttleposition();
float tempINTAKE_AIR_TEMP = myELM327.intakeairtemp();
float tempFUEL_TYPE = myELM327.fueltype();

digitalWrite(red, LOW);

if (cur_time = pre_time >= 500)
{
    pre_time = cur_time;
    if (ledState == LOW) {
        ledState = HIGH;
    }
    else {
        ledState = LOW;
    }
    digitalWrite(green, ledState);
    
}
if (myELM327.status == ELM_SUCCESS)
{
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM : "); Serial.println(rpm);

    kph = (int32_t)tempVEHICLE_SPEED;
    Serial.print(kph); Serial.println("km/h");

    engineload = (uint32_t)tempENGINE_LOAD;
    Serial.print("EngineLoad : "); Serial.print(engineload); Serial.println("%");

    enginetemp = (uint32_t)tempENGINE_COOLANT_TEMP;
    Serial.print("EngineCoolantTemp : "); Serial.print(enginetemp); Serial.println("˚C");

    throttleposition = (uint32_t)tempTHROTTLE_POSITION;
    Serial.print("ThrottlePosition : "); Serial.print(throttleposition); Serial.println("%");

    intakeairtemp = (uint32_t)tempINTAKE_AIR_TEMP;
    Serial.print("IntakeAirTemp : "); Serial.print(intakeairtemp); Serial.println("˚C");

    fueltype = (int32_t)tempFUEL_TYPE;
    Serial.print("FuelType : "); Serial.print(fueltype);

    if (fueltype == 0)
        Serial.println("Not Available");
    else if (fueltype == 1)
        Serial.println("Gasoline");
    else if (fueltype == 2)
        Serial.println("Methanol");
    else if (fueltype == 3)
        Serial.println("Ethanol");
    else if (fueltype == 4)
        Serial.println("Disel");
    else if (fueltype == 5)
        Serial.println("LPG");
    else if (fueltype == 6)
        Serial.println("CNG");
    else if (fueltype == 7)
        Serial.println("Propane");

        tone(BUZZER, beepFrequencyS2, beepDurationS);


    delay(500);

}
else
printError();

}

void printError()
{
digitalWrite(green, LOW);
Serial.print("Received: ");
for (byte i = 0; i < myELM327.recBytes; i++)
Serial.write(myELM327.payload[i]);
Serial.println();

if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));
    
    tone(BUZZER, beepFrequencyF, beepDurationF);

delay(10);

}

ESP32 crashes during startup

Hi there, thanks for your work on this library. Unfortunately in my environment / setup, the ESP32 crashes during startup, I get the following backtrace from the serial debug monitor:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400014fd  PS      : 0x00060330  A0      : 0x800e6ed0  A1      : 0x3ffc83c0  
A2      : 0x00000030  A3      : 0x0000002c  A4      : 0x000000ff  A5      : 0x0000ff00  
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x00000000  A9      : 0x3ffc8690  
A10     : 0x00000003  A11     : 0x00060323  A12     : 0x00060320  A13     : 0x3ffbc480  
A14     : 0x00000000  A15     : 0x3ffc68e0  SAR     : 0x0000000a  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000030  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

Backtrace: 0x400014fd:0x3ffc83c0 0x400e6ecd:0x3ffc83d0 0x400e5019:0x3ffc86e0 0x400d2462:0x3ffc87a0 0x400d24ee:0x3ffc87d0 0x400d1865:0x3ffc87f0 0x400d2f3f:0x3ffc8830 0x4008e0bd:0x3ffc8850

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac

Pasting this into the Exception Decoder I get this:

PC: 0x400014fd
EXCVADDR: 0x00000030

Decoding stack results
0x400e6ecd: _svfprintf_r at ../../../.././newlib/libc/stdio/vfprintf.c line 1529
0x400e5019: sprintf at ../../../.././newlib/libc/stdio/sprintf.c line 644
0x400d2462: ELM327::initializeELM(char) at /Users/patrickfelstead/Documents/Arduino/libraries/ELMDuino/src/ELMduino.cpp line 101
0x400d24ee: ELM327::begin(Stream&, unsigned short, char) at /Users/patrickfelstead/Documents/Arduino/libraries/ELMDuino/src/ELMduino.cpp line 39
0x400d1865: setup() at /Users/patrickfelstead/Documents/OBD_bluetooth/OBD_bluetooth.ino line 26
0x400d2f3f: loopTask(void*) at /Users/patrickfelstead/Library/Arduino15/packages/esp32/hardware/esp32/1.0.4/cores/esp32/main.cpp line 14
0x4008e0bd: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

Easier to view with color coding, see screen grab:

Screen Shot 2020-05-22 at 12 11 14 pm

As you can see it is crashing due to sprintf function in ELM327::initializeELM(char protocol)

I think it's because you specified a string with %s for the auto search protocol character. So I made this change and bingo - no more crashing!!

Was:

const char * const TRY_PROT_H_AUTO_SEARCH     = "AT TP A%s"; // OBD

changed to

const char * const TRY_PROT_H_AUTO_SEARCH     = "AT TP %c"; // OBD

Now I'm at the point where I see Connected to ELM327 which is great! But it's not reading RPM. I haven't had the time to debug further, but at least I'm communicating with my ELM clone dongle, so I can try some basic commands like reading voltage with AT RV etc. I believe I can use your ESP32_test.ino sketch to do that.

Received:

Hi. i am using elm327 wifi and esp32

My code:

#include <WiFi.h>
#include "ELMduino.h"


const char* ssid = "WiFi-OBDII";
const char* password = "your-password";


//IP Adress of your ELM327 Dongle
IPAddress server(192, 168, 0, 10);
WiFiClient client;
ELM327 myELM327;


uint32_t rpm = 0;


void setup()
{
  Serial.begin(115200);

  // Connecting to ELM327 WiFi
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid);
  // WiFi.begin(ssid, password); //Use this line if your ELM327 has a password protected WiFi

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("Connected to Wifi");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  if (client.connect(server, 35000))
    Serial.println("connected");
  else
  {
    Serial.println("connection failed");
    while(1);
  }

  myELM327.begin(client,5);
}


void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else{
    printError();
  }
}


void printError()
{
  Serial.print("Received: ");
  for (byte i = 0; i < myELM327.recBytes; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

  delay(100);
}

My Output:

Received:
Received:
Received:
Received:
Received:

I guess it doesn't meet the following condition
if` (myELM327.status == ELM_SUCCESS){}

*How can I list if using custom pid? I think the "at" commands are not valid in the wireless network on elm327.Is there an android app where I can list pids?
*Most importantly, could this problem be caused by custom pid?

Hi,can you tell me BluetoothSerial.h source,thank you

Hi, Thank you for your code, but I have a problem. I look at your code in "examples/ESP32_Bluetooth_Serial/ESP32_Bluetooth_Serial.ino", it have a "BluetoothSerial.h" ,I can't find the source on the Internet. Can you tell me its link and it's library? or can you provide the code? Thank you.

Esp32 connection

Hello,Firstly i would like to thank you for all the hard work you have put into making this library.unlike the previous esp32 issue #11. I havent been able to get a bluetooth connnection between the esp32 and obd2 scanner .while running the ESP32_Bluetooth_Serial.ino code provided in the example, i get the following output "Couldn't connect to OBD scanner - Phase 2".In the previous issuses you recommended that people olso try out the esp32 test.ino example.i have tested that example and realised that i get a "Connected to ELM327" output even when the is no obd2 scanner present.

I am using the LILYGO® TTGO T-Call V1.3 ESP32 Wireless Module GPRS Antenna SIM Card SIM800L Board and a standard elm32 bluetooth obd2 scanner

images (2)

ESP32 connects via BT, can send AT commands only, no query TIMEOUT-STOPPED error

Hi, I have this problem and I tried almost everithing,
My Esp32 connects correctly to vlink bluetooth 4 adapter and I can send at commands successfully.
Example:

atz

atzELM327 v2.2

at dp

at dp AUTO, ISO 9141-2

0105

010541 05 2E

I can send and read succesfully AT commands with this sketch:

void loop()
{
   myELM327.sendCommand(READ_VOLTAGE);



  if (myELM327.status == ELM_SUCCESS)
  
  {
      
  Serial.print("Data "); Serial.println(myELM327.payload);
        
  }
  
  else
      printError();
}

But if I want to read coolant temperature with the following command is not working:

ELM327.queryPID(01, 05);

or this

myELM327.sendCommand("0105");

or this

 void loop()
{
  
float ct = myELM327.engineCoolantTemp();


  if (myELM327.status == ELM_SUCCESS)
  {
      Serial.print("Coolant C. "); Serial.println(ct);

  }
  
  else
      printError();
}

I have always the same errors 6-7 elm stopped and timeout but connection is stable, there is any problem with esp32 240mhz?
Timing of some sort to adjust in library for query command?
Thank You for Your help.

ERROR: ELM_NO_DATA on ESP32Dev device

Describe the bug
Hello! First of all, many thanks for your library, what an excellent work! Nevertheless, I'm having some troubles while trying to use it with a ESP32Dev device. I'm continuously being shown the following error:

Attempting to connect to ELM327...
Connected to ELM327
Payload received for rpm: NODATA
ERROR: ELM_NO_DATA
Payload received for kph: NODATA
ERROR: ELM_NO_DATA

I have tested the ESP32_test.ino example, with a successful connection to the device, as follows:

Attempting to connect to ELM327...
Connected to ELM327
Ensure your serial monitor line ending is set to 'Carriage Return'
Type and send commands/queries to your ELM327 through the serial monitor

AT Z
ELM327 v2.1
AT E0
OK
AT S0
OK
AT SP0
OK
010C
SEARCHING...
410C0B94

I'm wondering if you could give me a clue about what's going on. Thanks in advance!

To Reproduce
Upload to a ESP32 device the code below.
Connect to ELM327 device

Expected behavior
Show values to .kph(), .rpm() and standard PIDs

Equipment
Microcontroller: ESP32-Bit (programmable as ESP32 Dev Module), like this one: https://www.amazon.es/ESP32-Bit-Desarrollo-Bluetooth-Ethernet-ESP32-T/dp/B07GD4SGYM
OBD II Controller: OBD II Mini ELM327, like this one: https://www.amazon.es/Interfaz-Bluetooth-herramienta-an%C3%A1lisis-diagn%C3%B3stico/dp/B00WU97RH8
Car Model: Peugeot 206

Code

// modified test + my custom PIDs
// based purely on library

#include "BluetoothSerial.h"
#include "ELMduino.h"


#define ELM_PORT SerialBT
#define ESP_BLUETOOTH_NAME "ESP32"


BluetoothSerial SerialBT;
ELM327 myELM327;


void setup()
{
  //pinMode(LED_BUILTIN, OUTPUT);
  //digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  //ELM_PORT.setPin("1234");
  ELM_PORT.begin(ESP_BLUETOOTH_NAME, true);

  Serial.println("Attempting to connect to ELM327...");

  if (!ELM_PORT.connect("OBDII"))
  //if (!ELM_PORT.connect("00:1d:a5:68:98:8d"))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 1");
    while (1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }
  
  Serial.println("Connected to ELM327");
  
/*  for (int a = 0; a < 10; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH); delay(100);
    digitalWrite(LED_BUILTIN,LOW); delay(100); 
  }
*/
}


void loop()
{
  int32_t rpm = -1;                     // Directo
  int32_t engineLoad = -1;              // A/2.55
  int32_t engineCoolant = -1;           // A - 40
  int32_t shortTermFuelTrimBank1 = -1;  // A/1.28 - 100
  int32_t longTermFuelTrimBank1 = -1;   // A/1.28 - 100
  int32_t intakeManifoldPressure = -1;  // A
  int32_t kph = -1;                     // Directo
  int32_t timingAdvance = -1;           // A/2 - 64
  int32_t intakeAir = -1;               // A - 40
  int32_t throttlePosition = -1;        // A/2.55
  

  /////////////////////////////////////////////////////// RPM
  float tempRPM = myELM327.rpm();
  
  Serial.print("Payload received for rpm: ");
  for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (int32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
      printError();

  /////////////////////////////////////////////////////// Kph
  float kphTemp = myELM327.kph();
  
  Serial.print("Payload received for kph: ");
  for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
  {
    kph = (int32_t)kphTemp;
    Serial.print("KPH: "); Serial.println(kph);
  }
  else
      printError();

  /////////////////////////////////////////////////////// Engine Load
  if (myELM327.queryPID(SERVICE_01, ENGINE_LOAD))
  {
    int32_t engineLoadTemp = myELM327.findResponse();

    Serial.print("Payload received for Engine Load: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      engineLoad = engineLoadTemp/2.55;
      Serial.print("EngineLoad: "); Serial.println(engineLoad);
    }
    else
      printError();
  }


  /////////////////////////////////////////////////////// engineCoolant = -1;       // A - 40
  if (myELM327.queryPID(SERVICE_01, ENGINE_COOLANT_TEMP))
  {
    int32_t engineCoolantTemp = myELM327.findResponse();

    Serial.print("Payload received for Engine Coolant: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      engineCoolant = engineCoolantTemp - 40;
      Serial.print("EngineCoolant: "); Serial.println(engineCoolant);
    }
    else
      printError();
  }


  /////////////////////////////////////////////////////// shortTermFuelTrimBank1 = -1;  // A/1.28 - 100
  if (myELM327.queryPID(SERVICE_01, SHORT_TERM_FUEL_TRIM_BANK_1))
  {
    int32_t shortTermFuelTrimBank1Temp = myELM327.findResponse();

    Serial.print("Payload received for Short Term Fuel Trim Bank 1: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      shortTermFuelTrimBank1 = shortTermFuelTrimBank1Temp/1.28 - 100;
      Serial.print("Short Term Fuel Trim Bank1: "); Serial.println(shortTermFuelTrimBank1);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// longTermFuelTrimBank1 = -1;   // A/1.28 - 100
  if (myELM327.queryPID(SERVICE_01, LONG_TERM_FUEL_TRIM_BANK_1))
  {
    int32_t longTermFuelTrimBank1Temp = myELM327.findResponse();

    Serial.print("Payload received for Long Term Fuel Trim Bank 1: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      longTermFuelTrimBank1 = longTermFuelTrimBank1Temp/1.28 - 100;
      Serial.print("Long Term Fuel Trim Bank1: "); Serial.println(longTermFuelTrimBank1);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// intakeManifoldPressure = -1;  // A
  if (myELM327.queryPID(SERVICE_01, INTAKE_MANIFOLD_ABS_PRESSURE))
  {
    int32_t intakeManifoldPressureTemp = myELM327.findResponse();

    Serial.print("Payload received for Intake Manifold Absolute Pressure: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      intakeManifoldPressure = intakeManifoldPressureTemp;
      Serial.print("Intake Manifold Absolute Pressure: "); Serial.println(intakeManifoldPressure);
    }
    else
      printError();
  }


  /////////////////////////////////////////////////////// timingAdvance = -1;           // A/2 - 64
  if (myELM327.queryPID(SERVICE_01, TIMING_ADVANCE))
  {
    int32_t timingAdvanceTemp = myELM327.findResponse();

    Serial.print("Payload received for Timing Advance: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      timingAdvance = timingAdvanceTemp;
      Serial.print("Timing Advance: "); Serial.println(timingAdvance);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// intakeAir = -1;               // A - 40
  if (myELM327.queryPID(SERVICE_01, INTAKE_AIR_TEMP))
  {
    int32_t intakeAirTemp = myELM327.findResponse();

    Serial.print("Payload received for Intake Air Temp: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      intakeAir = intakeAirTemp - 40;
      Serial.print("Intake Air Temp: "); Serial.println(intakeAir);
    }
    else
      printError();
  }

  /////////////////////////////////////////////////////// throttlePosition = -1;        // A/2.55
  if (myELM327.queryPID(SERVICE_01, THROTTLE_POSITION))
  {
    int32_t throttlePositionTemp = myELM327.findResponse();

    Serial.print("Payload received for Throttle Position: ");
    for (byte i = 0; i < myELM327.PAYLOAD_LEN; i++)
      Serial.write(myELM327.payload[i]);
    Serial.println();
    
    if (myELM327.status == ELM_SUCCESS)
    {
      throttlePosition = throttlePositionTemp/2.55;
      Serial.print("Throttle Position: "); Serial.println(throttlePosition);
    }
    else
      printError();
  }



/*  for (int a = 0; a < 5; ++a)
  {
    digitalWrite(LED_BUILTIN,HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN,LOW);
    delay(200); 
  }
  */
}


void printError()
{
  if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_GARBAGE)
    Serial.println(F("\tERROR: ELM_GARBAGE"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_GENERAL_ERROR)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

  delay(500);
}

Wiring
N/A

Screenshots
N/A

Additional Context
N/A

Troubleshooting Connection Issues

  • Try 38400 baud instead of 115200 ---> Tried with no success.
  • If using an HC-05 for communication, ensure it's configured properly ---> N/A
  • Ensure the car is on and running during troubleshooting ---> Car running
    -Also tested with BT mac address, and providing PIN code, with no success.

rpm() function

Hi, if I call the rpm() function, I should get 2 bytes as answer, but I get these 2 bytes two times, so for example: 0D8C would be the right answer, but I get 0D8C0D8C, if I give the explicit AT cmd 010C to the ELM327, get 4 bytes as an answer, as well. Do you know why is this happenning?
Thank you!
@PowerBroker2

Compiler warning

Describe the bug
Compiler warning when enabled.

C:\Users\Stuart\Documents\Arduino\libraries\ELMDuino\src\ELMduino.cpp: In member function 'bool ELM327::initializeELM(char)':
C:\Users\Stuart\Documents\Arduino\libraries\ELMDuino\src\ELMduino.cpp:116:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
     if (sendCommand(command) == ELM_SUCCESS)
     ^~
C:\Users\Stuart\Documents\Arduino\libraries\ELMDuino\src\ELMduino.cpp:120:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  return connected;
  ^~~~~~

To Reproduce
Enable compiler warnings.

Expected behavior
No compiler warnings.

Code

    if (sendCommand(command) == ELM_SUCCESS)
        if (strstr(payload, "OK") != NULL)
            connected = true;

	return connected;

Troubleshooting Connection Issues

  • Try 38400 baud instead of 115200
  • If using an HC-05 for communication, ensure it's configured properly
  • Ensure the car is on and running during troubleshooting

Couldn't connect to OBD scanner...

hello powerbroker~

First of all, I used elm327 v1.5. Initially I removed elm327 bluetooth chip and slodered rx,tx,gnd,vcc and connect to arduino uno board. I didn't wanna communicate with bluetooth so I removed the chip following this youtube channel "https://www.youtube.com/watch?v=EG94t0rqag4&t=121s"
I used software_serial_test examples to my arduino and serial monitor just keep showing that couldn't connect to OBD scanner. what'd be the problem.... sorry for my bad english :(

Actually I m a damn fucking beginner of arduino and i don' know a shit about what the c language is and so on... I just started to learn about it.. I spent about a week to two weeks for this problem...
Screenshots

KakaoTalk_20201216_013304743_LI
KakaoTalk_20201216_023758651_LI

Additional Context
PLEASE HELP ME !!!!
Troubleshooting Connection Issues

  • Try 38400 baud instead of 115200 >> I have tried all the baud.. and I already have connected to the car but it doesn't work bro..

support on stm32

I'm on my project developing car connected internet of things using lte catm1 module. Do you have any plan to modify the code that it works on arm mbed IDE to run on stm board?? I have willing to pay you a little for this project.. thank you

>ASSERT_WARN(1 8), in lc_task.c at line 5054ASSERT_WARN(1 8), in lc_task.c at line 5054

Hi,

First of all thanks for this great library, i'm using arduino UNO+ESP32S+Bluetooth ELM327 dongle, with ESP32_test example from your library, it connects to elm327 dongle and communicating without any problem but i'm receiving this line on the terminal and didn't figure it out why it's returning this ">ASSERT_WARN(1 8), in lc_task.c at line 5054ASSERT_WARN(1 8), in lc_task.c at line 5054"

When i send 010C(speed) it returns "41 0C 00 00" without any problem. But in every 3-5 seconds it returns ">ASSERT_WARN(1 8), in lc_task.c at line 5054ASSERT_WARN(1 8), in lc_task.c at line 5054"

Why? and how i can fix it?
My console output as below;

ASSERT_WARN(1 8), in lc_task.c at line 5054010C
010C
ASSERT_WARN(1 8), in lc_task.c at line 505441 0C 00 00 


>ASSERT_WARN(1 8), in lc_task.c at line 5054ASSERT_WARN(1 8), in lc_task.c at line 5054010C
010C
41 0C 00 00 


>ASSERT_WARN(1 8), in lc_task.c at line 5054010C
010C
41 0C 00 00 


>ASSERT_WARN(1 8), in lc_task.c at line 5054010D
010D
41 0D 00 


>ASSERT_WARN(1 8), in lc_task.c at line 5054ASSERT_WARN(1 8), in lc_task.c at line 5054

Small ELM327::initializeELM improvements

I try to suggest some small improvements to ELM327::initializeELM :

A previously used software may have done settings adjustments that prevent ELMduino from communicating properly with ELM327. So it is a practice for many software to send ATZ as a first command.

ELMduino initialize protocol using AT SP. This write the protocol to the ELM327 eeprom every time. Anoter practice is to use AT TP (or AT TP A), that doesn't store default, and fallback to AT SP if previous command fails (some ELM327 doesn't support AT TP).

hi mr. powerbroker2 . question for the coding..

hello mr.

nowadays I'm really struggling to make a code
my goal is to get some PID responses to collect the information.
Actually I'm not a programmer, so it's damn fuckin super hard for me to coding..

first of all I added some PIDs in .cpp file like this
float ELM327::engineload()
{
if( status == ELM_SUCCESS)
return findResponse();

         return ELM_GENERAL_ERROR;

}

I also add float engineload(); on my .h file

then this is my sketch
#include <SoftwareSerial.h>
#include "ELMduino.h"

SoftwareSerial mySerial(2, 3); // RX, TX
#define ELM_PORT mySerial

ELM327 myELM327;

uint32_t rpm = 0;
uint32_t kph = 0;
uint32_t engineload= 0;

void setup()
{
#if LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#endif

Serial.begin(38400);
ELM_PORT.begin(38400);

Serial.println("Attempting to connect to ELM327...");

if (!myELM327.begin(ELM_PORT))
{
Serial.println("Couldn't connect to OBD scanner");
while (1);
}

Serial.println("Connected to ELM327");
}

void loop()
{
float tempRPM = myELM327.rpm();
int32_t tempVEHICLE_SPEED = myELM327.kph();
float tempENGINELOAD = myELM327.engineload();

//////////////////rpm///////////////////
if (myELM327.status == ELM_SUCCESS)
{
rpm = (uint32_t)tempRPM;
Serial.print("RPM: "); Serial.println(rpm);
}
///////////////////////////////////////////
///////////////////////kph///////////////////
if (myELM327.status == ELM_SUCCESS)
{
kph = (int32_t)tempVEHICLE_SPEED;
Serial.print(kph); Serial.println("km/h");
}

///////////////////////////////////////////////
///////////////////engineload/////////////////
if (myELM327.status == ELM_SUCCESS)
{
engineload = (uint32_t)tempENGINELOAD;
Serial.print("EngineLoad: "); Serial.println(engineload);
}
////////////////////////////////////////////
else
printError();

}

void printError()
{
Serial.print("Received: ");
for (byte i = 0; i < myELM327.recBytes; i++)
Serial.write(myELM327.payload[i]);
Serial.println();

if (myELM327.status == ELM_SUCCESS)
Serial.println(F("\tELM_SUCCESS"));
else if (myELM327.status == ELM_NO_RESPONSE)
Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
else if (myELM327.status == ELM_BUFFER_OVERFLOW)
Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
else if (myELM327.status == ELM_NO_DATA)
Serial.println(F("\tERROR: ELM_NO_DATA"));
else if (myELM327.status == ELM_STOPPED)
Serial.println(F("\tERROR: ELM_STOPPED"));
else if (myELM327.status == ELM_TIMEOUT)
Serial.println(F("\tERROR: ELM_TIMEOUT"));
else if (myELM327.status == ELM_TIMEOUT)
Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

delay(100);
}

Acutually It's too hard to understand when to use "float" "uint32_t" "int8_t" like this kind of things. Absolutely I know the concept of these things since I ve been studying.. however, when I get in to the sketch or cpp I BECOME A FUCKING IDIOT.. plz help me EXPERT powerbroker2...
I will expect your generous reply thank you~

Error 7 / Timeout with ESP32

Arduino IDE Version: 1.8.12
ELMduino Library Version: 2.0.12 (Latest at the time of opening this issue)
ESP32 Board Used: TTGO T4 (based on ESP32 Dev Board)
ELM327 Module: Generic Bluetooth ELM327
Car: MCC Smart build in 2000 using the ISO14230-4 KWP fast protocoll

Issue description:

I try to use your test-sketch for ESP32 . No changes. I get the following console output:

Console Output

My engine is of cause running, I testet the adapter using the "Torque" App for Android. The adapter works well, its name is "OBDII".

I believe the connection to the ECU may fail. Any idea how to figure that out?

If I use the ESP32_Bluetooth_Serial.ino-Sketch, I can see another error-message:
WhatsApp Image 2020-04-19 at 15 29 26

Make PAYLOAD_LEN redefinable.

Now PAYLOAD_LEN is fixed to 40.
Some ECU have custom pids with custom reply.
For example mine reply with 36, 44 and 126 characters on ELM side.

Problem with ESP32 to connect ELM327 via Bluetooth Classic

I have discovered by Serial Bluetooth Terminal the ODBII device with MAC 23:32:17:05:88:45, located as classic bluetooth device. It's this one: http://de.nsautodiagnostic.com/elm327-auto-code-reader/45440948.html
Using the following code with ESP32 (https://joy-it.net/de/products/SBC-NodeMCU-ESP32), Arduino IDE 1.8.13, ELMDuino 2.3.0, powered by USB with Power-HUB
Code:

#include "BluetoothSerial.h"
#include "ELMduino.h"


BluetoothSerial SerialBT;
#define ELM_PORT   SerialBT
#define DEBUG_PORT Serial


ELM327 myELM327;


uint32_t rpm = 0;
String name = "OBDII";

String MACadd = "23:32:17:05:88:45";
// converted to hex
uint8_t address[6]  = {0x17, 0x20, 0x11, 0x05, 0x58, 0x2D};


void setup()
{
#if LED_BUILTIN
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
#endif

  DEBUG_PORT.begin(115200);
  SerialBT.setPin("1234");
  ELM_PORT.begin("ArduHUD", true);
  
  if (!ELM_PORT.connect(name))
  {
    DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1");
    while(1);
  }

  if (!myELM327.begin(ELM_PORT))
  {
    Serial.println("Couldn't connect to OBD scanner - Phase 2");
    while (1);
  }

  Serial.println("Connected to ELM327");
}


void loop()
{
  float tempRPM = myELM327.rpm();

  if (myELM327.status == ELM_SUCCESS)
  {
    rpm = (uint32_t)tempRPM;
    Serial.print("RPM: "); Serial.println(rpm);
  }
  else
    printError();
}


void printError()
{
  Serial.print("Received: ");
  for (byte i = 0; i < myELM327.recBytes; i++)
    Serial.write(myELM327.payload[i]);
  Serial.println();
  
  if (myELM327.status == ELM_SUCCESS)
    Serial.println(F("\tELM_SUCCESS"));
  else if (myELM327.status == ELM_NO_RESPONSE)
    Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
  else if (myELM327.status == ELM_BUFFER_OVERFLOW)
    Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
  else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
    Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
  else if (myELM327.status == ELM_NO_DATA)
    Serial.println(F("\tERROR: ELM_NO_DATA"));
  else if (myELM327.status == ELM_STOPPED)
    Serial.println(F("\tERROR: ELM_STOPPED"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_TIMEOUT"));
  else if (myELM327.status == ELM_TIMEOUT)
    Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));

  delay(100);
}

Connection by using name produces this debug output:
[I][BluetoothSerial.cpp:510] _init_bt(): device name set [I][BluetoothSerial.cpp:225] esp_spp_cb(): ESP_SPP_INIT_EVT [I][BluetoothSerial.cpp:702] connect(): master : remoteName [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 0c:ec:84:0a:c1:72 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT Couldn't connect to OBD scanner - Phase 2

Connection by using address produces this debug output:
[I][BluetoothSerial.cpp:510] _init_bt(): device name set [I][BluetoothSerial.cpp:225] esp_spp_cb(): ESP_SPP_INIT_EVT [I][BluetoothSerial.cpp:722] connect(): master : remoteAddress [I][BluetoothSerial.cpp:290] esp_spp_cb(): ESP_SPP_DISCOVERY_COMP_EVT Couldn't connect to OBD scanner - Phase 2

Connection by using name and set PIN produces this output:
[E][BluetoothSerial.cpp:784] isReady(): BT is not initialized. Call begin() first [I][BluetoothSerial.cpp:510] _init_bt(): device name set [I][BluetoothSerial.cpp:118] btSetPin(): pin set [I][BluetoothSerial.cpp:225] esp_spp_cb(): ESP_SPP_INIT_EVT [I][BluetoothSerial.cpp:702] connect(): master : remoteName [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:327] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT [I][BluetoothSerial.cpp:329] esp_bt_gap_cb(): Scanned device: 23:32:17:05:88:45 [I][BluetoothSerial.cpp:336] esp_bt_gap_cb(): ESP_BT_GAP_DISC_RES_EVT : EIR : OBDII : 32 [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT [I][BluetoothSerial.cpp:379] esp_bt_gap_cb(): ESP_BT_GAP_DISC_STATE_CHANGED_EVT Couldn't connect to OBD scanner - Phase 2

Using Torque or Serial Bluetooth Terminal is working well with sending AT request and getting a propper result. Also the BT classic send and receive with Serial Bluetooth Monitor has worked fine.

Can you help me please?

ELM32_test.ino ESP32 SerialBT.write("a") returns 0 bytes written

Describe the bug
ELM32_test.ino vs Android apps (sketch sends nothing to bluetooth peer)

To Reproduce
Using a generic esp32 dev board.
This works in Android:

Screenshot_2020-07-03-01-20-01

Screenshot_2020-07-03-02-24-21

image

image

As you see, sending atrv works in Android (BMW 2004 330ci). I was hoping for the same behavior, send atz, atrv etc get a reply in the serial monitor.

ELM327 with USB cable

Hi!

I would guess that your library works using bluetooth commands, isn't it?

Have you ever saw this EML327 adapter?
image
I would be curios to know if it the same command you send via BT works the same via Serial, do you have any idea?

Add special PID

Hi,

how i can add a new PID (221E12) i have foud who i can change the PIDs, but all PID is in 0x???? form and im stuck on this point

How can I use ELMduino over Uart?

I have ELM32 but the Bluetooth module on ELM is broken.
I extracted the RX and TX line and connected them to my laptop. It's work.
I would like to know. How to connect them over arduino with your library?

ELM_NO_DATA using the Wifi sketch.

Describe the bug
Using the wifi sketch in the example, I've attempted to connect an esp8266 (which I also read about in the closed issues). The ESP connects fine and the connect to server proceeds. I'm then trying some simple as a RPM read, however this always produces an ELM_NO _DATA. I thought of doing some debugging work in with a ,net program on a laptop over the wifi direct, but I though I'd ask first to see if anybody could point out the obvious.

To Reproduce
Using a Iegeek OBD2 wifi adapter and the simple wifi sketch provided running on an esp8266.
I haven't hooked up a serial monitor laptop, but rather used a simple ws2812 led matrix which lights different leds according to the error.

Expected behavior
Getting an ELM_SUCCESS:
float tempRPM = myELM327.rpm();

if (myELM327.status == ELM_SUCCESS)
{
rpm = (uint32_t)tempRPM;
Serial.print("RPM: "); Serial.println(rpm);
}

Equipment
Iegeek wifi:
https://www.bol.com/nl/p/obd2-wifi-interface-adapter-mini-elm327/9200000055136781/?country=BE&Referrer=ADVNLGOO002060-G-88680672361-S-795237665226-9200000055136781&gclid=Cj0KCQjw0Mb3BRCaARIsAPSNGpU3xTYW7FFMST7e_kB1dhrsSr1uZfIS692eeg2aOtnFi13dVnzg0-AaAkMBEALw_wcB

Nodemcu

Code

void setup_wifi()
{
    WiFi.disconnect();
    WiFi.config(ip, gate, sub); 
    WiFi.mode(WIFI_STA);
    WiFi.begin(AP_SSID);

    while (WiFi.status() != WL_CONNECTED)
    {
        FlashYellow();
        delay(100);
        FlashRed();
        delay(400);
    }

    FlashYellow();
    delay(1000);
    wifiClient.connect(server, 35000);
    while (!wifiClient.connected())
    {
        FlashGreen();
        delay(100);
        FlashYellow();
        delay(400);
    }
    FlashGreen();
    myELM327.begin(wifiClient);
}

void setup()
{

    FastLED.addLeds<NEOPIXEL, NEOPIN>(matrixleds, NUMMATRIX);
    matrix->begin();
    matrix->setTextWrap(false);
    matrix->setBrightness(40);
    matrix->setTextColor(colors[0]);
    FlashRed();
#ifdef CURRENT
    IPAddress ip1(192, 168, 1, 1);
    pzem.setAddress(ip1);

#else

#endif

    //uartP.CmdReceivedPtr = DataReceived;
    delay(10);

    setup_wifi();
#ifdef OTA_MODE
    setup_ota();
#endif
}

int x = 0;
int pass = 0;
void printError()
{

     if (myELM327.status == ELM_NO_RESPONSE)
        FlashWhite(0);
        //Serial.println(F("\tERROR: ELM_NO_RESPONSE"));
    else if (myELM327.status == ELM_BUFFER_OVERFLOW)
        FlashWhite(1);
        //Serial.println(F("\tERROR: ELM_BUFFER_OVERFLOW"));
    else if (myELM327.status == ELM_GARBAGE)
        FlashWhite(2);
        //Serial.println(F("\tERROR: ELM_GARBAGE"));
    else if (myELM327.status == ELM_UNABLE_TO_CONNECT)
        FlashWhite(3);
        //Serial.println(F("\tERROR: ELM_UNABLE_TO_CONNECT"));
    else if (myELM327.status == ELM_NO_DATA)
        FlashWhite(4);
        //Serial.println(F("\tERROR: ELM_NO_DATA"));
    else if (myELM327.status == ELM_STOPPED)
        FlashWhite(5);
        //Serial.println(F("\tERROR: ELM_STOPPED"));
    else if (myELM327.status == ELM_TIMEOUT)
        FlashWhite(6);
        //Serial.println(F("\tERROR: ELM_TIMEOUT"));
    else if (myELM327.status == ELM_GENERAL_ERROR)
        FlashWhite(7);
        //Serial.println(F("\tERROR: ELM_GENERAL_ERROR"));
    delay(100);
}
void loop()
{
#ifdef OTA_MODE
    ArduinoOTA.handle();
#endif


    unsigned long currentMillis = millis();

    // if we lose wifi
    if (WiFi.status() != WL_CONNECTED)
    {
        setup_wifi();
    }

    // get rpm and update matrix
    if (currentMillis - previousMillisHeart > heartBeat)  //heartbeat = 1000ms
    {
        float tempRPM = myELM327.rpm();

        if (myELM327.status == ELM_SUCCESS)
        {
            rpm = (uint32_t)tempRPM;
            values[1] = (int)(rpm);
            values[2] = (int)(rpm / (float)2);
            values[3] = (int)(rpm / (float)4);
            values[4] = (int)(rpm / (float)8);
            values[5] = (int)(rpm / (float)16);
            values[6] = (int)(rpm / (float)32);
            values[7] = (int)(rpm / (float)64);
            UpdateBars();
        }
        else
        {
            printError();
        }
        previousMillisHeart = currentMillis;
    }
}

Wiring
Using wifi.

Thanks in advance.

Couldn't connect to OBD scanner - Phase 2

Describe the bug
Hi, I'm trying to build a bluetooth connection between ELM327( like this
image )
and an ESP32 Wroom.
I'm using the bluetooth_serial example, and I tried everything to initialize the ELM327 object myELM327.initialize('5'), myELM327.begin(ELM_PORT), myELM327.begin(ELM_PORT, ISO_14230_FAST_INIT), myELM327.begin(ELM_PORT, ISO_14230_FAST_INIT, payloadLen)
BUT everytime, I got this on serial monitor : "Couldn't connect to OBD scanner - Phase 2"
@PowerBroker2 Can you please help, what am I doing wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.