thatlarrypearson / telemetry-obd

Telemetry OBDII (Onboard Diagnostic Data 2) Logger
MIT License
14 stars 1 forks source link

Telemetry OBD Logger

The Telemetry OBD Logger captures vehicle performance data using an OBD interface device attached to the vehicle. While the logger is running, it writes output to files. Data from multiple vehicles can easily be logged. Data from each different vehicle is stored in a directory/folder matching the vehicle's VIN or vehicle identification number.

The software is designed to run on Raspberry Pi with Raspberry Pi OS (formerly known as Raspbian) installed. Bluetooth capabilities are added to the Raspberry Pi through a USB Bluetooth adapter (BT Dongle) and installed software (Bluetooth Driver and tools).

The OBD Logger software runs on Python versions 3.11 (optionally 3.10).

High Level System View

OBD Logger

Command Line Usage

The Telemetry OBD Logger application command line interface (CLI) is as follows:

$ python3.11 -m telemetry_obd.obd_logger --help
usage: obd_logger.py [-h] [--config_file CONFIG_FILE] [--config_dir CONFIG_DIR] [--full_cycles FULL_CYCLES] [--timeout TIMEOUT] [--logging] [--no_fast]
                     [--shared_dictionary_name SHARED_DICTIONARY_NAME] [--shared_dictionary_command_list SHARED_DICTIONARY_COMMAND_LIST] [--verbose]
                     [--version]
                     [base_path]

Telemetry OBD Logger

positional arguments:
  base_path             Relative or absolute output data directory. Defaults to 'data'.

options:
  -h, --help            show this help message and exit
  --config_file CONFIG_FILE
                        Settings file name. Defaults to '<vehicle-VIN>.ini' or 'default.ini'.
  --config_dir CONFIG_DIR
                        Settings directory path. Defaults to './config'.
  --full_cycles FULL_CYCLES
                        The number of full cycles before a new output file is started. Default is 50.
  --timeout TIMEOUT     The number seconds before the current command times out. Default is 1.0 seconds.
  --logging             Turn on logging in python-obd library. Default is off.
  --no_fast             When on, commands for every request will be unaltered with potentially long timeouts when the car doesn't respond promptly or at
                        all. When off (fast is on), commands are optimized before being sent to the car. A timeout is added at the end of the command.
                        Default is off.
  --output_file_name_counter
                        Base output file name on counter not timestamps
  --shared_dictionary_name SHARED_DICTIONARY_NAME
                        Enable shared memory/dictionary using this name
  --shared_dictionary_command_list SHARED_DICTIONARY_COMMAND_LIST
                        Comma separated list of shared NMEA commands/sentences to be logged (no spaces), defaults to all.
  --verbose             Turn verbose output on. Default is off.
  --version             Print version number and exit.
$

--timeout TIMEOUT

The timeout value determines how long a read request can take between the underlying python-OBD library and the OBD reader device. If one or more individual commands are causing problems by intermittently responding with "no response" instead of a real value, an increase in the timeout value may help alleviate the problem.

--no_fast

--no_fast can also be used to reduce the number of "no response"s but be aware of the consequences. For commands that are not available on the vehicle being instrumented, the software may just wait forever for a response that will never come.

--shared_dictionary_name

When using UltraDict, the most embarrassing bug to find is the one where --shared_dictionary_name is set in the consuming application (e.g. telemetry_obd.obd_logger) but GPS or weather data just isn't showing up. When the expected data isn't showing up, add one or more of the following to the command line of telemetry_obd.obd_logger:

Ask me how I know. :unamused:

--version

Responds with the version and exits.

Telemetry OBD Logger Run Cycles

While logging, OBD Logger submits a pattern of OBD commands to the vehicle and stores the vehicle's responses. There are three patterns:

Run Cycles

Startup

The startup list of OBD commands is only executed when the program starts up. Typically, this list of OBD commands includes:

Housekeeping

A list of OBD commands that have ("relatively") "slow changing" return values such as AMBIANT_AIR_TEMP and BAROMETRIC_PRESSURE. These are commands that need to be run over and over again but in a slower loop.

Cycle

A list of OBD commands that have fast changing return values such as RPM, MAF (Mass Air Flow) and PERCENT_TORQUE. The idea is for these commands to run over and over again in relatively fast loops.

Full Cycle

The repeating part of the OBD command pattern is called a "full cycle" and has OBD commands from Cycle executed in a group followed by the next Housekeeping command. This basic pattern repeats over and over. When the end of the Housekeeping commands is reached, a "Full Cycle" has been achieved.

The total number of command submissions in a full cycle is the count of commands in Housekeeping times (one plus the count of commands in Cycle).

The --full_cycles parameter is used to set the number of full_cycles contained in output data files. Once the --full_cycles limit is reached, the data file is closed and a new one is opened. This keeps data loss from unplanned Raspberry Pi shutdowns to a minimum.

Telemetry OBD Logger Configuration Files

Configuration files are used to tell OBD Logger what OBD commands to send the vehicle and the order to send those commands in. A sample configuration file is shown below and another one is included in the source code.

Default Configuration File

A default configuration file is included in the repository at config/default.ini. This configuration file contains most OBD commands. There are wide variations in supported command sets by manufacturer, model, trim level and year. By starting out with this configuration file, OBD Logger will try all commands. After a full cycle is run, unsupported commands will respond with "obd_response_value": "no response" in the output data.

Some commands will result in an OBD response value of "no response" ("obd_response_value": "no response") when the vehicle is unable to satisfy the OBD data request quickly enough. You can identify this problem by searching for all responses for a particular command and seeing if sometimes the command responds with "no response" or with a value.

For example, 2017 Ford F-450 truck FUEL_RATE command in the cycle section of the configuration file returned mixed results. In 1,124 attempts, 1084 responded with a good value while 40 responded with no response.

human@computer:data/FT8W4DT5HED00000$ grep FUEL_RATE FT8W4DT5HED00000-20210910204443-utc.json | grep "no response" | wc -l
40
human@computer:data/FT8W4DT5HED00000$ grep FUEL_RATE FT8W4DT5HED00000-20210910204443-utc.json | grep -v "no response" | wc -l
1084

This problem may be solved by increasing the OBD command timeout from its default to a higher value. Use the --timeout setting when invoking the obd_logger command.

Telemetry OBD Logger Output Data Files

Output data files are in a hybrid format. Data files contain records separated by line feeds (LF) or carriage return and line feeds (CF and LF). The records themselves are formatted in JSON. Sample output follows:

{"command_name": "AMBIANT_AIR_TEMP", "obd_response_value": "25 degC", "iso_ts_pre": "2020-09-09T15:38:29.114895+00:00", "iso_ts_post": "2020-09-09T15:38:29.185457+00:00"}<CR>
{"command_name": "BAROMETRIC_PRESSURE", "obd_response_value": "101 kilopascal", "iso_ts_pre": "2020-09-09T15:38:29.186497+00:00", "iso_ts_post": "2020-09-09T15:38:29.259106+00:00"}<CR>
{"command_name": "CONTROL_MODULE_VOLTAGE", "obd_response_value": "0.0 volt", "iso_ts_pre": "2020-09-09T15:38:29.260143+00:00", "iso_ts_post": "2020-09-09T15:38:29.333047+00:00"}<CR>
{"command_name": "VIN", "obd_response_value": "TEST_VIN_22_CHARS", "iso_ts_pre": "2020-09-09T15:38:30.029478+00:00", "iso_ts_post": "2020-09-09T15:38:30.061014+00:00"}
{"command_name": "FUEL_STATUS", "obd_response_value": "no response", "iso_ts_pre": "2020-09-09T15:38:29.771997+00:00", "iso_ts_post": "2020-09-09T15:38:29.824129+00:00"}

JSON Fields

Pint encoded values are strings with a numeric part followed by the unit. For example, "25 degC" represents 25 degrees Centigrade. "101 kilopascal" is around 14.6 PSI (pounds per square inch). Pint values are used so that the units are always kept with the data and so that unit conversions can easily be done in downstream analysis software. These strings are easy to deserialize to Pint objects for use in Python programs.

Telemetry OBD Logger Debug Output

OBD Logger provides additional information while running when the --verbose option is used. Additionally, The underlying python obd library (python-obd) supports detailed low-level logging capabilities which can be enabled within OBD Logger with the --logging option.

Sample --logging output follows:

[obd.obd] ======================= python-OBD (v0.7.1) =======================
INFO:obd.obd:======================= python-OBD (v0.7.1) =======================
[obd.obd] Using scan_serial to select port
INFO:obd.obd:Using scan_serial to select port
[obd.obd] Available ports: ['/dev/rfcomm0']
INFO:obd.obd:Available ports: ['/dev/rfcomm0']
[obd.obd] Attempting to use port: /dev/rfcomm0
INFO:obd.obd:Attempting to use port: /dev/rfcomm0
[obd.elm327] Initializing ELM327: PORT=/dev/rfcomm0 BAUD=auto PROTOCOL=auto
INFO:obd.elm327:Initializing ELM327: PORT=/dev/rfcomm0 BAUD=auto PROTOCOL=auto
[obd.elm327] Response from baud 38400: b'\x7f\x7f\r?\r\r>'
DEBUG:obd.elm327:Response from baud 38400: b'\x7f\x7f\r?\r\r>'
[obd.elm327] Choosing baud 38400
DEBUG:obd.elm327:Choosing baud 38400
[obd.elm327] write: b'ATZ\r'
DEBUG:obd.elm327:write: b'ATZ\r'
[obd.elm327] wait: 1 seconds
DEBUG:obd.elm327:wait: 1 seconds
[obd.elm327] read: b'ATZ\r\r\rELM327 v1.5\r\r>'
DEBUG:obd.elm327:read: b'ATZ\r\r\rELM327 v1.5\r\r>'
[obd.elm327] write: b'ATE0\r'
DEBUG:obd.elm327:write: b'ATE0\r'
[obd.elm327] read: b'ATE0\rOK\r\r'
DEBUG:obd.elm327:read: b'ATE0\rOK\r\r'
[obd.elm327] write: b'ATH1\r'
DEBUG:obd.elm327:write: b'ATH1\r'
[obd.elm327] read: b'OK\r\r>'
DEBUG:obd.elm327:read: b'OK\r\r>'
[obd.elm327] write: b'ATL0\r'

OBD Logger Data File Naming Convention

See Telemetry System Boot and Application Startup Counter.

Testing All Available OBD Commands To See Which Ones Work On Your Vehicle

Telemetry OBD Command Tester can be used to determine which set of OBD commands are supported by a given vehicle.

$ python3.11 -m telemetry_obd.obd_command_tester --help
usage: obd_command_tester.py [-h] [--base_path BASE_PATH] [--cycles CYCLES] [--timeout TIMEOUT] [--logging] [--no_fast] [--verbose]

Telemetry OBD Command Tester

optional arguments:
  -h, --help            show this help message and exit
  --base_path BASE_PATH
                        Relative or absolute output data directory. Defaults to 'data'.
  --cycles CYCLES       The number of cycles before ending. A cycle consists of all known OBD commands. Default is 10.
  --timeout TIMEOUT     The number seconds before a command times out. Default is 0.5 seconds.
  --logging             Turn on logging in python-obd library. Default is off.
  --no_fast             When on, commands for every request will be unaltered with potentially long timeouts when the car
                        doesn't respond promptly or at all. When off (fast is on), commands are optimized before being
                        sent to the car. A timeout is added at the end of the command. Default is off so fast is on.
  --output_file_name_counter
                        Base output file name on counter not timestamps
  --verbose             Turn verbose output on. Default is off.

The output file format is the same as telemetry_obd.obd_logger as are many of the command line arguments. --cycles determines the number of times the full list of known OBD commands is tried. The OBD command list needs to be run a number of times because vehicles don't alway respond to requests in a timely manner.

Test output files are named differently than obd_logger data files. Both test and obd_logger data files will be placed in the {BASE_PATH}/{VIN} directory. For example, using data (default) as the base path, if the vehicle VIN is FT8W4DT5HED00000, then test files will be of the form data/FT8W4DT5HED00000/FT8W4DT5HED00000-TEST-20211012141917-utc.json. The obd_logger files will be of the form data/FT8W4DT5HED00000/FT8W4DT5HED00000-20211012141917-utc.json.

Issues Surfaced During Vehicle Testing

IMPORTANT! Some vehicle identification numbers (VIN) are known to drop characters when being recorded. Not to worry as the recorded VIN is still VERY UNLIKELY to overlap with another vehicle's VIN (unless you are working with thousands of vehicles). VIN data is provided by the python-obd library.

IMPORTANT! Calibration Verification Numbers (CVN) come in 4 byte sets. Multiple CVN (more than 4) can be returned through a single CVN command. As a result, the CVN data isn't likely to be valid as provided by the python-obd library.

IMPORTANT! Calibration IDs (CALIBRATION_ID) come in 16 byte sets. Multiple CALIBRATION_ID (more than 4) can be returned through a single CALIBRATION_ID command. As a result, the CALIBRATION_ID data isn't likely to be valid as provided by the python-obd library.

Problems like the above can be found by running telemetry_obd.obd_logger and telemetry_obd.obd_command_tester with the --logging and --verbose command line arguments. Look for "DEBUG:obd.OBDCommand:Message was longer than expected" in the output.

Configuration File Creation and Validation

When a VIN (vehicle identification number) specific configuration file doesn't exist, the OBD Logger program defaults to using the "default.ini" configuration file. This file, included in the software distribution under "config/default.ini" contains most known OBD commands. Because of the wide variations in supported command sets by manufacturer, model, trim level and year made, it is difficult to know what OBD commands a specific car will respond to. Additionally, manufacturers don't typically publish lists of valid OBD commands for each vehicle sold. This "try-them-all" method seems to be the only approach to identifying which OBD commands a specific vehicle will respond to.

The preferred way to "try-them-all", that is try every known OBD command, is to use the telemetry_obd.obd_command_tester program. Once all the possible known OBD commands have been tried, it becomes possible to create a list of valid known commands to be used in the creation of a vehicle specific configuration file. The OBD Logger software was written to automatically choose configuration files appropriately named "<VIN>.ini" by default. If the "<VIN>.ini" isn't available, then the other default, "default.ini", is chosen.

Analysis of telemetry_obd.obd_command_tester and telemetry_obd.obd_logger output is done by telemetry_obd_log_to_csv.obd_log_evaluation found in the Telemetry OBD Data To CSV File repository.

When creating vehicle specific configuration files, use obd_log_evaluation to determine the list of commands providing valid vehicle responses. Only valid OBD commands should be used long term when gathering vehicle data.

Raspberry Pi System Installation

The recommended Raspberry Pi system is a Raspberry Pi 4 Model B, Raspberry Pi 400 or Raspberry Pi 5 with 4 GB RAM or more. The full 64 bit release of Raspberry Pi OS version 12 (bookworm) or newer, including the GUI is the recommended operating system. When choosing a Micro-SD card for storage, look for Internet resources like Best microSD Cards for Raspberry Pi & SBCs as a guide to making an appropriate selection. Select cards 32 GB or larger.

After installing Raspberry Pi OS on a Raspberry Pi 4 computer, update the operating system to the newest version. One way to do this is as follows:

# update and upgrade Linux/Raspberry Pi OS
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get autoremove -y
sudo shutdown -r now
sudo apt-get dist-upgrade -y
sudo shutdown -r now

Install useful software:

# git software
sudo apt-get install -y git

Bluetooth Software

Install the Bluetooth support software and then reboot the system:

# Bluetooth support software
sudo apt-get install -y bluetooth bluez bluez-tools blueman bluez-hcidump
# Bluetooth support software requires reboot to become activated
sudo shutdown -r now

Pairing Bluetooth OBD Devices

Bluetooth OBD adapters must be paired and trusted before they can be used. The pairing and trust process is covered in Pairing Bluetooth OBD Devices.

Bluetooth Trouble

After operating system upgrades, Bluetooth may not operate as expected. Possible solutions may include

Python 3.11

Validate that your Raspberry Pi has Python version 3.11 available:

# Python 3 version
human@hostname:~$ python3 --version
Python 3.6.9
# Python 3.11 version
human@hostname:~$ python3.11 --version
Python 3.11.5
human@hostname:~$

The latest Raspberry Pi OS version Bookworm (12.2), ships with Python 3.11 but don't use it. It has a new feature that will prevent you from using pip to download necessary Python packages. Instead, download/make/install Python 3.11 from source following the instructions below.

# Python 3 version on Rasberry Pi OS Bookworm Version 12.2
human@hostname:~$ python3 --version
Python 3.11.2
human@hostname:~$

If Python 3.11, isn't already installed you will need to compile it from source before installing it. Follow the Python 3.11 Install Instructions to download, compile and install the preferred Python 3.11.

Alternatively, you may follow the Python 3.10 Install Instructions to download, compile and install Python 3.10.

Installing telemetry_obd Package

# get latest version of this software from github repository
git clone https://github.com/thatlarrypearson/telemetry-obd.git
cd telemetry-obd
python3.11 -m build
python3.11 -m pip install --user dist/telemetry_obd-0.4.2-py3-none-any.whl

# make shell programs executable
chmod 0755 bin/*.sh
cd

On Windows 10, connecting to USB or Bluetooth ELM 327 OBD interfaces is simple. Plug in the USB and it works. Pair the Bluetooth ELM 327 OBD interface and it works. Linux and Raspberry Pi systems are a bit more challenging.

On Linux/Raspberry Pi based systems, USB ELM 327 based OBD interfaces present as tty devices (e.g. /dev/ttyUSB0). If software reports that the OBD interface can't be accessed, the problem may be one of permissions. Typically, tty devices are owned by root and group is set to dialout. The user that is running the OBD data capture program must be a member of the same group (e.g. dialout) as the tty device.

# add dialout group to the current user's capabilities
sudo adduser $(whoami) dialout

On Linux/Raspberry Pi, Bluetooth serial device creation is not automatic. After Bluetooth ELM 327 OBD interface has been paired, sudo rfcomm bind rfcomm0 <BT-MAC-ADDRESS> will create the required serial device. An example follows:

# get the Bluetooth ELM 327 OBD interface's MAC (Media Access Control) address
sudo bluetoothctl
[bluetooth]# devices
Device 00:00:00:33:33:33 OBDII
[bluetooth]# exit
# MAC Address for OBD is "00:00:00:33:33:33"

# bind the Bluetooth ELM 327 OBD interface to a serial port/device using the interfaces Bluetooth MAC (Media Access Control) address:
sudo rfcomm bind rfcomm0 00:00:00:33:33:33

Realize that before the above can work, the Bluetooth device must have already been paired to the Raspberry Pi. One easy way to pair is to use the Raspberry Pi's GUI to access the Bluetooth. The pairing and trust process is covered in Pairing Bluetooth OBD Devices.

RaspberryPi Bluetooth GUI Utility

On Linux/Raspberry Pi systems, the rfcomm command creates the device /dev/rfcomm0 as a serial device owned by root and group dialout. If multiple Bluetooth serial devices are paired and bound to /dev/rfcomm0, /dev/rfcomm1, /dev/rfcomm2 and so on, OBD Logger will only automatically connect to the first device. The code can be modified to resolve this limitation.

Regardless of connection type (USB or Bluetooth) to an ELM 327 OBD interface, the serial device will be owned by root with group dialout. Access to the device is limited to root and users in the group dialout.

Users need to be added to the group dialout. Assuming the user's username is human:

human@hostname:~ $ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Aug 13 15:47 /dev/ttyUSB0
human@hostname:~ $ ls -l /dev/rfcomm0
crw-rw---- 1 root dialout 120, 0 Aug 13 15:47 /dev/rfcomm0
human@hostname:~ $ sudo adduser human dialout

Installing and Enabling Shared Dictionary Feature

The shared dictionary feature requires the UltraDict Python package to be installed using UltraDict Installation instructions.

Once the package is installed, the feature can be enabled by changing the obd_logger.sh shell program. The change involves adding command line options to turn the feature on.

    ${APP_PYTHON} -m telemetry_obd.obd_logger \
        --config_file "${APP_CONFIG_FILE}" \
        --config_dir "${APP_CONFIG_DIR}" \
        --full_cycles "${APP_FULL_CYCLES}" \

Add the following option to the telemetry_obd.obd_logger command line below the --full_cycles option:

        --shared_dictionary_name "${SHARED_DICTIONARY_NAME}" \

If specific shared dictionary keys are desired, they can be added below --shared_dictionary_name.

    --shared_dictionary_command_list "NMEA_GNGNS,NMEA_GNGST,NMEA_GNVTG,NMEA_GNZDA,WTHR_rapid_wind,WTHR_hub_status,WTHR_device_status,WTHR_obs_st" \

If the default shared dictionary keys are desired, they can be added below --shared_dictionary_name.

    --gps_defaults \
    --wthr_defaults \
    --imu_defaults \

-shared_dictionary_command_list, --gps_defaults, --wthr_defaults and imu_defaults are used when present in any combination to determine which shared dictionary commands are added into the logged data files.

The --shared_dictionary_name option should appear on the line before "${APP_BASE_PATH}"

        "${APP_BASE_PATH}"

Headless Operation On Raspberry Pi

In order to reliably run in an automotive environment, the OBD Logger application needs to start automatically after all preconditions are satisfied. That is, the application must start without any user interaction. The trigger for starting the application is powering up the Raspberry Pi system.

/etc/rc.local

On the Raspberry Pi, commands embedded in "/etc/rc.local" will be run at the end of the system startup sequence by the root user. A sample "/etc/rc.local" follows:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# BEGIN TELEMETRY-OBD SUPPORT

/bin/nohup "/root/bin/telemetry.rc.local.obd" &

# END TELEMETRY-OBD SUPPORT

exit 0

/etc/rc.local invokes /root/bin/telemetry.rc.local. The functionality in /root/bin/telemetry.rc.local is not placed in /etc/rc.local for these reasons:

telemetry-obd/root/bin/telemetry.rc.local.obd

telemetry-obd/root/bin/telemetry.rc.local.obd must be run as root. Once the Bluetooth subsystem is configured correctly, it invokes bin/obd_logger.sh which invokes obd_logger.py provided in this distribution.

Shell variables, like OBD_USER must be changed in root/bin/telemetry.rc.local to match the target system. The line for BT_MAC_ADDR in "00:04:3E:5A:A7:67" "00:19:5D:26:4B:5F" must also be changed. the Bluetooth Media Access Control layer addresses ("00:04:3E:5A:A7:67" and "00:19:5D:26:4B:5F") will need changing to match the target Bluetooth OBD dongle devices. This address, like an Internet address, must match your current configuration. Assuming your Bluetooth OBD adapter is currently paired to your Raspberry Pi, click on the Bluetooth icon on your Raspberry Pi desktop and select the Devices option.

RaspberryPi Bluetooth GUI Utility Devices Dialog

The yellow arrow points to where the Bluetooth MAC address is found on the Devices dialog box.

The runuser command in "telemetry-obd/root/bin/telemetry.rc.local.obd" file runs the "telemetry-obd/bin/obd_logger.sh" bash shell program as user "human" and group "dialout".

Once the telemetry-obd/root/bin/telemetry.rc.local.obd file has been modified, it must be copied to /root/bin and the file permissions changed:

$ cd
$ cd telemetry-obd/root/bin
$ sudo mkdir /root/bin
$ sudo cp telemetry.rc.local.obd /root/bin
$ sudo chmod 0755 /root/bin/telemetry.rc.local.obd
$ sudo ls -l /root/bin/telemetry.rc.local.obd
$ sudo ls -l /root/bin/telemetry.rc.local.obd
-rwxr-xr-x 1 root root 1503 May 31 10:16 /root/bin/telemetry.rc.local.obd
$

Make both obd_logger.sh and obd_tester.sh executable by using the command chmod +x obd_logger.sh obd_tester.sh.

Date/Time Accuracy During Data Collection

After the power has been off, an unmodified Raspberry Pi will do one of the following to determine the time it starts up with:

While the Raspberry Pi runs, time updates as expected in its built-in clock and it periodically saves the current time value to disk. Because the built-in clock only works while the power is on, when the power goes off, the clock stops working. When power comes back on, the clock starts up from zero time. During the boot process, the clock gets updated from the disk and later, after the network starts up, an NTP server. No network, no time update.

Each bit of data collected is collected with timestamps. Data and log file names have embedded timestamps in them. When the clock is hours or even weeks behind the actual time, data analysis becomes more difficult as it is hard to connect OBD data with driver activity such as stops for fuel or stops at destinations.

One solution to consider is to always provide the Raspberry Pi with Internet access, especially during the boot process. For example, mobile phones (with the correct carrier plan) support mobile WIFI hotspot capability. In iPhone settings, this shows up in the Settings app as Personal Hotspot.

On an iPhone, the Personal Hotspot times out and goes to sleep when no devices are connected to it. Before starting the vehicle, disable the hotspot and reenable it through the iPhone Settings app. This approach worked flawlessly on a two day, 1,000 mile trip with seven fuel stops, one overnight stop and several random health stops.

Running Raspberry Pi's in headless mode requires WIFI to be configured in advance. For example, put each phone or tablet into mobile hotspot mode and then configure the Raspberry Pi to automatically connect to them before using the logging system in a vehicle.

A possible solution is to use add a GPS receiver to the Raspberry Pi to add Stratum-1 NTP Server capability to the Raspberry Pi. This works in remote environments were mobile wireless signals are unavailable. It also requires less work on behalf of the vehicle operator.

The solution currently in use a Raspberry Pi UPS HAT with a built-in real-time clock. This option, using the Raspberry Pi UPS HAT had been working well with no operator intervention required. However, once the Lithium battery got funky, the built-in real-time clock often lost power. Power loss resets the clock to 1970 almost every time the system boots.

In environments where the following are unavailable:

The function get_output_file_name() from Telemetry System Boot and Application Startup Counter has been added to obd_logger and obd_tester to ensure the creation of data files with unique invariant identifiers. These file names assure that data files can be processed in the order they were created. For the file naming to work properly, obd_logger and obd_tester need to be started through the bash startup programs found in telemetry-obd/bin/ named obd_logger.sh and obd_tester.sh.

Data timestamp information may still need downstream processing using embedded GPS data to recalibrate system timestamp data. Examples for this type of downstream processing can be found in the obd_log_to_csv package. See Telemetry OBD Data To CSV File.

Running Raspberry Pi In Vehicle

Getting the Raspberry Pi and OBD interface to work reliably in running vehicles turned out to be problematic. The initial setup used a USB OBD interface. The thinking was that a hard wired USB connection between the Raspberry Pi and the ODB interface would be simpler and more reliable. On the 2013 Jeep Wrangler Rubicon, this was true. The 110 VAC power adapter was plugged into the Jeep's 110 VAC outlet.

However, both the 2017 Ford F-450 Truck and 2019 Ford EcoSport SUV wouldn't power the Raspberry Pi if it was connected via USB to an OBD interface. It didn't matter if the Pi was plugged into 12 VDC or 110 VAC outlets. It wasn't until a 600 Watt Sine Wave Inverter was used to power the Raspberry Pi that the underlying problem became clear. The inverter has GFCI circuitry that tripped soon after the Raspberry Pi started communicating through USB to the OBD interface. There wasn't adequate electrical isolation between the vehicle OBD port and the Raspberry Pi.

Given that electrical isolation was an issue, it became clear that wireless connection between components would be necessary. This is why Bluetooth became the preferred solution.

Depending on the power supply powering the Raspberry Pi, there may also be issues with power when powering the Pi directly through the vehicle. Switching to a portable 12 VDC battery also made the solution more stable.

Driver Responsibilities

Run Cycles

Before turning on the ignition:

After vehicle is running:

After turning off the vehicle:

Software Testing

Software was tested manually using a Freematics OBD-II Emulator (vehicle emulator) as well as in actual vehicles. The test environment is as follows:

Run Cycles

The Freematics OBD-II Emulator does not cover all available OBD commands. This is especially true for the additional commands provided through add_commands.py. Be aware that actual vehicle responses may not match the software. Also be aware that test code coverage in add_commands.py is sketchy at best. Your mileage may vary.

Manufacturer Warranty Information

The 2019 Ford EcoSport manual has the following statement with respect to aftermarket OBD devices:

"Your vehicle has an OBD Data Link Connector (DLC) that is used in conjunction with a diagnostic scan tool for vehicle diagnostics, repairs and reprogramming services. Installing an aftermarket device that uses the DLC during normal driving for purposes such as remote insurance company monitoring, transmission of vehicle data to other devices or entities, or altering the performance of the vehicle, may cause interference with or even damage to vehicle systems. We do not recommend or endorse the use of aftermarket plug-in devices unless approved by Ford. The vehicle Warranty will not cover damage caused by an aftermarket plug-in device."

You use this software at your own risk.

LICENSE

MIT License