Analog to CAN using ESP32

Hi everyone.

I working on a project where I utilize an ESP32 device and a CAN level shifter to create an analog to CAN device. So far I have reasonable amount of success with this, the only issue I have left to overcome is the Baud rate in my code is always double what I measure on the CAN bus using a CANAlyzer.

I am using a Sparkfun ESP32 Thing Plus:

Along with the Comimark CAN driver:

https://www.amazon.com/gp/product/B07YHYQ7C9/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1

I have successfully installed the ESP32-Arduino-CAN-master library.

Here is the code I have been using:

#include "CAN.h"
#include "CAN_config.h"

// Define the CAN_cfg variable
CAN_device_t CAN_cfg = {
    .speed = CAN_SPEED_1000KBPS,  // Set the desired speed
    .tx_pin_id = (gpio_num_t)16, // TX pin number
    .rx_pin_id = (gpio_num_t)17, // RX pin number
};

// Define all 8 analog input pins
const int analogPins[8] = {26, 25, 34, 35, 32, 33, 27, 14}; // Replace with actual pin numbers

void setup() {
    Serial.begin(115200);
    if (CAN_init() != 0) {
        Serial.println("Starting CAN failed!");
        while (1);
    }
    analogReadResolution(12); // 12 bits resolution for ESP32
}

void loop() {
    // Read voltage from all analog pins and send over CAN in two messages
    for (int msgIdx = 0; msgIdx < 2; msgIdx++) {
        CAN_frame_t frame;
        frame.FIR.B.FF = CAN_frame_std;
        frame.FIR.B.DLC = 8; // 2 bytes per analog read
        frame.MsgID = 100 + msgIdx; // CAN ID: 100 for first message, 101 for second

        for (int i = 0; i < 4; i++) {
            int analogValue = analogRead(analogPins[msgIdx * 4 + i]);
            float voltage = 3.3 * analogValue / 4095; // Convert to voltage
            uint16_t voltageInt = (uint16_t)(voltage * 100); // Convert to 2 decimal places

            frame.data.u8[i * 2] = (voltageInt >> 8) & 0xFF; // High byte
            frame.data.u8[i * 2 + 1] = voltageInt & 0xFF;    // Low byte
        }

        // Send message
        if (CAN_write_frame(&frame) == 0) {
            for (int i = 0; i < 4; i++) {
                Serial.print("Voltage");
                Serial.print(msgIdx * 4 + i + 1);
                Serial.print(": ");
                int analogValue = analogRead(analogPins[msgIdx * 4 + i]);
                float voltage = 3.3 * analogValue / 4095;
                Serial.print(voltage);
                Serial.println(" V");
            }
        } else {
            Serial.println("Error sending message");
        }
    }

    delay(10); // Adjust delay as needed
}

Any pointers will be great, thanks. Frustrating to get it so close to fully working. I'm sure it's something dumb on my part...

Richard

Post an annotated schematic showing exactly how you have wired it, be sure to include links to the hardware devices that give technical information. Show all connections, power, ground and power sources. Where is the CAN controller, your link does not state there is one on the processor.

The ESP32 supports CAN via the TWAI interface:

ESP32

I don't have access to a decent schematic package right now but here is a photo of the setup (very basic):

The CAN transceiver board operates via the TJA1051:

TJA1051

As mentioned earlier, when I connect the CANAlyzer to the CAN bus I see all the data as expected, just at a different Baud rate from what I defined in the software. In the example above the Baud rate should be 1000Kbps but I have to set my CANAlyzer at 500Kbps to monitor the data.

My guess is it is an issue within the libraries (attached below) but my Arduino experience does not delve deep enough into that side of things. It'll be interesting to see what light a more experienced user can shed on this issue.

Thanks

ESP32-Arduino-CAN-master (1).zip (15.7 KB)

From what I know the TWAI controller is not compatible with ISO11898-1 FD Format frames, and will interpret such frames as errors. The MCP2515 works with the FD format.

The datasheet for the TJA1051 lists the minimum supply voltage at 4.5v.
That is true for all variants including the TJA1051/T3 version that has a dual voltage data interface.

If your current driver is working at 3.3v then it indicates that you have a fake chip which is a common problem with stuff from Amazon/Ebay/Aliexpress.

To make a working system you have 2 choices:

  • Use a transceiver board that has the TJA1051/T3 variant with the VIO pin exposed so it can be connected to 3.3v to set the voltage of the data interface. The chip still needs to be powered by 5v.
  • Use a 3.3v transceiver such as the SN65HVD230D.

Who mentioned CAN-FD?

Not true.

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