# Getting Started

# What is CAN bus?

**Controller Area Network (CAN)** is a serial communication protocol that lets microcontrollers and devices talk to each other without a central host computer. Developed by Bosch in the 1980s, it is now the standard in automotive and heavy vehicle electronics.

### Why buses use it

In a **MAN Lion's City**, dozens of ECUs (Electronic Control Units) share data in real time: the engine tells the instrument cluster the RPM, the EBS reports brake air pressure, the tachograph transmits vehicle speed — all over **two wires** (CAN\_H and CAN\_L).

### The J1939 standard

Heavy vehicles (buses, trucks) use **SAE J1939**, an application layer built on top of CAN. It defines:

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-element-description-"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Element</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Description</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">**29-bit ID**</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Extended identifier (vs 11-bit basic CAN)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">**PGN**</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Parameter Group Number — identifies the data type</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">**SA**</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Source Address — address of the sending ECU (0x00–0xFE)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">**SPN**</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Suspect Parameter Number — each signal within a PGN</td></tr></tbody></table>

</div>### Implementation parameters

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-parameter-value-bus-"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Parameter</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Value</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Bus speed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">250 kbps</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ID type</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Extended (29-bit)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Send cycle</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">20 ms (50 Hz)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Transceiver</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MCP2515 + TJA1050</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MCP2515 oscillator</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8 MHz</td></tr></tbody></table>

</div>### Note

`0xFF` bytes in unused positions are the J1939 default for "parameter not available" (SNA — Specific Not Available).

# Hardware setup

### Compatible boards

Any Arduino with SPI support works. The CS pin and SPI pins vary by board:

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-board-sck-mosi-miso-"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Board</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">SCK</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">MOSI</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">MISO</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">CS (recommended)</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Notes</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Arduino Mega 2560</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">52</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">51</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">50</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">53</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Hardware SPI, most headroom</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Arduino Uno</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">13</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">11</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">12</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5V, limited RAM</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Arduino Nano</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">13</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">11</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">12</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Same as Uno, compact</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Arduino Micro</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">15</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">16</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">14</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5V, USB HID capable</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Arduino Leonardo</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">15</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">16</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">14</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Same as Micro</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ESP32</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">18</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">23</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">19</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">3.3V — use level shifter</td></tr></tbody></table>

</div>For ESP32, the MCP2515 runs at 3.3V — do **not** connect directly to a 5V MCP2515 module without a level shifter.

### Required components

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-component-recommende"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Component</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Recommended model</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Microcontroller</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Any board from the table above</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CAN module</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MCP2515 + TJA1050 breakout board</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Bus terminators</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">2× 120 Ω resistor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Wiring</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Twisted pair for CAN\_H / CAN\_L</td></tr></tbody></table>

</div>### Wiring — Arduino Mega

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-arduino-mega-mcp2515"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Arduino Mega</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">MCP2515 module</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5V</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VCC</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">GND</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">GND</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 52</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SCK</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 51</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MOSI</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 50</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MISO</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 53</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CS</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 2</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">INT (optional)</td></tr></tbody></table>

</div>### Wiring — Arduino Uno / Nano

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-arduino-uno%2Fnano-mcp"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Arduino Uno/Nano</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">MCP2515 module</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5V</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VCC</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">GND</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">GND</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 13</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SCK</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 11</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MOSI</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 12</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">MISO</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 10</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CS</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">pin 2</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">INT (optional)</td></tr></tbody></table>

</div>### Initialization code

Change `SPI_CS_PIN` to match your board:

```c++
#include <SPI.h>
#include <mcp_can.h>

const int SPI_CS_PIN = 10;  // 53 for Mega, 10 for Uno/Nano
MCP_CAN CAN(SPI_CS_PIN);

void setup() {
    while (CAN_OK != CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ)) {
        delay(100);
    }
    CAN.setMode(MCP_NORMAL);
}
```

### MCP2515 oscillator

Most MCP2515 modules come with an **8 MHz** crystal. Some come with **16 MHz** — check the crystal printed on your module and change the parameter accordingly:

<div class="overflow-x-auto w-full px-2 mb-6" id="bkmrk-crystal-parameter-8-"><table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Crystal</th><th class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold" scope="col">Parameter</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8 MHz</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">`MCP_8MHZ`</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">16 MHz</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">`MCP_16MHZ`</td></tr></tbody></table>

</div>### Installing the library

Install **mcp\_can** by Cory Fowler from the Arduino IDE library manager, or clone directly:

```bash
cd ~/Documents/Arduino/libraries
git clone https://github.com/coryjfowler/MCP_CAN_lib
```

### Important

Always place a **120 Ω resistor between CAN\_H and CAN\_L at each end** of the bus. Without terminators, signal reflections will make the bus unstable.