ELMduino Library

repository·master·Indexed 21 days ago

https://github.com/powerbroker2/elmduino

An Arduino library for interfacing with ELM327 OBD-II scanners. It enables developers to query vehicle data such as RPM, speed, and engine temperature, and to view or clear trouble codes using a non-blocking execution model.

Tokens
1.3K
Snippets
2
Records
4
Agent score
25%

What's inside ELMduino

  1. How the non-blocking execution model works

    master

    ELMduino uses a non-blocking execution model. When you call a PID query function (e.g., myELM327.rpm()), the function returns immediately without waiting for the hardware response. This allows your main loop() to continue executing other tasks.

    To retrieve the data, you must monitor the nb_rx_state property. You should repeatedly call the PID query function and check the state until it reaches a terminal state:

    1. ELM_SUCCESS: The data has been successfully received and is ready to use.
    2. ELM_GETTING_MSG: The library is still waiting for a response from the ELM327. Continue your loop and check again later.
    3. Error State: If nb_rx_state is neither ELM_SUCCESS nor ELM_GETTING_MSG, an error has occurred. Use myELM327.printError() to diagnose the issue.

    CRITICAL RULE: Do not attempt to query more than one PID at a time. You must wait for the current PID query to reach ELM_SUCCESS or an error state before initiating the next query.

    // Example of the non-blocking pattern
    rpm = myELM327.rpm();
    
    if (myELM327.nb_rx_state == ELM_SUCCESS) {
      // Use the data
    } else if (myELM327.nb_rx_state != ELM_GETTING_MSG) {
      // Handle error
      myELM327.printError();
    }
  2. Troubleshoot ELM327 connection issues

    master

    If you are having difficulty establishing or maintaining a connection to your ELM327 scanner, try the following steps:

    1. Adjust Baud Rate: If the default 115200 fails, try 38400. If that fails, try other possible baud rates.
    2. ESP32 Bluetooth Configuration: If using BluetoothSerial on an ESP32, use the ELM327's MAC address instead of the device name (e.g., "OBDII").
    3. Clear Paired Devices: If connection issues persist on ESP32, you may need to remove previously paired devices using a specialized sketch.
  3. Example: Querying RPM and Speed using ELMduino

    master

    This example demonstrates how to initialize the library on Serial1 and use a state machine in the loop() to query Engine RPM and Vehicle Speed (MPH) using the non-blocking pattern.

    #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;
        }
      }
    }