Skip to content

NH-RedAnt/ledTPMS2

Repository files navigation

BLE TPMS Arduino Monitor/Logger

Bluetooth Low Energy(BLE) Tire Pressure Monitoring System (TPMS).

Motivation

In 2023 I toured over 36,000 miles, all over North America and wore out a number of tires. This was an epic year for my riding, normally I cover 12,000 miles in a year.

Going through so many tires I wondered if I was running the appropriate pressure for the extremes I rode in. The pressure when checked seemed to vary too much and I started to feel certain I was under inflated for the full touring load I was traveling with.

What I needed a way to monitor the tires while touring, better yet a logger that could graph them after riding.

Solutions

First borrowed a set of tire caps from a friend that I could never get to pair with my phone. After reviewing various apps, I took my chances on a set of four newer BLE TPMS caps on Amazon sold by LeePee.

The Android app suggested by LeePee for their BLE TPMS tire caps only provided current values (no history). I found a few other OpenSource android apps that worked with these tire caps. The OpenSource apps worked better, but I found nothing that would plot or capture data during my rides.

Next I did the obvious and wrote an app for my Android Phone. Extending an example BLE scanner to capture and plot TPMS data. But it only worked while the screen was on, so I moved on before learning how to save the captured data to a file.

Seeing that ESP32s3 hardware supported BLE, I decided to experiment with ESP32s3 hardware. I've wanted to explore Arduino divice more anyway.

I slowly learned how to program the ESP32s3 and continued adding more features until I finally arrived at a viable solution for my needs. Like most software, it'll never be finished. I already want to port it to an ESP32s3 with a touchscreen graphics. And why not capture a GPS track...

Hardware

LeePee BLE TPMS valve stem caps

TPMS valve stem caps are marketed under a variety of brands and names. It took the chance on a newer version sold on Amazon be LeePee. I purchased a set of 4 valve stem caps (for a car) for $49. Not sure why you would, but a set of 2 motorcyle caps can be purchased for $39.

Amazon link: https://a.co/d/7M1FDxD

Because I have 4 TPMS monitors, my code monitors two motorcycles. My bike is the primary but my wife's bike is also montored when in range. Monitoring works in the garage and while we ride, at normal riding distances. In fact the TPMS BLE devices can be read anyplace in my house, I consider the range to be excellent.

The LeePee BLE TPMS tire caps transmit current state every couple of minutes. All the time, not just while moving. They will update more frequently if conditions change. So more data will occur when in stop and go traffic. Yes motorcycle tires don't warm up on normal cornering (like the flex on a car), but they do flex and warm up a lot on braking and acceleration. Now I know that.

Their data is part of a manufagture payload in their broadcast. They don't show up like attributes of a BLE service.

ESP32s3 hardware

Most ESP32s3 hardware will work. I used the ESP32-s3-zero for this project, but I also have their ESP32-s3-touch128 board, that I hope to build an LBGL touch GUI for.

The code

my lack of style

Most of my coding has been in python, so my C/C++ is a bit rusty. Your welcome to not like my sytle. I'll admit it's not polished and probably doesn't conform to anyones standards. I'm uncomfortable being a "good example", but more than happy to have better solutions suggested. Equally as happy to not impliment anything I don't feel is actually better.

Since I have ideas for many projects, I've attempted to create classes that I can reuse. I've attempted to drive functionality from data. Sometimes this adds unnecesary complexity. The code is not yet "done". Currently the configuration data comes from .h definitions. Eventually I'll read them from YAML files and provide configuration interfaces. I moved onto something else once I had the code functional for my needs. Eventually I return to it.

Program flow

Logging is enabled on the serial console. Status data is logged while runing.

Upon boot multiple attempts are made to join WiFi networks (connection data defined in "WifiTime.cpp" as "AP_list"). Led lit a dim yellow while seeking for WiFi. Dim green once WiFi connected, brighter Green after NTP time is set. When Network Time Protocal (NTP) time was found the log file will use a name like: "/dat/TPMS_2024-11-14T13_38_24EST.dat" using the ESP boot time for the entire session. Without a valid datetime the log file used is: "/dat/TPMS_Raw.dat" (a default defined in "Tpms.cpp"). Data is appended to the file when the buffer is full (about 50 minutes for 2 tires). Effectively storing data for long trips, and not a quick joint down the street that would just burn up write cycles on the flash memory. The Touch sensors can be used trigger save events.

After NTP has succeed (or failed) the WiFi network is shutdown, so that the shared antenna can be used for BLE.

If no LittleFS file system exists, the code attempts to create one and the following folders: /dat, /www, /www/js. The current dat logger file and contents of /dat is printed to the serial log.

Normal BLE scans are done by a TpmsScan class (defined in "ledTPMS2.ino"). A new scan is started every 30 seconds. The LED is turned OFF when the scan starts. When a known BLE device broadcasts a TPMS payload the LED is lit with that devices predefined color. These colors identify each TPMS cap as it reports in, and are also used to indicate which valve stem cap is outside of it's defined range. Under normal conditins each BLE cap reports once every 180 seconds. They may report more often if conditions change. If multiple caps report during a single 30 seconds scan window the led will show the last one, but update instantly as each one comes in. note: The current scanning method only captures the first time a BLE device broadcasts, so only the first broadcast in each 30 second interval is reported. Meaning at tramatic event causing multiple reports could be ignored until the next 30 second interval!

If a TPMS cap goes outside of it's defined range (as defined in "TireCaps.h") the LED will pulse a warning color followed by the tire's HI or LO waring color.

Two Capacitive Touch sensors are currently monitored by the code.

T7 causes the current data cache to be appended to the LittleFS dat file. Indicating this action by a pulsing white LED, then pulses yellow, turns solid RED during save and turns GREEN once saved.

T2 Stops BLE scanning, saves out the current cache to the LittleFS dat file, starts back up the WiFi connection from boot and runs a web server. While it does this the LED pulses a magenta color. Hitting the Touch2 sensor reverses the process by taking down the web services and WiFi, and returns to BLE scanning.

The web interface supports downloading and plotting the raw data files. As well as drag and drop updating of the .html and .js files into the /web and /web/js folders. Note that a clean ESP32s3 install will create the /web/ and /web/js foldings but they will not have any content. So no plots until you: use the default web server to drag and drop the files from this codes bases "web/" folder to the same location the LittleFS /web/.

www/
  index.html admin.html chartjs.html
www/js/
  struct.min.js

Note: The web server only runs when started with Touch2. When running there is no protection, anyone may upload or delete your LittleFS files.

Build

For this project I used the Ardiuno IDE appimage (v2.3.3 & V2.3.4) on an Ubuntu Linux (release 24.04) desktop.

Two python scripts helped to test the web code and generate CSV files from the raw data.

File Overview

For storage sizing I opted to leave the TPMS data in it's RAW binary format, adding in some of my own. That my not have been the best choice, but it was my choice.

/dat/

Storage folder saved to about every 50 minutes. Filenames used when the NTP service was availble at boot will use a format like: "/dat/TPMS_2024-11-14T13_38_24EST.dat".

When datetime is not know the log file defaults to: "/dat/TPMS_Raw.dat". The time data logged is from device boot. So a TPMS_Raw.dat file used multiple times will have times that increase, and then drop low again on a different session. Those logged sessions could be seconds or months apart, no way to tell without the datestamps.

python/app.py python/dat2csv.py

Included are two python scripts that helped me develop the web graphing and can convert raw data files to CSV data.

ledTPMS2.ino

Main Arduino sketch. Basic config/setup, program flow, and inclusion of all the following classes.

WifiTime.cpp WifiTime.h

Configure your WiFi SSID(s) and password(s) in "WifiTime.cpp". I use my home AP, then phone hotspot, and a very unlikely connect attempt on an open WiFi.

LedUtils.cpp LedUtils.h

Some unnecessarily complex LED code I created to do nice led fades. Pull from another code where it was used to do more.

Web.cpp Web.h

The Web server classes that I modified to handle my web needs. When not /web data exists, the top level URL is a redirect to the Upload page. Allowing the drag and drop transfer of /web file from this repo to new ESP LittelFS instances. This must be done once or you don't get the data downloading and plotting features of the web interface.

Note: The javascript plotting libary is loaded from the network, so you will need access to the internet for at least the first plots, to cache the library used.

LFS_utils.cpp LFS_utils.h

A couple routines used to setup LittleFS and list files in /dat/.

TireCaps.h

Configuration data to define your TMPS valve stem caps BLE addresses, LED colors, target_psi and range multipliers.

Note that all of the attributes starting with "last_", "min_", or "max_" are stored values during data capture. You want to change "target_psi", "psi_lo_m" and "psi_hi_m" to set the range. The normal PSI range is FROM target_pspsi_lo_m TO target_pspsi_hi_m. Defaults from .9 (90%) and 1.20 (120%) of target_psi.

Tpms.cpp Tpms.h

These files define the TPMS Raw storage structures, and decoding routines.

builtinfiles.h

This file contains the "Upload page" HTML content that enables drag and drop uploading of "/web" data below.

/web

The following files should be copied to the LittleFS /web/ folder. You will need to use Touch2 button to start the web server. Then use a web browser to drag and drop these files onto the ESP32s3 LittleFS /web storage.

www/
  index.html admin.html chartjs.html
www/js/
  struct.min.js

Configuration

Arduino IDE building for "WaveShare ESP32-s3-zero"

Before compile and flash

  1. Edit WiFi settings in "WifiTime.cpp" variable "AP_list".
  2. Edit "TireCaps.h" variable "tire_groups" to define you "vehicle(s)". a. Primary (grp_id=0) BLE data older than 5 minutes is reported as an error. Other groups are optional so their absence is not reported as an error.
  3. Also in "TireCaps.h" edit the variable "tire_caps" to include your BLE specific data. a. The range is defined by the tires "target_psi", and it's "psi_lo_m" and "psi_hi_m". Default psi_lo_m is 0.9 (warn when below 90% of target_psi). Default psi_hi_m is 1.20 (warn when 20% above target_psi).

After first boot

  1. Boot up and watch the logs or LED to confirm you have a working WiFi.
  2. Use the Touch2 capacitive button to start the web server.
  3. Connect to the web server with a browser.
  4. Drag the contents of this repos /www folder to the corresonding location on the ESP LittleFS file system.

Misc

ESP32-s3-zero case

I created a tiny 3D printable case to protect this device. It has two holes lined up wiht Touch2 and Touch7 pins. A 22 gauge solid core bare wire can be slid through the case holes and clipped off. A capacitive touch even can then be tranfered by touching the case at one of those two locations. I'll include the STL file.

The case has a 2mm hole above the LED light. A 2mm fiber optic cable can be slid into this hole to extend the visability of the LED outside the case. Cut flush it just protects the LED and brings it's light out of the case. Slightly proud and rounded it becomes visible in in one hemishere. Leaving 4-5mm sticking out makes it much more visible. Alternatively the entire case could be safely hidden away and just run the end of fiber to someplace where you can see it.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published