Followup from this thread and now pimped up to be of actual use on the infamous Pixl.js.
Hardware
cheap BLE 4 enabled set of 4 thimble-sized tire pressure sensors (search for TPMS - V11 on eBay or Aliexpress):
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:
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
Followup from this thread and now pimped up to be of actual use on the infamous Pixl.js.
Hardware
Software
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:The sensor seems to:
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 pressureminBar
and a minimum battery percentageminBat
.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