> For the complete documentation index, see [llms.txt](https://yagsl.yassrobotics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yagsl.yassrobotics.com/how-to-guides/choose-a-can-bus.md).

# Put devices on a different CAN bus

Tell YAGSL which SystemCore, Motioncore or vendor CAN bus each device is on with the canbus field.

The SystemCore has several CAN buses instead of one, so every CAN device in your YAGSL JSON (drive and angle motors, absolute encoders, the gyro) has a `canbus` field saying which bus it is wired to. YAGSL reads that field the same way for every vendor.

{% hint style="warning" %}
**Behavior change for CTRE devices.** An empty `canbus` now always means SystemCore bus `can_s0`, for every vendor. Before, CTRE devices with an empty `canbus` ended up on Phoenix 6's own SystemCore default, `can_s2`. If your TalonFX, CANcoder or Pigeon 2 devices are wired to `can_s2`, they now need `"canbus": "2"`.
{% endhint %}

## 1. Find the bus each device is wired to

<figure><img src="https://567506766-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F754c0Fpq8fBi6k4ByS1k%2Fuploads%2Fgit-blob-8f34e3b3aa704db47ab46c524d61e81ce7c6d17e%2Fyagsl-can-buses.png?alt=media" alt="Three groups of buses. SystemCore: can_s0 is an empty canbus or 0, then can_s1 to can_s4 are 1 to 4. Motioncore: can_d0 is 5, can_d1 is 6, up to can_d19 which is 24. CANivore: its name, for example canivore. An empty canbus is can_s0 for every vendor, a number outside 0 to 24 stops the program at startup, and any other text goes to the vendor as is."><figcaption><p>Which canbus value means which bus.</p></figcaption></figure>

| `canbus` value     | Bus                                                                |
| ------------------ | ------------------------------------------------------------------ |
| `""` (or left out) | SystemCore `can_s0`                                                |
| `"0"` to `"4"`     | SystemCore `can_s0` to `can_s4`                                    |
| `"5"` to `"24"`    | Motioncore `can_d0` to `can_d19`                                   |
| Any other text     | Passed to the vendor as is, for example a CANivore's name for CTRE |

So a device on `can_s1` gets `"canbus": "1"`, and the first Motioncore bus, `can_d0`, is `"5"`. A number outside 0 to 24 stops the robot program at startup with `CAN bus <n> does not exist`.

## 2. Set `canbus` on each device

`canbus` is a string, so bus numbers are quoted:

```json
{
  "drive": { "type": "sparkflex_vortex", "id": 2, "canbus": "1" },
  "angle": { "type": "sparkmax_neo550", "id": 1, "canbus": "1" },
  "absoluteEncoder": { "type": "cancoder_can", "id": 10, "channel": 0, "canbus": "" },
  "inverted": { "drive": false, "angle": false },
  "absoluteEncoderOffset": -50.977,
  "location": { "front": 12, "left": 12 }
}
```

```json
{
  "gyro": { "type": "pigeon2_can", "id": 13, "canbus": "canivore" },
  "gyroAxis": "yaw",
  "gyroInvert": false,
  "modules": ["frontleft.json", "frontright.json", "backleft.json", "backright.json"]
}
```

Devices in one module don't have to share a bus, and neither do the modules.

## 3. Check what your vendor accepts

Not every vendor can use a bus name:

| Vendor                                                          | Accepted `canbus` values                                                                                                                                                |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CTRE (`talonfx_*`, `talonfxs_*`, `cancoder_can`, `pigeon2_can`) | Empty, a bus number, or a CANivore's name or serial number                                                                                                              |
| REV (`sparkmax_*`, `sparkflex_*`, `splineencoder_can`)          | Empty or a bus number only                                                                                                                                              |
| Thrifty (`nova_*`)                                              | Empty or a bus number only                                                                                                                                              |
| Redux (`canandgyro_can`, `canandmag_can`)                       | Empty, a bus number, or a ReduxLib bus string such as `socketcan:can_s1`                                                                                                |
| Studica (`navx3_can`), AndyMark (`andymarkhexbore_can`)         | `canbus` is not used; the device is created from its CAN ID alone. Neither device works with YAGSL 2027 yet, because their vendor libraries have no `2027_alpha7` build |

That includes port names: a SPARK on `can_s1` is `"1"`, not `"CAN_S1"`. Giving a REV or Thrifty device anything other than a bus number stops the robot program at startup with an `IllegalArgumentException` like:

```
REV devices only use the Systemcore and Motioncore CAN buses, but canbus is "canivore". Use "" for can_s0, or the bus number, such as "1" for can_s1.
```

Encoders with an `_attached`, `_dio` or `_analog` type are not on CAN at all, so their `canbus` is ignored. An `_attached` encoder is read through the angle motor controller, on that controller's bus.

## 4. Verify it

Deploy and check the Driver Station console. A wrong bus doesn't stop the program the way a malformed value does: the device is simply never found, so you get that vendor's usual "device not detected" alerts and a module that doesn't respond. If one module or one vendor's devices are missing, compare its `canbus` against the bus it is physically wired to before looking anywhere else.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://yagsl.yassrobotics.com/how-to-guides/choose-a-can-bus.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
