Skip to main content
Each entry in the JSON-formatted address map corresponds to a data field within a CAN frame on the actual device. Every entry in the address map must contain several required and optional parameters, which are described below. The final address map should cover all relevant CAN data fields for the device.

Understanding CAN Frames

CAN (Controller Area Network) communication uses frames to transmit data. Each frame is identified by a CAN ID and contains up to 8 bytes of data. Data fields within a frame are defined by their byte position, bit position, and bit length, allowing for precise extraction of values from the CAN frame payload.

Naming Conventions

While not mandatory, it is recommended to adopt the following naming conventions for clarity and usability:
  • Write Operations: Prefix names with control. to indicate that the field is used for controlling the device.
  • Read Operations: Prefix names with measure. to signify that the field is used for measurement purposes.
  • Fault and Warning Fields: Use the prefixes fault. or warning. for fields that monitor faults or warnings. This helps in generating appropriate Telegram notifications and alerts for the system.
See the example CANbus address map below for naming conventions.

Required Parameters

Each register in the address map must include the following parameters:
canId
int
required
The CAN identifier for the frame containing this data field. The canId should be specified in decimal format.Example: 100
startByte
int
required
The starting byte position within the CAN frame data payload (0-7).Options: 0 - 7
startBit
int
required
The starting bit position within the start byte (0-7).Options: 0 - 7
bitLength
int
required
The total number of bits for this data field (1-64).Options: 1 - 64
name
string
required
A unique name for the data field, representing the measurement point read from or written to the CAN device.Example: measure.ports.port1.voltage
datatype
string
required
The data type of the value.Options: int8 | uint8 | int16 | uint16 | int32 | uint32 | float32 | string32 | int64 | uint64 | float64

Optional Parameters

These parameters are not necessary for every entry but can be included as needed:
scaling
int | float | string
The scaling factor to apply to the CAN data field’s return value or the value being written.Example: 0.1
offset
int | float
The offset to apply to the CAN data field’s return value or the value being written.Example: 10
direction
string
The direction of the power or current flow on a port of the device. When the direction is set to output, the register value will be inverted.Options: input | output
minimum
int | float
The minimum value of the register. For write register, setting the minimum value prevents you from writing a value lower than the minimum value. The control command will be blocked by the Power Platform.Example: 0
maximum
int, float
The maximum value of the register. For write register, setting the maximum value prevents you from writing a value higher than the maximum value. The control command will be blocked by the Power Platform.Example: 10
map
object
Indicates if mapping should be applied to the return value or the value being written.Example:
{
  "map": {
    "type": "bitwise"
  }
}
byteOrder
string
Specifies the byte order notation.Options: little | big
By following the naming conventions and adding all the required and optional parameters to each CAN data field, you have created a complete address map for the controller to communicate and interact with the device. The final JSON file should be saved with a unique name and a .json extension. For example, canbus_device_address_map.json.

Example

canbus_address_map.json
[
  {
    "canId": 100,
    "startByte": 0,
    "startBit": 0,
    "bitLength": 16,
    "name": "measure.ports.port1.voltage",
    "datatype": "uint16"
  },
  {
    "canId": 100,
    "startByte": 2,
    "startBit": 0,
    "bitLength": 16,
    "name": "measure.ports.port1.current",
    "datatype": "int16",
    "scaling": 0.1,
    "offset": 0
  },
  {
    "canId": 200,
    "startByte": 0,
    "startBit": 0,
    "bitLength": 8,
    "name": "control.ports.port1.method",
    "datatype": "uint8",
    "map": {
      "type": "value",
      "0": "idle",
      "1": "net",
      "2": "GPWR",
      "3": "FPWR"
    }
  },
  {
    "canId": 300,
    "startByte": 0,
    "startBit": 0,
    "bitLength": 16,
    "name": "fault.active",
    "datatype": "uint16",
    "map": {
      "type": "bitwise",
      "0": "Overvoltage",
      "1": "Undervoltage",
      "2": "Overcurrent",
      "3": "Overtemperature",
      "4": "Communication error",
      "5": "Internal fault"
    }
  }
]