Although the Pilot allows for many CAN messages to be configured, there are often downstream constraints (data logger memory or CAN licences etc) that make it advantageous to "squeeze" values into the smallest space possible. If you fail to match the possible range of input data to the limited range of the output (or receiver) then the resultant data can be confusing to diagnose. A simple example is shown below; the input data, green, is a sine wave centred on 250 ranging from 0 to 500. However, if we try to send that in a single byte the value will not have the higher bits and the resultant data (logged or otherwise) will suffer confusing transitions as shown by the red line below.
Solutions are given below.
Error Values
Pilot and many sensors output distinct error values when no other data is available. Caution must be taken to make sure that the error is still unique after the bit-count has been reduced, as often the error value is placed at an extreme end of the source bit range e.g. for byte values it is common to use 254 or 255 to represent an error state. Sometimes the error value is still unique but may not easily resemble the original if you don't account for it. Error values are normally identifiable by staying at a fixed value for long periods.
Range Limiting
If you have a sensor providing a range value in centimetres that can vary from 0cm to 400cm. This range is larger than be stored in a single byte. But if might not be of interest that someone is over 100cm away (i.e. they are not in arms reach) then you may use the maths Upper Limit. If you set the limit to 100 and then select Truncate you can treat 100 as a "out of range" value. You can now send this value as a single byte.
Offsets
Sensors often use a decade multiplier to provide a value with one or more decimal point. A common example is body temperature - whole numbers do not give enough detail, you need at least tenths of a degree to be useful. So a common technique is for the sensor to send the number multiplied by ten or hundred. For example, the sensor may send 375 for 37.5C which could be sent as-is by the Pilot - but this requires 16 bits (8 bits topping out at 255). However, we are only interested in temperatures between 35C to 41C (getting anywhere near these is a medical emergency). If expressed as 350 to 450 then this is a range of 100 - we know 100 fits into a byte with plenty to spare. So one solution is to apply an offset of -350 so the output will vary between 0 to 100 and can be sent in a byte. The other end just needs to reverse the offset.
Reducing Accuracy
Following on from using Offsets, if we were receiving a room temperature reading that is provided as a decade-multiplied value it might vary from 60 to 400 (i.e. 6C to 40C). The range is still larger than a byte so an offset can't help us. However, we can apply a divider of 10 as knowing the temperature to a whole degree may be accurate enough; 6 to 40 easily fits in a byte.
Reducing Byte Count
If a sensor reports a value as a 24 bit value, this can represent a value between 0 and 16777215 (224). If this digital value represents a 12 volt battery level then the accuracy would be around the microvolt level. If you only really need to know that the battery is fully charged then you could get away with reducing the value to 8 bits, which would still give a reading of steps of roughly 50millivolts. To do this you can just divide the value to a lower range accepting the loss of accuracy. The amount you divide by depends on all the limits but in order to reduce byte count the following table can be used.
Divider | Input is 1 byte (8 bit) | Input is 2 bytes (16 bit) | Input is 3 bytes (24 bit) | Input is 4 bytes (32 bit) |
Required output is 1 byte (8 bit) | Not Required | 256 | 65536 | 16777216 |
Required output is 2 bytes (16 bit) | Not Required | Not Required | 256 | 65536 |
Required output is 3 bytes (24 bit) | Not Required | Not Required | Not Required | 256 |
Required output is 4 bytes (32 bit) | Not Required | Not Required | Not Required | Not Required |