CAN communication

From wiki
Revision as of 16:40, 17 February 2024 by Johu (talk | contribs) (→‎SDO commands)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

The Revision 2 main board supports CAN communication. The CAN bus can be used for configuration and for obtaining values like voltages, input states etc. The CAN messages are configurable and can be adjusted to be compatible with existing equipment.

Since firmware 3.75 throttle and digital inputs can be controlled via CAN.

After firmware 5.27.R throttle, digital inputs, cruise speed and regen preset are no longer freely mappable due to safety concerns, see below.

Be aware that all CAN mapping uses decimal numbers. So COB ID 0x123 must be entered as 291

Inverter control via CAN - new!

As discussed here[1] the CAN communication was redesigned to improve operational safety. This will become effective with the first official release after 5.27.R

Now there is a fixed mapping for pot, pot2, canio, cruisespeed and regenpreset along with some alive counters and a CRC.

The COB Id is still freely configurable and defaults to 0x3F. It is advised to use a low ID value as low IDs have priority on the bus over high Ids.

The mapping is as follows [startbit, endbit]:

  • pot[0:11]
  • pot2[12:23]
  • canio[24:29]
    • cruise[24]
    • start[25]
    • brake[26]
    • forward[27]
    • reverse[28]
    • bms[29]
  • canrun1[30:31]
  • cruisespeed[32:45]
  • canrun2[46:47]
  • regenpreset[48:55]
  • cancrc[56:63]

pot is the value of the first throttle channel and its range is configured with potmin/potmax as before. pot2 is the value of the second throttle channel, its range configured via pot2min/pot2max and we strongly recommend to use dual channel throttle pedals and setting potmode to CanDual (or DualChannel if you choose to connect the throttle directly to the inverter). We also recommand to set up your throttle in a way that doesn't use the full range from 0-4095 but leaves at least 500 digit at either end (so 500-3600) to be able to detect cable issues between throttle and VCU (short to Vcc, loss of GND and other wire breaks)

cruisespeed is the setpoint for the speed control loop in rpm with a maximum value of 16383 rpm. Only applied if the cruise and forward bit is also set and the brake bit is reset.

regenpreset is a value from 0-100% that controls how much of your configured regen (offthrotregen or brakeregen) is actually applied

canrun1/2 are simple message counters that count from 0-3 and indicate that the message producer doesn't just send the same, stale, content over and over again.

cancrc is an 8-bit CRC, the lowest byte of the STM32 integrated CRC32 generator. It spans over all 8 bytes where the crc byte is set to 0. If you're on a non-STM32 platform you can use this C-implementation[2]. CRC checking is optional to remain compatible with "dumb" CAN converters. It can be disabled with parameter controlcheck=CounterOnly.

Controlling throttle via CAN - deprecated!

This no longer works starting v5.32.R! See above!

If you want to send the throttle and regen magnitude commands via CAN rather then via analog inputs you have to set "potmode" to "CAN" (=2). Next you have to map a CAN message to pot and optionally pot2. So say you have a digital throttle that sends values from 0 to 1000 for 0 to 100% travel on CAN-Id 100 in the first two bytes.

  • Configure potmin=0 and potmax=1000
  • Map CAN message to pot: can rx pot 100 0 16 1

CAN messages must be received every 500ms, otherwise throttle times out and is set to 0.

Controlling Digital IO via CAN - deprecated

This no longer works starting v5.32.R! See above!

6 signals, namely cruise, start, brake, forward, backward and bms can be controlled via CAN. The CAN message is ORed to the physical inputs so you can have mixed signals also. Digital CAN IO doesn't need to be explicitely configured, it works as soon as you map a CAN message to "canio". "canio" is bit-encoded:

  • Bit 0: cruise
  • Bit 1: start
  • Bit 2: brake
  • Bit 3: forward
  • Bit 4: reverse
  • Bit 5: bms

So say you have a BMS that transmits an over/under voltage bit on CAN Id 200, 2nd data bit

can rx canio 200 2 1 1024

Note the 1024x gain that shifts the bit into the correct position (5 fraction bits plus 5th data bit). In this case all other IOs remain traditional, only BMS is controlled via CAN. Note that you cannot map multiple CAN messages onto "canio" as they would overwrite each other.

If you have a managed to mangle all 6 bits into one message, say CAN Id 300, first 6 bits the mapping is done like so

can rx canio 300 0 6 32

The same timeout mechanism is used as for throttle control, so after 500ms with no message the CAN-mapped inputs are assumed off. Traditional inputs remain unaffected.

Setting and reading parameters via SDO

The abbreviation SDO is taken from the CANOpen protocol. It assigns a certain meaning to the 8 data bits of a CAN frame.

Note that SDO semantics (cmd) were changed since version 5.20.R of the inverter firmware. Old cmd value is in ()

Purpose CAN-Id Byte 1 (Cmd) Bytes 2-3 (Index) Byte 4 (Subindex) Bytes 5-8 (Data)
Set Value 0x601 0x23 (0x40) 0x2000 Value Index Value x 32
Set Value Reply 0x581 0x60 (0x23) 0x2000 Value Index Value x 32
Get Value 0x601 0x40 (0x22) 0x2000 Value Index don't care
Get Value Reply 0x581 0x43 0x2000 Value Index Value x 32
Abort - invalid index 0x581 0x80 Index of request Value Index Abort Code = 0x06020000
Abort - value out of range 0x581 0x80 Index of request Value Index Abort Code = 0x06090030
Set Param 0x601 0x23 (0x40) 0x21xx xx=MSB UID Param UID LSB Value x 32
Set Param Reply 0x581 0x60 (0x23) 0x21xx xx=MSB UID Param UID LSB Value x 32
Get Param 0x601 0x40 (0x22) 0x21xx xx=MSB UID Param UID LSB don't care
Get Param Reply 0x581 0x43 0x21xx xx=MSB UID Param UID LSB Value x 32

The value index must be determined by counting the output of the list command. E.g. "boost" at the very top has index 0, potnom has index 77. The indexes can change over firmware versions as new parameters are added somewhere in between.

The Get/Set Param commands use the unique parameter identifier assigned to each savable parameter. These do not vary between firmware versions. Only savable parameters not spot values can be read and written by these commands.


0x601 # 0x40 0x00 0x20 0x00 0 0 0 0 Get value of "boost"

0x601 # 0x23 0x00 0x20 0x01 0x80 0x0C 0 0 Set "fweak" to 100Hz (0xC80=3200 because scaled by 32)

0x601 # 0x23 0xAA 0x31 0x01 0x08 0x10 1 0 Map value of fweak to COB ID 0x1AA, starting at bit 8, stretching 16 bits, scaled by 1

0x601 # 0x40 0x10 0x20 0x0D 0 0 0 0 Get value of "pwmfrq" on any firmware version or build (0x0D = 13 from the PARAM_ENTRY() for "pwmfrq" in param_prj.h)

Mapping values to arbitrary CAN messages

Values can be mapped into a certain bit range of the 64 payload bits of a CAN message. They can either be read from the message or sent via a message. To do so enter

can tx udc 123 0 16 10

This maps the value of udc to a CAN message with id 123 bits 0..15 (start at bit 0, span over 16 bits) with a gain of 10.

can tx din_forward 123 24 1 1

would map the pin state of the forward input to bit 24 of CAN message with id 123.

If you want to clear all messages, type

can clear

If you want to remove only a specific signal (starting version 4.18.R) type

can del <name>

To save your can map simply type "save".

idcmin, idcmax example

Mapping Values through the web interface

Value can also be mapped through the web interface.

Spot values
Spot values
  • CAN Id
  • Position
    • This is where in the 64 bit length of the CAN message the data should start.
  • Bits
    • How many bits are assigned to send the data. Negative numbers will yield big endian mapping
  • Gain
    • This applies the internal scaling. Pre FW v5.27 this is fixed point (integers only). FW v5.27 and later is floating point (decimals allowed).
    • Your gain needs to be opposite of the receiving end's scaling. For example, the Speedhut EV gauges list a scaling of 0.1, meaning they apply that to incoming messages, so you need to transmit with a gain of 10.
  • Map to CAN
    • TX to tell the control board to transmit the data onto the CANBUS
    • RX to tell the control board to expect to receive this data from the CANBUS

Mapping values via SDO

Special SDO objects also allow editing the CAN map. See examples above on how to send an SDO request.

Adding a mapping requires a sequence of 3 SDO requests:

  • Index 0x3000 - Add transmit (TX) mapping
    • Subindex 0: CAN Id, data contains 11 or 29-bit CAN Id
    • Subindex 1: Parameter Id in bytes 0 and 1, bit position in byte 2, bit length in byte 3
    • Subindex 2: Gain * 1000 in bytes 0-2, offset in byte 3
  • Index 0x3001 - Add receive (RX) mapping
    • Same subindexes as above

For reading the entire CAN map subsequent reads to indexes 0x3100 (TX) or 0x3180 (RX) must be performed. The indexes and subindexes must be incremented between the reads until an SDO abort is received. Each CAN message maps to its own SDO index and the data items within the message map to sub indexes like so

  • Index 0x3100 - first transmit (TX) message
    • Subindex 0: CAN Id
    • Subindex 1: First parameter Id, position and length (see add)
    • Subindex 2: First gain and offset (see add)
    • Subindex 3: Second parameter Id, position and length
    • Subindex 4: Second gain and offset
    • Subindex 5: third...
  • Index 0x3101 - second TX message
    • as first
  • Index 0x3180 - First receive (RX) message
    • as above
  • Index 0x3181 - Second RX message

Once you know the index an sub index of a specific mapping you can also delete it by sending a write request. E.g. writing to Index 0x3181, sub index 3 would delete the second item of the second RX message.

Because the mappings are stored in a dynamic memory structure their order will change when deleting items. So before deleting the next item you have to re-download the entire mapping table to obtain the correct index.

After changing the map you have to send a flash save command to make your changes permanent. See commands below

SDO commands

Write requests to SDO Index 0x5002 trigger various commands

  • Subindex 0 - save parameters and CAN mappings to flash
  • Subindex 1 - loads parameters from flash
  • Subindex 2 - MCU reset
  • Subindex 3 - Load parameter defaults


  • A maximum of 10 messages can be defined
  • Per message a maximum of 8 values can be mapped (50 total over all messages in FW v5.27 and later)
  • a value can not span across the 32-bit boundary, i.e. it must be fully contained in the first or second 32 bits of the message. E.g. "can tx udc 123 16 32 10" is not allowed (will change in later versions)
  • A value can span maximum 32 bits


CAN messages sent to, or received from the inverter are Little-endian.

If you are sending or receiving messages containing multi-byte values then the byte order must be taken into account. Upcoming versions of the CAN module will allow receiving big endian data.

PC Tool

A PC based tool called openinverter_can_tool exists to query and control openinverter systems over CAN bus with a supported CAN interface adapter.