Brightwater TPMS CAN

From Autosport Labs
Jump to: navigation, search

About Brightwater TPMS

The Brightwater TPMS is a tyre pressure monitoring system for use on motor sport and other off highway test vehicles, the system is not certified for use on road vehicles. The system comprises a number of wheel mounted sensors and a vehicle mounted data receiver. The sensors continually monitor tyre pressure and temperature and transmit this data by low power radio to the receiver mounted inside the vehicle. This is connected to the vehicle system by CAN or RS232 interface providing pressure, temperature, and sensor diagnostics for each tyre.


Brightwater sensors are produced with different mechanical housing designs making them suitable for use on a wide range of wheel rim types.

Example sensor types

Each sensor has a unique electronic serial number, serial numbers are assigned to each customer, each sensor is assigned to a corner position on the vehicle. This allows the receiver to correctly identify each sensor transmission and assign the pressure and temperature data to the correct wheel regardless of how many wheel sets are being used. The system is supplied pre-configured, so it is not normally necessary to modify the system setup.


The Brightwater TPMS receiver monitors and decodes the sensor messages. Data for each wheel position on the vehicle is then passed to the logging system by CAN or RS232 interface. The update rate is determined by the sampling strategy that was specified for the sensors, e.g. 1Hz transmit interval. “BW TPMS Monitor” is a PC software utility that allows sensor data to be directly monitored and for changes to made to the receiver operation.

Installation VS50 type



  • Pin 1 = Power in (+8V to +24V), 40mA
  • Pin 2 = Power in 0V
  • Pin 3 = Receiver RS232 TX
  • Pin 4 = Receiver RS232 RX
  • Pin 5 = CAN Lo (must have termination 120R resistor if not connected) Pin 6 = CAN Hi

Fitting The Supplied Valve To The Wheel Rim

The valves with the VS50 sensors conform to the European Tyre and Rim Technical Organisation (E.T.R.T.O.) Standard Annex H.17 for valve holes of 11.3mm diameter (typical for production type alloy wheels). A copy of the page from the ETRTO standard showing the dimensioned drawing of the valve hole is attached. If necessary, consult with your wheel manufacturer as to the suitability of your rims to the ETRTO valve hole standard. The sensor uses either an external whip antennae or an integral antenea. Care must be taken to ensure the whip antennae is not damaged or traped under the tyre bead. The integral antenna uses the valve stem and connects by conductive paint under the sensor mounting screw, take care not to damage this painted area.

  • Insert the valve through the valve hole
  • Replace the washer and nut and finger tighten.
  • Note: The orientation of the nut must be as shown
  • Note: There are two washers supplied. Chamfered 45° for chamfered valve holes and a non-chamfered 90° for non-chamfered valve holes.
  • Place the steel rod into the hole on the side of the valve base to prevent rotation during tightening
  • Tighten the nut to a torque setting of: 4 +/- 0.5 Nm

Fitting The Sensor Onto The Valve

Secure the sensor to the valve using the T-20 Torx screw, supplied

  • Fit the sensor concave section to the valve convex section
  • Assemble the Torx screw and captive washer. Do not tighten at this stage, leave loose so that the sensor can move
  • Position the sensor housing so that the feet rest on the wheel rim
  • Tighten the Torx screw to a torque setting of 4 +/- 0.5 Nm
  • Note: The Torx screw has thread-locking compound on it. More compound must be added if removed and refitted.
  • Sensors weight approx 25g, and so balancing is achieved with normal balancing procedures.
  • Caution should be taken when mounting the tyres to the rims to avoid damage to the sensor or antennae.

Sensor Battery Maintenance and Replacement

The battery life is dependant on the number of times the sensor transmits. The do not transmit until the tyre is pressurised, this helps to prolong battery life. We recommend that the wheels are stored deflated or at a pressure below the sleep mode pressure threshold stated for the sensor type you have purchased. After a period of use, the battery fitted to the sensors will fail. You should then return the sensors for a battery change and calibration check. Changing of the battery should only carried out by the factory or autherised service agent, as permanent damage can be caused if the correct procedures are not taken.

CAN Specification

  • CAN 2.0 A
  • Motorola Format
  • 8 bytes are sent. Each byte has 8 bits.
  • Bit Rate 1Mb/s (Option 500Kb/s)
  • Message Identifier - 11 bit (defaults, user programmable)
  • Each corner has its own message own identifier, although all corners could be set to the same identifier and the corner information decoded from byte 7
    • Front Right 5A0
    • Front Left 5A1
    • Rear Left 5A3
    • Rear Right 5A2

Message Format

Byte Number Description Data Format
1 ID high byte Team Code in hex
2 ID low byte Sensor ID in hex
3 Pressure high byte 15 bit Pressure in psi (abs) (x 100(dec)) is sent in in these two bytes - see below
4 Pressure low byte
5 Temperature Temperature (+40°C) in °C. Subtract 40 decimal for true temperature.
6 Infra red Temperature Temperature (+40°C) in °C. Subtract 40 decimal for true temperature.
7 Corner/Status flags See below for description
8 Sensor TX count A rolling counter 0-255 incremented every transmission in the sensor - see below

Corner Flags

Byte Number Type Data Format
7 Corner flags bits 0,1 give the corner position of the sensor as set up in the receiver ID library 00=FR, 01=FL, 10=RL, 11=RR.

Descriptions and examples

Status flags are only sent from the sensor when the TX count is 0 to 7 inclusive

Byte Number Type Data Format
7 Status flags bits 2,3 are sensor battery voltage flags - measured during sensor transmission.
 00=(>3.0V)  01=(2.7 to 3.0V),  10=(2.4 to 2.7V),  11=(<2.4V)
7 Status flags bits 4,5 are sensor over temperature flags
 00 = (<140°C),  01 = (>140°C),    11 = (>150°C)
7 Status flags bit 6 is unused at present
7 Status flags bit 7 is a flag to show that the sensor Status flags are enabled. Ignor the Status flags if this is not set.
3,4 Pressure Pressure in psi absolute (x100(dec)) is sent as a 15 bit number

eg byte 5 = 0F(hex), byte 6 = 82(hex) = 0F82(hex) = 3970 (dec) 3970/100 = 39.7psi (abs) If we assume air pressure is 14.7psi, then tyre pressure will be 39.7 - 14.7 = 25.0 psi

8 Sensor TX count The sensor increments a counter 0 through FF then back to 0 (hex) etc. every transmission it makes.

At the end of the sensor interval (e.g. every second) the transmitter sends a transmission 'burst' of 4 x transmissions of identical data - with the TX count incrementing each transmission. This TX count is sent along with the sensor data and can be used as an indication of lost receptions.

RaceCapture Integration

Lua Script (WIP)

Attention: This script has bad code,it is quick and dirty, framework part was modified as quick hack because at that time I thought that only 10 Virtual Channels are available. I will clean up the code soon.

Please, Check comments.

tickRate = 100
CAN_baud = 1000000
CAN_chan = 0
be_mode = 1

tireSetHack = 1

--addChannel( name, sampleRate, [precision], [min], [max], [units] )

tirePresFR_Id = addChannel("TirePressFR", 1, 4, 0, 50, "BAR")
tireTempFR_Id = addChannel("TireTempFR", 1, 2, 0, 200, "C")

tirePresFL_Id = addChannel("TirePressFL", 1, 4, 0, 50, "BAR")
tireTempFL_Id = addChannel("TireTempFL", 1, 2, 0, 200, "C")

tirePresRR_Id = addChannel("TirePressRR", 1, 4, 0, 50, "BAR")
tireTempRR_Id = addChannel("TireTempRR", 1, 2, 0, 200, "C")

tirePresRL_Id = addChannel("TirePressRL", 1, 4, 0, 50, "BAR")
tireTempRL_Id = addChannel("TireTempRL", 1, 2, 0, 200, "C")
tireSetChan_Id = addChannel("TireSet", 1, 0, 0, 4, "")
--format is: [CAN Id] = function(data) map_chan(<channel id>, data, <CAN offset>, <CAN length>, <multiplier>, <adder>)
--multiplier is 0.0006894759 because units are x100(PSI) so to convert those to bar we have to multiply it by 0.0689475729*0.01

CAN_map = {
[1440] = function(data) map_chan(tirePresFR_Id, data, 2, 2 , 0.0006894759, 0) map_chan(tireTempFR_Id, data, 4, 1 , 1, -40) end,
[1441] = function(data) map_chan(tirePresFL_Id, data, 2, 2 , 0.0006894759, 0) map_chan(tireTempFL_Id, data, 4, 1 , 1, -40) end,
[1442] = function(data) map_chan(tirePresRR_Id, data, 2, 2 , 0.0006894759, 0) map_chan(tireTempRR_Id, data, 4, 1 , 1, -40) end,
[1443] = function(data) map_chan(tirePresRL_Id, data, 2, 2 , 0.0006894759, 0) map_chan(tireTempRL_Id, data, 4, 1 , 1, -40) end


--Added logging 
function onTick()

--Part below as changed---
--===========do not edit below===========
function processCAN(chan)
        local id, e, data = rxCAN(chan,5000)
----****************HACK START***************------
        if tireSetHack == 1 then
        	if data[2] == 0 or data[2] == 1 or data[2] == 2 or data[2] == 3 then
        		setChannel(tireSetChan_Id, 1)
        	elseif data[2] == 4 or data[2] == 5 or data[2] == 6 or data[2] == 7 then
        		setChannel(tireSetChan_Id, 2)
        	elseif data[2] == 8 or data[2] == 9 or data[2] == 10 or data[2] == 11 then
        		setChannel(tireSetChan_Id, 3)
        		setChannel(tireSetChan_Id, 99)
----****************HACK END***************------

--  println("ID:" .." Byte[0]: "[1].." Byte[1]: "[2].." Byte[2]: "[3].." Byte[3]: "[4].." Byte[4]: "[5].." Byte[5]: "[6].." Byte[6]: "[7].." Byte[7]: "[8])
        if id ~= nil then
            local map = CAN_map[id]
            if map ~= nil then
--    println("in procesCAN map != nil")
    until id == nil

--Map CAN channel, little endian format
function map_chan_le(cid, data, offset, len, mult, add)
    offset = offset + 1
    local value = 0
    local shift = 1
    while len > 0 do
        value = value + (data[offset] * shift)
        shift = shift * 256
        offset = offset + 1
        len = len - 1
-- println("DEBUG: map_chan_be")
 setChannel(cid, (value * mult) + add)

--Map CAN channel, big endian format
function map_chan_be(cid, data, offset, len, mult, add)
    offset = offset + 1
    local value = 0
    while len > 0 do
        value = (value * 256) + data[offset]
        offset = offset + 1
        len = len - 1
--  println("DEBUG: inside while len > 0")
-- println("DEBUG: map_chan_be")
-- println("DEBUG: value: "..value)
-- println("DEBUG: mult: "..mult)
--    println("DEBUG: add: "..add)
    setChannel(cid, (value * mult) + add)

map_chan = (be_mode == 1) and map_chan_be or map_chan_le
initCAN(CAN_chan, CAN_baud)