TPMS - Tire Pressure Monitoring System

Posted on
  • Followup from this thread and now pimped up to be of actual use on the infamous Pixl.js.

    Hardware

    1. cheap BLE 4 enabled set of 4 thimble-sized tire pressure sensors (search for TPMS - V11 on eBay or Aliexpress):

    2. Pixl.js module

    Software

    // define your tires here (2-4)
    const tires = {
      '207bdd': {
        name: 'FL',
        minBar: 7.0,
        minBat: 20,
      },
      '30bc95': {
        name: 'FR',
        minBar: 7.0,
        minBat: 20,
      },
      '10ba52': {
        name: 'R',
        minBar: 5.5,
        minBat: 20
      }
    };
    
    const ALARM_BAR = 0x01;
    const ALARM_BAT = 0x02;
    const ALARM_LEAK = 0x04;
    const ALARM_TIME = 0x08;
    
    var dirty = 1;
    const timeout = 120;
    
    var flashTimer;
    
    function setFlash(on) {
      if(on) {
        if(flashTimer == undefined) {
          flashTimer = setInterval(function(){
            digitalPulse(LED1, 1, [100]);
          }, 1000);
        }
      }
      else {
        if(flashTimer) {
          clearInterval(flashTimer);
          flashTimer = undefined;
        }
        LED1.reset();
      }
    }
    
    
    function analyze() {
      var flash = 0;
      for(let id in tires) {
        var alarm = 0;
        var d = tires[id];
        if(d.t > 0) {
          // underpressure
          if(d.bar < d.minBar) {
            alarm |= ALARM_BAR;
          }
          // battery low
          if(d.bat < d.minBat) {
            alarm |= ALARM_BAT;
          }
          // signal loss
          if(d.t + timeout < getTime()) {
            alarm |= ALARM_TIME;
          }
          // leak
          if(d.leak) {
            alarm |= ALARM_LEAK;
          }
        }
        else {
          tires[id].t = getTime();
        }
        if(alarm > 0) {
          flash = 1;
        }
        tires[id].alarm = alarm;
      }
      setFlash(flash);
    }
    
    function out(text, x, y, inverse) {
      if(inverse) {
        g.fillRect(x, y, x + g.stringWidth(text) + 2, y + g.getFontHeight() - 1);
        g.setColor(0, 0, 0);
      }
      g.drawString(text, x + 1, y);
      g.setColor(1, 1, 1);
    }
    
    function draw() {
      g.clear();
      var y = 0;
      out('TPMS', 0, 0, 1);
      for(let id in tires) {
        y += g.getFontHeight();
        var d = tires[id];
        g.drawString(d.name, 0, y);
        if(d.bar != undefined) {
          out(d.bar.toFixed(1), 25, y, d.alarm & ALARM_BAR);
          out(d.temp.toFixed(1) + '°C', 55, y);
          out(d.bat + '%', 95, y, d.alarm & ALARM_BAT);
        }
        else {
          out('...', 50, y);
        }
        if(d.alarm & ALARM_TIME) {
          out('?', 120, y, 1);
        }
        else if(d.alarm & ALARM_LEAK) {
          out('!', 120, y, 1);
        }
      }
      g.flip();
    }
    
    function decodeData(device) {
      var d = new DataView(device.manufacturerData);
      var id = d.getUint32(2).toString(16).slice(-6);
    
      if( tires[id] != undefined ) {
        tires[id].t = getTime();
        tires[id].bar = d.getUint32(6, 1) / 100000;
        tires[id].temp = d.getUint32(10, 1) / 100;
        tires[id].bat = d.getUint8(14);
        tires[id].leak = d.getUint8(15);
        dirty = 1;
      }
    }
    
    
    function onInit() {
      require("FontDylex7x13").add(Graphics);
      g.setFontDylex7x13();
      analyze();
      draw();
    
      NRF.setScan(function(device){
        decodeData(device);
      }, {
        filters:[{
          services: ['fbb0']
        }]
      });
    
      setInterval(function(){
        if(dirty) {
          analyze();
          draw();
          dirty = 0;
        }
      }, 5000);
    }
    
    onInit();
    

    Function

    The sensors do not require a connection or traversing Services and Characteristics.
    All the data is just put into 16 bytes of manufacturerData found in each broadcast:

    • Bytes 0-5: pevice ID
    • Bytes 6-9: pressure (Pascal, Bar * 100000)
    • Bytes 10-13: temperature (°C * 100)
    • Byte 14: Battery (%)
    • Byte 15: Flat (flag - 0=OK, 1=detected)

    The sensor seems to:

    • Sleep when no pressure detected (no transmissions at all)
    • Transmit as soon as a change appears (with a few seconds delay)
    • Transmit at least every 60 seconds when pressure detected

    The set contains a card showing the last 6 hex digits of each device.
    You can copy these digits (lower case) to the object on top of the code.
    Everything from 1-4 wheels is possible. I only use 3 wheels because I own a Velomobile, but everything from unicycle to car is possible.

    For each wheel you can define an individual name, a minimum pressure minBar and a minimum battery percentage minBat.

    Underpressure, low battery, loss of signal (stale data for more than timeout seconds) and leaks are detected.
    There is a flag (I called it leak that seems to show 1 when the pressure is starting to decrease at a certain rate and/or the temperature is rising but the pressure is not).

    When any issue is detected, LED1 begins to flash and the value gets inverted.
    This is how it looks:


    1 Attachment

    • IMG_1467.JPG
  • Wow, that looks excellent!

    Where do you think they measure the temperature? I wonder how much it actually reflects the gas temperature in the tyre...

  • The sensor sits on the valve top. So it is mainly the outside temperature, not the gas temperature...
    I think it is more about compensation. If you change from a cool underground car park to hot summer roads the temperature rises and so should the pressure.
    If the pressure stays the same but the temperature rises this may be a leakage so the alarm goes off. Thats what seemed to be happening once during testing when I covered the sensor with my (warmer) fingers.

  • Update:
    After testing for a few weeks there were issues with the battery life. In the beginning sensors worked for days without noticeable battery wear.
    Then some other sensors started failing after only 1-2 days, eating batteries like candy.
    I bought another (identical) set and tested indoors with a modified aluminium water bottle and all was fine. Once the sensors were installed on the wheels some of them also started to drain battery.

    Taking the first set indoors again and counting messages showed that some sensors (the ones with the battery issues) sent far more messages than the others.
    I don't know if this is a hardware issue or if there is more about the protocol than I first thought.

    But how can they run dry when there is not a smartphone around? This is probably the case in 90% of the time...

    I just ordered a different/updated version (BLE 5.0) now and have a look at their protocol and battery lifetime. The outer caps just look similar. Stay tuned...

  • Thanks for the update! That's a shame...

    I guess it's possible that a phone app might connect and somehow configure them for a lower power operation mode?

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

TPMS - Tire Pressure Monitoring System

Posted by Avatar for ChristianW @ChristianW

Actions