Basics
RaceChrono Pro (v6.0 and later) allows users to enter freely typed equations for custom OBD-II channels and CAN-Bus channels.
- Case insensitive: Variables and functions in equations are case insensitive. It doesn’t matter if you write POW(2) , Pow(2) or pow(2).
- Decimal floating point values: 64-bit floating point value. A dot ( . ) is used as decimal separator. Comma ( , ) is reserved as function parameter separator. Constants are interpreted as floating point values only when decimal separator is included ( . ). Example: 12494.0
- Decimal integer values: 64-bit integer value. Example: 12494
- Hexadecimal integer values: 64-bit integer value. Denoted by 0x at start. Example: 0x30CE = 12494
- Spaces: Spaces can be used to make equations more readable, but they are not required anywhere.
- Brackets: Brackets can be used to mark precedence. For example:
(4 + 2) * 10 = 60
4 + (2 * 10) = 24 - Definition of true and false: In logical operations and functions, zero is always considered as false. Anything else is considered as true.
Operators
Normal C / C++ / Java style operators work, and the operator precedence is same as in these languages.
- Add
5 + 2 = 7 - Subtract
5 – 2 = 3 - Multiplication
5 * 2 = 10 - Division
5 / 2 = 2
5.0 / 2 = 2.5
5 / 2.0 = 2.5
Notice when dividing two integers, an integer rounded down will be returned. - Modulo
10 % 3 = 1
-10 % 3 = -1
10 % 3.5 = 3.0 - Equal to
11 == 12 = 0 (false)
11 == 11 = 1 (true) - Not equal to
11 != 12 = 1 (true)
11 != 11 = 0 (false) - Less than
11 < 12 = 1 (true)
11 < 11 = 0 (false) - Greater than
12 > 11 = 1 (true)
11 > 11 = 0 (false) - Less or equal to
11 <= 11 = 1 (true)
11 <= 10 = 0 (false) - Greater or equal to
11 >= 11 = 1 (true)
11 >= 12 = 0 (false) - Logical or
0 || 100 = 1 (true)
0 || 0 = 0 (false) - Logical and
10 && 100 = 1 (true)
10 && 0 = 0 (false) - Bitwise shift left
1 << 3 = 8 - Bitwise shift right
8 >> 3 = 1 - Bitwise and
15 & 8 = 8 - Bitwise or
8 | 4 = 12 - Bitwise xor
15 ^ 8 = 7
Variables and constants
- NaN
Not-a-number. Floating point value that will not be displayed in gauges and graphs. Can be used in place of an invalid value. - raw
Raw data output by the OBD-II PID or CAN-Bus PID. Usually you’ll extract bytes (or bits) from the raw variable to an integer, and then apply some maths over it. The following will extract first two bytes to an unsigned integer, and divides that by 100:
bytesToUint(raw, 0, 2) / 100.0
bytesToUint(0x0101FFFFFFFFFFFF, 0, 2) / 100.0
257 / 100.0 = 2.57 - A and R2
1st byte of variable raw. Same as bytesToUInt(raw, 0, 1) - B and R3
2nd byte of variable raw. Same as bytesToUInt(raw, 1, 1) - C and R4
3rd byte of variable raw. Same as bytesToUInt(raw, 2, 1) - D and R5
4th byte of variable raw. Same as bytesToUInt(raw, 3, 1) - E and R6
5th byte of variable raw. Same as bytesToUInt(raw, 4, 1) - F and R7
6th byte of variable raw. Same as bytesToUInt(raw, 5, 1) - G and R8
7th byte of variable raw. Same as bytesToUInt(raw, 6, 1) - H and R9
8th byte of variable raw. Same as bytesToUInt(raw, 7, 1)
Basic functions
These basic functions can be used everywhere equations can be written.
- bitsToUint(source, bitOffset, bitLength)
Returns unsigned integer value, extracted from the source value. Bit offset 0 is the bit with most significance (msb-0 and big-endian).
raw = 0x 00 11 22 33 44 55 66 77
raw = 00000000 00010001 00100010 00110011 01000100 01010101 01100110 0111 0111 (binary)
bitsToUint(raw, 24, 16) = 0011 0011 0100 0100 (binary) = 0x3344 = 13124 - bitsToInt(source, bitOffset, bitLength)
Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Bit offset 0 is the bit with most significance (msb-0 and big-endian).
raw = 0x00 11 22 33 44 55 66 77
bitsToInt(raw, 24, 16) = 0x3344 = 13124
and
raw = 0x001122B344556677
bitsToInt(raw, 24, 16) = 0x3344 – 0x8000 = -19644
- bitsToUintLe(source, bitOffset, bitLength)
Little-endian version of bitsToUInt. Returns unsigned integer value, extracted from the source value. Bit offset 0 is the bit with least significance (lsb-0 and little-endian).
raw = 0x01 23 45 67 89 AB CD EF
bitsToUintLe(raw, 28, 16) = 0xB896 = 47254 - bitsToIntLe(source, bitOffset, bitLength)
Little-endian version of bytesToInt. Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Bit offset 0 is the bit with least significance (lsb-0 and little-endian).
raw = 0x01 23 45 67 89 AB CD EF
bitsToIntLe(raw, 28, 16) = 0xB896 = 47254
and
raw = 0x01 23 45 67 89 AB CD EF
bitsToIntLe(raw, 28, 16) = 0x3896 – 0x8000 = -18282
- bytesToUint(source, byteOffset, byteLength)
Returns unsigned integer value, extracted from the source value. Byte offset 0 is the byte with most significance (big-endian).
raw = 0x0011223344556677
bytesToUint(raw, 3, 2) = 0x3344 = 13124 - bytesToInt(source, byteOffset, byteLength)
Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Byte offset 0 is the byte with most significance (big-endian).
raw = 0x0011223344556677
bytesToInt(raw, 3, 2) = 0x3344 = 13124
and
raw = 0x001122B344556677
bytesToInt(raw, 3, 2) = 0x3344 – 0x8000 = -19644 - bytesToUintLe(source, byteOffset, byteLength)
Little-endian version of bytesToUint. Returns unsigned integer value, extracted from the source value. Byte offset 0 is the byte with least significance (little-endian).
raw = 0x0011223344556677
bytesToUintLe(raw, 3, 2) = 0x4433 = 17459 - bytesToIntLe(source, byteOffset, byteLength)
Little-endian version of bytesToInt. Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Byte offset 0 is the byte with least significance (little-endian).
raw = 0x0011223344556677
bytesToIntLe(raw, 3, 2) = 0x4433 = 17459
and
raw = 0x00112233C4556677
bytesToIntLe(raw, 3, 2) = 0x4433 – 0x8000 = -15309 - bytesToFloat(source, byteOffset, byteLength)
Returns a floating point value, extracted from the source value. The source value is encoded in IEEE 754 format using the standard byte order. Only 32-bit and 64-bit values are supported, so the byteLength parameter is either 4 or 8. - bytesToFloatLe(source, byteOffset, byteLength)
Little-endian version of bytesToFloat. Returns a floating point value, extracted from the source value. The source value is encoded in IEEE 754 format using the reverse byte order. Only 32-bit and 64-bit values are supported, so the byteLength parameter is either 4 or 8. - float(arg)
Converts the argument to floating point. Examples: float(4) = 4.0, float(5) / 2 = 2.5 - int(arg)
Converts the argument to integer. Examples: int(4.0) = 4, int(5.0) / 2 = 2 - pow(base, power)
The first argument is a base value and second argument is a power raised to the base value. Examples: pow(x, y) = x y, pow(3, 2) = 3 2 = 9 - pow2(base)
The base argument is raised to power of 2. Examples: pow2(x) = x 2, pow2(3) = 3 2 = 9 - sqrt(arg)
Returns the square root of the argument. Examples: sqrt(x) = √x, sqrt(4) = 2 - lowPass(source, limit)
Returns source when source <= limit, otherwise NaN.
lowPass(100.0, 99.9) = NaN
lowPass(99.9, 99.9) = 99.9
lowPass(99.8, 99.9) = 99.8 - highPass(source, limit)
Returns source when source >= limit, otherwise NaN.
highPass(100.0, 99.9) = 100.0
highPass(99.9, 99.9) = 99.9
highPass(99.8, 99.9) = NaN - min(a, b)
Returns minimum value of the two arguments.
max(100.0, 99.9) = 99.9 - max(a, b)
Returns maximum value of the two arguments.
max(100.0, 99.9) = 100.0
- if(a, b, c)
Returns argument c if argument a is 0 (false), otherwise returns argument b.
if(1, 100, 101) = 100
if(0, 100, 101) = 101
- abs(source)
Returns absolute value of source.
abs(-10) = 10
abs(10) = 10
- scale(source, oldA, oldB, newA, newB)
Scales source value from range [oldA, oldB] to [newA, newB].
scale(50, 0, 100, 0, 200) = 100
scale(50, 0, 100, 1000, 2000) = 1500
scale(source, oldA, oldB, newA, newB) = ((value – oldA) / (oldB – oldA)) * (newB – newA) + newA
- isNaN(source)
Returns 1 (true) if the argument is not a number (NaN), otherwise returns 0 (false)
isNaN(100) = 0
isNaN(NaN) = 1
Extended functions
These extended functions can be used with features where channel data is available, such as the DIY Monitor API.
- device(deviceTypeIdentifier)
Selects a device with device type identifier. List of available device type identifiers can be found here.
device(gps) selects the GPS device
device(obd) selects the OBD-II device - channel(device, channelIdentifier)
Selects a channel from a device with a channel identifier, and returns the current value of the selected channel. List of available channel identifiers can be found here.
channel(device(gps), speed) selects the speed from a GPS device
channel(device(obd), accelerator_pos) selects the accelerator position from OBD-II device
Examples
- 2009 BMW 320d oil temperature
OBD-II PID: 0x2C100458
Source data: 0x49D4
Equation: bytesToUInt(raw, 0, 2) * 0.01 – 100.0
= bytesToUInt(0x49D4, 0, 2) * 0.01 – 100.0
= 18900 * 0.01 – 100.0
= 189.0 – 100.0
= 89.0 celsius - 2018 KTM 790 Duke engine RPM
CAN-Bus PID: 288
Source data: 0x23A0223344556677
Equation: bitsToUInt(raw, 0, 16)
= 9120 RPM