이것은 Arduino를 ELM327 OBD-II 스캐너와 쉽게 인터페이스할 수 있는 간단하면서도 강력한 라이브러리입니다. 이 라이브러리를 사용하면 모든 OBD-II 지원 PID를 쿼리하여 다양한 자동차 데이터(예: 속도, rpm, 엔진 온도 등)를 수집할 수 있습니다. 또한 ELMduino를 사용하여 자동차의 문제 코드를 보고 지울 수 있습니다. 더 이상 AutoZone에 갈 필요가 없습니다!
Arduino IDE의 라이브러리 관리자를 사용하여 ELMduino를 설치합니다("ELMduino.h" 검색).
ELM327에 연결/연결을 유지하는 데 어려움이 있는 경우 115200 대신 38400 보드를 사용해 보십시오. 여전히 문제가 있으면 가능한 다른 보드를 모두 시도해 보십시오. 마지막으로 ESP32에서 BluetoothSerial을 사용하는 경우 장치 이름 "OBDII" 대신 ELM327의 MAC 주소를 사용해 보고 이 스케치를 사용하여 페어링된 장치를 제거해 보세요.
라이브러리는 비차단입니다. 이는 myELM327.rpm()
과 같은 PID를 쿼리할 때 코드가 응답을 기다리지 않아 메인 루프의 다른 코드가 실행되는 것을 차단한다는 의미입니다. ELMDuino를 사용하면 메인 루프에서 다른 작업을 계속할 수 있습니다. 이 작업을 수행하려면 PID 쿼리 함수를 반복적으로 호출하고 ELM_SUCCESS
와 같아질 때까지 비차단 수신 상태( myELM327.nb_rx_state
)를 확인해야 합니다. 상태가 ELM_SUCCESS
아닌 경우 라이브러리는 여전히 응답 수신을 기다리고 있을 수 있습니다. 이는 myELM327.nb_rx_state
가 ELM_GETTING_MSG
와 동일함을 나타냅니다. 상태가 이러한 값(ELM_SUCCESS 또는 ELM_GETTING_MSG) 중 하나와 같지 않으면 오류가 발생했음을 나타냅니다. myELM327.printError()
호출하여 문제가 무엇인지 확인할 수 있습니다. 엔진 속도를 RPM 단위로 쿼리하는 아래의 간단한 예를 참조하세요.
명확히 하기 위해, 한 번에 두 개 이상의 PID를 쿼리하려고 시도하지 마십시오. 다음 PID 쿼리를 시작하기 전에 현재 PID 쿼리가 완료될 때까지 기다려야 합니다.
# 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 ;
}
}
}
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 ();
void queryPID ( const uint8_t & service, const uint16_t & pid, const uint8_t & num_responses = 1 );
void 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 ();
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 ' ;
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
(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 " ;