Issue getting packets from CANBUS using ESP32

Hello, I spent 2 days trying to get data from a car's CAN BUS without success. I am using an ESP32 with a CAN tranceiver. the setup is:

                                                      +-------------+
                                                      |             |
                                                      |             |
                                                      |             |
                                                      |             |
                                                    [ESP32 WROOM 32 U]   
                                                      |             |
CAR                 +-------------------------+       |             |
     CAN_L o--------o CAN_L               3v3 o-------o 3v3         |
     CAN_H o--------o CAN_H               GND o-------o GND         |
                    |                         |       |             |
                    |   [SN65HVD230]   CAN TX o-------o 16  (RX)    |
                    |                  CAN RX o-------o 17  (TX)    |
                    +-------------------------+       +-------------+

ESP32, SN65HVD230 and the car's CANBUS share a common GND.
I tried the library in GitHub - sandeepmistry/arduino-CAN: An Arduino library for sending and receiving data using CAN bus.
The code is :

#include <CAN.h>

const int rxPin = 16;
const int txPin = 17;

// Specify the desired CAN bus speed (500 kbps)
const long canSpeed = 500E3;

unsigned long lastPacketTime = 0;
const unsigned long timeout = 20000; // 20 seconds

#define CAN_ID_ENGINE_SPEED 0x410  // CAN ID for Engine Speed (Subaru Impreza)

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("CAN Receiver");
  CAN.setPins(rxPin, txPin);

  if (!initializeCAN(canSpeed)) {
    Serial.println("Failed to initialize CAN at 500 kbps.");
    while (1);
  }
}

void loop() {
  int packetSize = CAN.parsePacket();  // Check for incoming CAN packets

  if (packetSize) {  // If a packet is received
    lastPacketTime = millis();
    Serial.print("Received ");

    if (CAN.packetExtended()) {
      Serial.print("extended ");
    }

    if (CAN.packetRtr()) {
      Serial.print("RTR ");
    }

    Serial.print("packet with id 0x");
    Serial.print(CAN.packetId(), HEX);

    if (CAN.packetRtr()) {
      Serial.print(" and requested length ");
      Serial.println(CAN.packetDlc());
    } else {
      Serial.print(" and length ");
      Serial.println(packetSize);

      if (CAN.available()) {
        byte buf[8];
        for (int i = 0; i < packetSize; i++) {
          buf[i] = CAN.read();
        }

        // Check if the received CAN ID is the one broadcasting Engine Speed
        if (CAN.packetId() == CAN_ID_ENGINE_SPEED) {
          // Process Engine Speed data based on the provided format
          uint16_t engineSpeed = buf[5] | (buf[6] << 8);  // Little endian
          Serial.print("Engine Speed: ");
          Serial.print(engineSpeed);
          Serial.println(" rpm");
        } else {
          // Print the received data if it's not Engine Speed
          for (int i = 0; i < packetSize; i++) {
            Serial.print(buf[i], HEX);
            Serial.print(" ");
          }
          Serial.println();
        }
      }
    }

    Serial.println();
  } else {
    if (millis() - lastPacketTime > timeout) {
      Serial.println("No CAN packet received for 20 seconds, attempting to reinitialize CAN...");
      if (!initializeCAN(canSpeed)) {
        Serial.println("Failed to reinitialize CAN at 500 kbps.");
      }
    }
    delay(1000);
  }
}

bool initializeCAN(long speed) {
  Serial.print("Initializing CAN at ");
  Serial.print(speed / 1E3);
  Serial.println(" kbps");

  if (CAN.begin(speed)) {
    Serial.print("CAN initialized successfully at ");
    Serial.print(speed / 1E3);
    Serial.println(" kbps");
    lastPacketTime = millis();
    return true;
  } else {
    Serial.print("Starting CAN at ");
    Serial.print(speed / 1E3);
    Serial.println(" kbps failed!");
    return false;
  }
}

in the console I can see:

08:22:40.720 -> CAN Receiver
08:22:45.409 -> Initializing CAN at 500.00 kbps
08:22:45.409 -> CAN initialized successfully at 500.00 kbps
08:23:06.357 -> No CAN packet received for 20 seconds, attempting to reinitialize CAN...
08:23:06.424 -> Initializing CAN at 500.00 kbps
08:23:06.462 -> CAN initialized successfully at 500.00 kbps
08:23:27.485 -> No CAN packet received for 20 seconds, attempting to reinitialize CAN...
....

I confirm that there is no problem with the wiring with respect to the setup shown above. I have no oscilloscope to check the signal between L and H of the CAN bus.

I checked many posts in the internet but I could not find anything that helps to solve the issue.
Any help is greatly appreciated.

Have a search on the forum for “ ESP32 and CAN (VD230

You can make a simple detector by using an Op Amp with a LED on the output and connecting the inputs via maybe 20K resistors to CAN_H and CAN_L. The led will blink when there is traffic.

1 Like

Good idea. I will try that to see if something comes in the CAN_H and CAN_L. Thank you for the hint.

It depends on how it is connected on the +- inputs or the polarity of the LED but swapping the inputs or reversing the LED will keep it dark except when data if flowing, the other way it goes dark when data is flowing. I generally use a LM358. The input resistors are to keep from placing any load on the CAN bus.

After implementing the LED hint, I confirm that the packets are received in the CAN_H and CAN_L but still nothing is received by esp32. (By the way, the value of the resistance between CAN_H and CAN_L is 60 ohm). I will continue the investigation next weekend and feed this post.

That is where is exactly what it should be, you probably have a 120 Ohm resistor on each end of the bus.

If you can get a scope check the outputs of the bus transceiver. It should also be toggling with the bus. You may have a bad or mislabeled bus transceiver the SN65HVD230. I received a bunch of 5V transceivers that were 5V only that worked down to just less than 3V. All of the parameters were met or exceeded. They were soldered on a MPC2515 module.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.