C.E.
C.E.

Reputation: 664

ESP32 - TWAI Timing Problems (cant receive messages below 5ms period)

I am currently trying to read an existing canbus (Car) with my ESP32 Rev3. I got it to work fine with an external MCP2515 shield using a default library.

But when I connect an transceiver and trying to use the internal TWAI controller built into ESP32 I am starting to get troubles. When receiving messages with at least >5ms period, it works fine but as soon the period gets under 5ms, its rapidly filling up the RX buffer and once its full, its starting to drop packets. When I set the RX buffer to a higher value, this only extend the time until the first error appears. It seems like the transceiver works fine but the twai_receive() function can't catch up. Does anyone have an idea, what I can do here.

For receiving, I am using the following, which works kind of fine for ESP32 Wroom Rev3. https://github.com/halfroad/TWAIMessager

Before, I was directly accessing the API by using this documentation, but this has the same behaviour: https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32/api-reference/peripherals/twai.html#examples

If the internal limitation is >5ms per message period, the CAN controller is pretty useless as in most modern cars canbus you have periods as low as 0.4ms per message.

To verify, that I'm not missing anything I setup two ESP32 and sending from A to B.

The code/setup of the receiving part is like this:

#include "driver/twai.h"
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_33, GPIO_NUM_32, TWAI_MODE_LISTEN_ONLY);
    twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS(); 
    twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

    //Install TWAI driver
    if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
        Serial.println("Driver installed\n");
    } else {
        Serial.println("Failed to install driver\n");
        return;
    }

    //Start TWAI driver
    if (twai_start() == ESP_OK) {
       Serial.println("Driver started\n");
    } else {
        Serial.println("Failed to start driver\n");
        return;
    }

The processing of ingoing messages in the loop() function is something like this:

twai_message_t message;

void loop() {
    while (twai_receive(&message, 0) == ESP_OK) {
        // process message (which will only arrive every 5ms
        Serial.printf(msgString, "STD CAN-ID: 0x%.3lX       DLC: %1d  Data:", message.identifier, message.data_length_code);
            for(byte i = 0; i<message.data_length_code; i++){
                        Serial.printf(" 0x%.2X", message.data[i]);
            }
        Serial.println(); 
    }

return; 
} 

Here is the receiving side's output when sending in a 5.1ms period: enter image description here

On the left you can see the period between this, and the previous message. The ID in green on the right side confirms, that the message is a valid follow up to the previous message (data).

As soon as im trying to go <5ms, 3ms in this example it looks like this: enter image description here

Here, it starts to drop messages as soon the RX buffer is filled up.

In the last image, you will see a log of the drivetrain canbus of a 2013 VAG car using the ESP32 and a MPC2515 controller externally.

It has periods between 0.41 and 9ms between each package and its not missing a single one of it.

enter image description here

I hope, someone here can actually help with this or had experienced the same behaviour before.

Upvotes: 0

Views: 769

Answers (1)

DrMickeyLauer
DrMickeyLauer

Reputation: 4684

The key to fast TWAI response is to a) put the ISR into IRAM using the configuration and a special flags when setting up the driver, and b) run a high priority task that blocks in twai_receive and just puts the read frames into a queue with enough slots (e.g., 587, if you're using ISOTP).

Upvotes: 0

Related Questions