Подключение трансивера CAN SN65HVD230 к ESP32

Трансивер шины CAN, 3,3 В

SN65HVD230 к ESP32 — питание 3,3 В, земля, CTX на вывод передачи TWAI (в примере GPIO5), CRX на вывод приёма (GPIO4) и пара CANH/CANL к шине.

Схема подключения трансивера CAN SN65HVD230 к ESP32

SN65HVD230ESP32
3V33V3
CANHobd2-port obd, вывод CANH
CANLobd2-port obd, вывод CANL
CRXGPIO4
CTXGPIO5
GNDGND, obd2-port obd, вывод GND

Схема из примера «SN65HVD230: обороты двигателя по шине CAN (OBD-II)».

SN65HVD230: обороты двигателя по шине CAN (OBD-II)

Открыть пример целиком

Выводы SN65HVD230

ВыводНазначение
3V3питание модуля, 3,3 В
CANHпровод шины CAN High
CANLпровод шины CAN Low
CRXвыход приёма: сюда идёт RX контроллера CAN
CTXвход передачи: сюда идёт TX контроллера CAN
GNDобщий провод, в том числе с шиной

Код для ESP32

#include "driver/twai.h"

// Запрос оборотов двигателя по OBD-II.
//
// Контроллер CAN внутри ESP32 (он называется TWAI) выдаёт обычные
// логические уровни на TX и RX. Шине нужна дифференциальная пара
// CANH/CANL — её даёт трансивер SN65HVD230. Он питается от 3,3 В и
// стоит между выводами платы и разъёмом.
//
// Диагностика OBD-II устроена как вопрос и ответ:
//   вопрос  — кадр 0x7DF (всем блокам): 02 01 0C  («служба 01, параметр 0C»)
//   ответ   — кадр 0x7E8 (двигатель):   04 41 0C A B
//   обороты = (256 * A + B) / 4

const gpio_num_t CAN_TX = GPIO_NUM_5;   // к CTX трансивера
const gpio_num_t CAN_RX = GPIO_NUM_4;   // к CRX трансивера

void setup() {
  Serial.begin(115200);

  twai_general_config_t general = TWAI_GENERAL_CONFIG_DEFAULT(CAN_TX, CAN_RX, TWAI_MODE_NORMAL);
  twai_timing_config_t timing = TWAI_TIMING_CONFIG_500KBITS();   // скорость легковой шины
  twai_filter_config_t filter = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  if (twai_driver_install(&general, &timing, &filter) != ESP_OK) {
    Serial.println("CAN: драйвер не установился");
    return;
  }
  if (twai_start() != ESP_OK) {
    Serial.println("CAN: драйвер не запустился");
    return;
  }
  Serial.println("CAN запущен, 500 кбит/с");
}

void loop() {
  twai_message_t request = {};
  request.identifier = 0x7DF;
  request.data_length_code = 8;
  request.data[0] = 0x02;   // длина полезных данных
  request.data[1] = 0x01;   // служба 01: текущие данные
  request.data[2] = 0x0C;   // параметр 0C: обороты
  twai_transmit(&request, 0);

  // Ответ ждём не дольше четверти секунды: если автомобиль молчит, это
  // тоже результат, а не повод зависнуть.
  unsigned long start = millis();
  bool answered = false;
  while (millis() - start < 250 && !answered) {
    twai_message_t reply;
    while (twai_receive(&reply, 0) == ESP_OK) {
      if (reply.identifier == 0x7E8 && reply.data[1] == 0x41 && reply.data[2] == 0x0C) {
        int rpm = (256 * reply.data[3] + reply.data[4]) / 4;
        Serial.printf("обороты: %d об/мин\n", rpm);
        answered = true;
        break;
      }
    }
    delay(5);
  }
  if (!answered) Serial.println("автомобиль не ответил: проверьте CANH, CANL и скорость шины");

  delay(1000);
}

Скетч можно править и запускать в симуляторе без платы и установки среды.

Что учесть на ESP32

В железе

У многих модулей на плате стоит нагрузочный резистор 120 Ом между CANH и CANL. На шине их должно быть два — по одному на каждом конце. Если вы подключаетесь к готовой сети (автомобиль, станок), где концы уже нагружены, лишний резистор лучше отключить. Земля модуля и земля шины должны быть общими.

Частые ошибки при подключении к ESP32

Другие детали для ESP32