---
title: Bafang CAN Bus Programming
date: 2024-04-21T20:54:56+00:00
modified: 2025-12-21T14:58:38+00:00
image:: https://kaspars.net/wp-content/uploads/2024/04/bafang-m200-motor-connectors-scaled.jpg
permalink: https://kaspars.net/blog/bafang-canbus
post_type: post
author:
  name: Kaspars
  avatar: https://reverse.kaspars.net/gravatar/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=mm&r=g
category:
  - Electronics
---

# Bafang CAN Bus Programming

![Bafang M200 (M-series) mid-drive motor with CAN bus](https://kaspars.net/wp-content/uploads/2024/04/bafang-m200-motor-connectors-scaled.jpg?strip=all&quality=90&resize=2560,1920)Bafang M200 mid-drive motor (model `MM G210.250.C`) with 36V battery connector (yellow, from left), empty 6-pin electric break connector (purple), 8-pin rear light and wheel speed connector, and 8-pin front light and display connector.I got my wife this [Accolmile Antelope 1S](https://accolmile.com/products/aantelope-1s) electric bicycle with Bafang components from their latest [M-series lineup of mid-drive motors](https://www.bafang-e.com/en/products/motors/m-series/) and [displays](https://www.bafang-e.com/en/oem-area/components/hmi/) which communicate over a CAN bus. It’s a great city bike and the price includes fast shipping from the warehouse in Poland. Their support was also quick to send a replacement wheel for the original that got dented during transport (despite the thoughtful packaging).

## CAN over NodeJS

The M500/M600 motors are particularly popular with MTB riders so the communication protocol has been discussed in [this forum thread](https://endless-sphere.com/sphere/threads/bafang-m500-m600-thread.100777/) and documented in [this GitHub repository](https://github.com/OpenSourceEBike/Bafang_M500_M600). Importantly, the [BESST software](https://bafang-e.com/en/oem-area/service/besst/) for managing the configuration and firmware updates is [an Electron app](https://www.electronjs.org) with all logic as plain HTML and JS files (and bundled [source maps](https://developer.chrome.com/blog/sourcemaps) for all minified code), including the CAN frame specification. I’ve started documenting my research in [this GitHub repository](https://github.com/kasparsd/besst-reference).

## Connecting to CAN Bus

![Wiring diagram for connecting to Bafang CAN-bus wiring between screen and motor controller](https://kaspars.net/wp-content/uploads/2024/04/bafang-canbus-canable-wiring.png?strip=all&quality=90&resize=1920,1234)    The display connector at the wheel is the most convenient place to tap into the CAN bus. I purchased two HIGO 5-pin connectors B5-F and S5-F from [ETShop in Germany](https://shop.e-bike-technologies.de/de/) for around €7 each ([AliExpress](https://kaspars.net/go/bafang-5-pin-can-cable) / [Amazon](https://kaspars.net/go/amazon-bafang-5-pin-can-cable)) and soldered the CAN high (green), CAN low (white) and ground (black) wires from each for a connection to (a copy of) the [CANable Pro 1.0 CAN-to-USB adapter](https://canable.io) ([AliExpress](https://kaspars.net/go/canable-pro) / [Amazon](https://kaspars.net/go/amazon-canable-pro)). **Be sure to test the wiring with a multimeter because one of the wires carries the full battery voltage!**

Technically *any CAN-to-USB adapter will work* (as long as it supports 250kbit transfer rate) and the choice depends more on the software you want to use for interacting with the bus. The CANable adapter runs the [slcan firmware](https://github.com/normaldotcom/canable-fw) which implements the [Lawicel SLCAN protocol](https://www.canusb.com/products/canusb/) (a basic ASCII serial) which is supported by various libraries, including SocketCAN.

![HIGO S5-F connector wires for Bafang CAN bus](https://kaspars.net/wp-content/uploads/2024/04/bafang-higo-s5-male-connector-scaled.jpeg?strip=all&quality=90&resize=2560,1920)Pinout of the HIGO S5-F (female) connector.![Bafang HIGO S5 and B5 connectors attached to CANable Pro](https://kaspars.net/wp-content/uploads/2024/04/bafang-can-bus-higo-s5-b5-canable-pro-scaled.jpeg?strip=all&quality=90&resize=2560,2560)HIGO 5-pin B5-F and S5-F connectors attached to CANable Pro 1.0 CAN-to-USB adaptor.![CANbus traffic between Bafang M200 and DP C245 display.](https://kaspars.net/wp-content/uploads/2024/04/cangaroo-can-bus-bafang-m200-motor-dp-c245-scaled.jpeg?strip=all&quality=90&resize=2560,1920)Logging CANbus traffic between Bafang M200 (G210.250.C) motor and DP C245 display.## Update Controller Configuration Manually

I was able to test the setup by increasing the assisted maximum speed to 60km/h from the original 25km/h by sending [a CAN message](https://github.com/kasparsd/besst-reference/blob/47b3139c6dc672b90358e546abc30992b20d48c9/app/static/js/webpack/device/controller.js#L652-L663) composed of the following components:

- `0x05` for the [message source](https://github.com/kasparsd/besst-reference/blob/47b3139c6dc672b90358e546abc30992b20d48c9/app/static/js/webpack/node_modules/besst-usb-sdk/src/usbClient/common.js#L41-L53) (`0x01` — torque sensor, `0x02` — controller, `0x03` — display or HMI, `0x04` — battery, `0x05` — BESST),
- `0x02` for the message target (controller),
- `0x00` for a WRITE [operation](https://github.com/kasparsd/besst-reference/blob/47b3139c6dc672b90358e546abc30992b20d48c9/app/static/js/webpack/node_modules/besst-usb-sdk/src/usbClient/common.js#L55-L68) (`0x01` for READ),

which are transformed into a frame ID prefix for the `0x3203` code and subcode for “speed limit, wheel diameter and circumference” registry through [this transformer function](https://github.com/kasparsd/besst-reference/blob/47b3139c6dc672b90358e546abc30992b20d48c9/app/static/js/webpack/node_modules/besst-usb-sdk/src/usbClient/common.js#L229-L237):

```
buildHexStringCommand = (source, target, opt, anfn, nfn) => {
    const cmdPrefix = hexAllocToBinaryStr(source.toString(16), 5) + hexAllocToBinaryStr(target.toString(16), 5) + hexAllocToBinaryStr(opt.toString(16), 3);
    let cmdPrefixHex = parseInt(cmdPrefix, 2).toString(16);
    if (cmdPrefixHex.length % 2 !== 0) {
        cmdPrefixHex = '0' + cmdPrefixHex;
    }
    let cmdHexString = cmdPrefixHex + anfn + nfn;
    return hexReverse(cmdHexString);
};
```

which returns:

```
05 10 32 03
```

as the frame ID along with the payload:

```
70 17 C0 2B B6 08 
```

where (with little-endian byte order):

- `0x1770` is 6000 or 60km/h × 100,
- `0x2BC0` is 700 or 700c wheel diameter (29-inch), and
- `0x08B6` is 2230 or 2230mm wheel circumference.

## Use Bafang CANable Pro Software

There is now the [Bafang CANable Pro open-source software](https://github.com/mdi-9/bafang_canable_pro) that allows you to configure all parameters using a desktop app (see [related forum thread](https://endless-sphere.com/sphere/threads/bafang-canable-pro-master-discussion.128228/)). Importantly, this requires CANable to be running the [candlelight firmware](https://github.com/candle-usb/candleLight_fw) since it uses the [GS\_USB protocol](https://github.com/torvalds/linux/blob/9094662f6707d1d4b53d18baba459604e8bb0783/drivers/net/can/usb/gs_usb.c#L34-L35) for talking directly to the USB device without the Serial/UART translation layer.