Hardware Matrix

Is MCP2515 CAN Bus Transceiver Module Compatible with Home Assistant (ESPHome)?

Verdict Badge
VERDICT: [ COMPATIBLE (MANUAL CONFIG REQUIRED) ]
Protocol: SPI / 3.3V
Bridge Needed: NO

Electrical Specifications

Always confirm pin assignments against the manufacturer datasheet before wiring.

Not yet documented. Electrical specifications for this device have not been confirmed against a manufacturer datasheet, so none are shown here rather than showing estimates. Submit verified specifications if you have the datasheet to hand.

Compatibility Overview

High-speed CAN bus communication interface for automotive OBD-II diagnostics solar inverter bus monitoring and industrial automation.

Wiring MCP2515 CAN Bus Transceiver Module to ESP32

Module pin ESP32 Note
VCC 5V The TJA1050 transceiver needs at least 4.75V. See the first gotcha for what that does to the SPI lines.
GND GND
CS GPIO5
SCK GPIO18
SI GPIO23 MOSI.
SO GPIO19 MISO — and on the stock module a 5V output driving a 3.3V input.
INT unconnected ESPHome polls the controller.
CANH / CANL the bus Twisted pair. On an OBD-II port, pins 6 and 14.
J1 jumper The 120Ω terminator. Fitted at the two physical ends of a bus and nowhere else.

Host pins are the ones the configuration on this page uses. Move a pin here and change it in the YAML — they are documented together so they cannot disagree.

Technical Specification Matrix

Feature / Attribute Specification / Status
Hardware Protocol SPI / 3.3V
Bridge Required NO
Border Router Needed None
Hardware Capabilities & Peripherals
CAN Packet Receiver OBD-II Telemetry Bus State

Note: these entities come from the ESPHome configuration you flash — each one needs its matching component in that YAML before it appears.

Pairing Complexity Advanced
Factory Reset Instruction Hold BOOT button for 3 seconds.

Wire, Flash, Adopt, Check

1

Wire it up

Follow the wiring table above. The ESP32 pins there are the ones the configuration uses, so if you move one, change it in both places.

2

Flash the configuration

Create a new device in the ESPHome dashboard (the Home Assistant add-on) and paste the configuration below into it, or save it as emb_esp32_mcp2515_ha.yaml and run esphome run emb_esp32_mcp2515_ha.yaml. The first flash goes over USB. If it is not detected, hold BOOT button for 3 seconds to put it in download mode. Every update after that is over the air.

3

Adopt it in Home Assistant

Settings → Devices & Services. A node on the same network shows up as a discovered ESPHome device within a minute of joining Wi-Fi; choose Configure and enter the API encryption key from your secrets.yaml. If discovery does not find it, add the ESPHome integration by hand with the node's IP address.

4

Check it works

The setup log reports the controller initialised. On a car with the engine running, pressing Request Engine RPM updates Engine RPM within a second. A controller that fails to initialise is SPI (or the SO voltage); one that initialises and never sees a frame is the clock setting or the terminator.

ESPHome Configuration

Starting configuration for MCP2515 CAN Bus Transceiver Module on ESP32. Untested on hardware — verify wiring and pins against your own board.

# ESPHome configuration for MCP2515 CAN Bus Transceiver Module
# Host: ESP32. Pin numbers below are host-side defaults — any free
# GPIO will do, and you should change them to match your own wiring.

esphome:
  name: emb_esp32_mcp2515_ha
  friendly_name: "MCP2515 CAN Bus Transceiver Module"

esp32:
  board: esp32dev
  framework:
    type: esp-idf

logger:

api:
  encryption:
    key: !secret api_encryption_key

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

spi:
  clk_pin: GPIO18
  mosi_pin: GPIO23
  miso_pin: GPIO19

# clock must match the crystal on the module — the figure printed on the
# metal can. Most of the cheap blue boards carry 8.000 MHz; some carry
# 16.000 MHz. A wrong value gives a bit rate that is out by 2x and a bus
# that never synchronises.
canbus:
  - platform: mcp2515
    id: can_bus
    cs_pin: GPIO5
    can_id: 4
    bit_rate: 500KBPS
    clock: 8MHZ
    on_frame:
      # 0x7E8 is the engine ECU's reply address on an OBD-II port.
      # Mode 01 PID 0x0C is engine RPM: (A * 256 + B) / 4.
      - can_id: 0x7E8
        then:
          - lambda: |-
              if (x.size() >= 5 && x[1] == 0x41 && x[2] == 0x0C) {
                id(engine_rpm).publish_state(((x[3] << 8) | x[4]) / 4.0);
              }

sensor:
  - platform: template
    name: "Engine RPM"
    id: engine_rpm
    unit_of_measurement: "rpm"
    accuracy_decimals: 0

# 0x7DF is the OBD-II broadcast request address.
button:
  - platform: template
    name: "Request Engine RPM"
    on_press:
      then:
        - canbus.send:
            canbus_id: can_bus
            can_id: 0x7DF
            data: [0x02, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00]

Before you flash: the !secret values come from your secrets.yaml, and the GPIO numbers are host-side defaults rather than properties of this part — change them to match how you actually wired it.

What Appears in Home Assistant

Engine RPM
sensor

Decoded by the example lambda from the reply to OBD-II PID 0x0C. Every other value needs its own on_frame handler and its own template sensor.

Request Engine RPM
button

Sends the mode 01 request to the broadcast address. Put the same canbus.send in an interval: to poll.

Known Problems and Fixes

The 5V/3.3V problem on the cheap module

The common blue board powers the MCP2515 and the TJA1050 from one VCC pin. The transceiver needs 5V, so the controller runs at 5V too, and its SO pin then drives 5V into the ESP32's MISO — above the 3.6V maximum. Three fixes: the trace-cut mod that feeds the MCP2515 3.3V and only the TJA1050 5V; a level shifter or resistor divider on SO; or a module sold with separate 3.3V and 5V pins.

clock is the crystal on the board

The MCP2515 derives its bit timing from the crystal next to it. The frequency is printed on the can — 8.000 on most of these modules, 16.000 on some — and clock: must match. A mismatch gives a bit rate out by two and a bus that never synchronises, with no error to say why.

Termination

A bench bus of two nodes wants both terminated. A car is already terminated at both ends, so a module plugged into the OBD port should have J1 removed — a third terminator loads the bus.

OBD-II basics

Most cars since 2008 use 500kbps with 11-bit IDs. Requests go to 0x7DF; the engine ECU replies from 0x7E8, other ECUs from 0x7E9 to 0x7EF. Some makes use 29-bit IDs (use_extended_id: true and different addresses). The config's decoder handles the RPM PID; the formulas for the others are public.

Frames are not entities

Nothing appears in Home Assistant until a lambda publishes it. A busy bus also delivers thousands of frames a second, more than SPI polling keeps up with; filter with can_id and can_id_mask on each on_frame handler so the node only decodes what it needs.

🛠️ Hardware Correction & Field Contributions

Report a Pinout Error or Submit Tested Code Snippets

Found a pin mapping quirk or built a custom ESPHome YAML driver for MCP2515 CAN Bus Transceiver Module? Submit a pull request or report corrections to our index.

Frequently Asked Questions

Does MCP2515 CAN Bus Transceiver Module work without an internet connection?
100% local CAN frame decoding.
How is MCP2515 CAN Bus Transceiver Module powered and wired to the host board?
3.3V VCC for logic 5V power for TJA1050 transceiver chip; SPI (CS=GPIO5 INT=GPIO4).
How does the host board reach Home Assistant (ESPHome)?
Wi-Fi 2.4GHz.

Alternatives

Related Compatibility Matrix Guides