Communication and location

CAN bus (SN65HVD230) with ESP32

The ESP32 has a built-in CAN controller, called TWAI in Espressif's documents, but no physical CAN driver. Add a 3.3 V transceiver such as the SN65HVD230 and two pins connect to a real CAN bus. It suits vehicles, machines and robots, where several devices share one twisted pair.

Wiring is short: TX and RX to the transceiver's TXD and RXD, 3.3 V, ground, then CANH and CANL to the bus. Use 3.3 V only, because the logic pins are not 5 V tolerant. A bus needs a 120 Ω resistor at both ends. Many modules have one fitted, and if yours sits in the middle of a bus, it should come off.

The ESP32 and ESP32-S3 support classic CAN, not CAN FD. A device alone on the bus cannot finish sending, because nobody acknowledges its frames, so test with two nodes or a CAN adapter. The code below uses the driver in the ESP32 core, without a library. Check the board page first: boards such as Waveshare's Touch LCD 7 already have a transceiver and a terminal. Connecting to a car's bus can interfere with safety systems, so listen only unless you know the network.

CAN bus (SN65HVD230) wiring diagram for ESP32
Wiring diagram drawn by LCD Ultra Pro.

Specifications

ControllerESP32 TWAI, classic CAN only
Transceiver supply3.3 V
Bus wiresCANH, CANL
Termination120 Ω at both ends
Logic pinsNot 5 V tolerant

Power and logic levels

3.3 V: safe to connect directly

Supply3.3 V
Signal level3.3 V
On an ESP32This is a 3.3 V transceiver, so no shifting is needed. Do not feed it 5 V.

ESP32 pins, including those on a display board's connectors, work at 3.3 V and are not 5 V tolerant. Modules differ, so if in doubt, measure the signal before you connect it.

Wiring

CAN bus (SN65HVD230)Connect toNote
VCC3V3Never 5 V
GNDGND
TXD / CTXGPIO 5
RXD / CRXGPIO 6
CANH, CANLCAN busTwisted pair

Arduino code

#include "driver/twai.h"

const gpio_num_t TX_PIN = GPIO_NUM_5, RX_PIN = GPIO_NUM_6;

void setup() {
  Serial.begin(115200);
  twai_general_config_t g = TWAI_GENERAL_CONFIG_DEFAULT(TX_PIN, RX_PIN, TWAI_MODE_NORMAL);
  twai_timing_config_t t = TWAI_TIMING_CONFIG_500KBITS();
  twai_filter_config_t f = TWAI_FILTER_CONFIG_ACCEPT_ALL();
  twai_driver_install(&g, &t, &f);
  twai_start();
}

void loop() {
  twai_message_t tx = {};
  tx.identifier = 0x123;
  tx.data_length_code = 2;
  tx.data[0] = 0x11;
  tx.data[1] = 0x22;
  twai_transmit(&tx, pdMS_TO_TICKS(100));

  twai_message_t rx;
  if (twai_receive(&rx, pdMS_TO_TICKS(1000)) == ESP_OK) {
    Serial.printf("ID %03lX, %d bytes\n", (unsigned long)rx.identifier, rx.data_length_code);
  }
}

No extra library needed. Compiled for ESP32-S3 with arduino-esp32 3.x. Not yet tested by us on a physical sensor. Change the pins to match your board.

On a display

Read the value in your sketch and pass it to a label, or send it over MQTT and show it with an MQTT value in the editor.

Design a display for CAN bus (SN65HVD230)

Boards with a ready connector

Only boards whose connectors we have surveyed. Others may still work on free GPIOs.

Elecrow CrowPanel ESP32 HMI 2.4"GPIO_D port: GPIO 25, 32
Elecrow CrowPanel ESP32 HMI 2.8"GPIO_D port: GPIO 25, 32
Elecrow CrowPanel ESP32 HMI 3.5"GPIO_D port: GPIO 25, 32
Elecrow CrowPanel ESP32-S3 HMI 4.3"GPIO_D port: GPIO 37, 38
LilyGO T-Display (classic) 1.14"Left pin header: GPIO 21, 22
LilyGO T-Display-S3-Pro 2.33"QWIIC LEFT: GPIO 43, 44
LilyGO T-Deck 2.8"Grove connector: GPIO 43, 44On the T-Deck Plus this port is taken by the built-in GPS
M5Stack AtomS3 0.85"Grove port: GPIO 2, 1
M5Stack M5StickC Plus2 1.14"Grove port: GPIO 32, 33
Sunton ESP32-2432S028R 2.8"GPIO / I2C header (CN1): GPIO 22, 27
Sunton ESP32-4827S043R/C 4.3"GPIO header (P4): GPIO 17, 18P3 carries the same two pins
Sunton ESP32-8048S043C 4.3"GPIO header (P4): GPIO 17, 18P3 carries the same two pins
Sunton ESP32-8048S050C 5.0"GPIO header (P4): GPIO 17, 18P5 carries the same pins. Shared with the I2S amplifier of the speaker output (P6).
Sunton ESP32-8048S070C 7.0"GPIO header (P4): GPIO 17, 18P5 carries the same pins. Shared with the I2S amplifier of the speaker output (P6).
Waveshare ESP32-S3 Touch LCD 1.28" roundSH1.0 GPIO header: GPIO 15, 16Six GPIOs led out per the wiki pin table
Waveshare ESP32-S3 Touch LCD 1.28" round (CNC metal housing)SH1.0 GPIO header: GPIO 15, 16Six GPIOs led out per the wiki pin table

Good to know

  • A lone node gets no acknowledge. Test with two devices.
  • Use 3.3 V only on the transceiver.
  • ESP32 and ESP32-S3 support classic CAN, not CAN FD.
  • Keep off a car's bus unless you know what you are doing. Listen only.
  • Some display boards already have CAN.

What it is good for

  • Machine panels
  • Vehicle data displays
  • Robot and sensor networks

FAQ

Does the ESP32 have CAN?

It has a CAN controller called TWAI, but needs an external transceiver.

Why does my CAN send fail?

With one node, nobody acknowledges the frame. Add a second node and check termination.

Does the ESP32 support CAN FD?

ESP32 and ESP32-S3 support classic CAN only.

Sources

Related parts

Use this information at your own risk. It is for general guidance only: the example code compiles, but it has not been tested on every part, and modules differ between sellers. Check the manufacturer's data before you build. Product names belong to their owners, and LCD Ultra Pro is not affiliated with them. See our Terms.