From d8cee810e46fb02551c85c3617c3ae0eb14cd681 Mon Sep 17 00:00:00 2001 From: Stephan Martin Date: Sat, 5 Nov 2022 08:19:50 +0100 Subject: [PATCH 1/3] Add TWAI receive example Example showing how to receive messages using the TWAI interface and a CAN transceiver. --- .../examples/TWAI/TWAIreceive/TWAIreceive.ino | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino diff --git a/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino new file mode 100644 index 00000000000..63bb6f4db22 --- /dev/null +++ b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino @@ -0,0 +1,97 @@ +/* ESP32 TWAI receive example. + Receive messages and sends them over serial. + + Connect a CAN bus transceiver to the RX/TX pins. + For example: SN65HVD230 + + TWAI_MODE_LISTEN_ONLY is used so that the TWAI controller will not influence the bus. + + The API gives other possible speeds and alerts: + https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html + + Example output: + -> Message received + -> Message is in Standard Format + -> ID is 604 + -> Byte 0 = 0 Byte 1 = f Byte 2 = 13 Byte 3 = 2 Byte 4 = 0 Byte 5 = 0 Byte 6 = 8 Byte 7 = 0 + + created 05-11-2022 by Stephan Martin (designer2k2) +*/ + +#include "driver/twai.h" + +//Pins used to connect to CAN bus transceiver: +#define rxPin 21 +#define txPin 22 + +void setup() { + // Start Serial: + Serial.begin(115200); + + //Initialize configuration structures using macro initializers + twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)txPin, (gpio_num_t)rxPin, TWAI_MODE_LISTEN_ONLY); + twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS(); //Look in the api-reference for other speed sets. + 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"); + } else { + Serial.println("Failed to install driver"); + return; + } + + //Start TWAI driver + if (twai_start() == ESP_OK) { + Serial.println("Driver started"); + } else { + Serial.println("Failed to start driver"); + return; + } + + //Reconfigure alerts to detect Bus-Off error and RX queue full states + uint32_t alerts_to_enable = TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL; + if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) { + Serial.println("CAN Alerts reconfigured"); + } else { + Serial.println("Failed to reconfigure alerts"); + } + +} + +void loop() { + //Check if alert happened + uint32_t alerts_triggered; + twai_read_alerts(&alerts_triggered, 1); + if (alerts_triggered & TWAI_ALERT_ERR_PASS) { + Serial.println("Alert: TWAI controller has become error passive."); + } else if (alerts_triggered & TWAI_ALERT_BUS_ERROR) { + Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus."); + } else if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) { + Serial.println("Alert: The RX queue is full causing a received frame to be lost."); + } + + //Wait for message to be received: + twai_message_t message; + if (twai_receive(&message, pdMS_TO_TICKS(1000)) == ESP_OK) { + Serial.println("Message received"); + } else { + Serial.println("No message received"); + return; + } + + //Process received message + if (message.extd) { + Serial.println("Message is in Extended Format"); + } else { + Serial.println("Message is in Standard Format"); + } + Serial.printf("ID is %x\n", message.identifier); + if (!(message.rtr)) { + for (int i = 0; i < message.data_length_code; i++) { + Serial.printf("Byte %d = %x ", i, message.data[i]); + } + Serial.println(""); + } + +} From a4c26a6eef0962fa1f2a4fc7d30cecad61cf2bfe Mon Sep 17 00:00:00 2001 From: Stephan Martin Date: Mon, 7 Nov 2022 17:29:53 +0100 Subject: [PATCH 2/3] Fix example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use pdMS_TO_TICKS for twai_read_alerts, format specifier on hex byte info, and dedicated if´s instead of else if on alerts to show multiple errors. --- .../ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino index 63bb6f4db22..472b02234c0 100644 --- a/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino +++ b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino @@ -62,12 +62,14 @@ void setup() { void loop() { //Check if alert happened uint32_t alerts_triggered; - twai_read_alerts(&alerts_triggered, 1); + twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(1)); if (alerts_triggered & TWAI_ALERT_ERR_PASS) { Serial.println("Alert: TWAI controller has become error passive."); - } else if (alerts_triggered & TWAI_ALERT_BUS_ERROR) { + } + if (alerts_triggered & TWAI_ALERT_BUS_ERROR) { Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus."); - } else if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) { + } + if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) { Serial.println("Alert: The RX queue is full causing a received frame to be lost."); } @@ -89,7 +91,7 @@ void loop() { Serial.printf("ID is %x\n", message.identifier); if (!(message.rtr)) { for (int i = 0; i < message.data_length_code; i++) { - Serial.printf("Byte %d = %x ", i, message.data[i]); + Serial.printf("Byte %d = %02x ", i, message.data[i]); } Serial.println(""); } From a46fed0d2ee2107f7b8cf168a85c5fc5e5d1662b Mon Sep 17 00:00:00 2001 From: Stephan Martin Date: Fri, 18 Nov 2022 20:24:34 +0100 Subject: [PATCH 3/3] More context to alerts by adding twai_status_info_t Reading the twai status help to understand why certain alerts happen Update as requested - capitals for macros - using TWAI_ALERT_RX_DATA for polling - parsing in static function - (shortened output to speed up output) move function above loop, define before use --- .../examples/TWAI/TWAIreceive/TWAIreceive.ino | 88 +++++++++++-------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino index 472b02234c0..ebbf2f5d1aa 100644 --- a/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino +++ b/libraries/ESP32/examples/TWAI/TWAIreceive/TWAIreceive.ino @@ -9,31 +9,40 @@ The API gives other possible speeds and alerts: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html - Example output: + Example output from a can bus message: -> Message received -> Message is in Standard Format - -> ID is 604 - -> Byte 0 = 0 Byte 1 = f Byte 2 = 13 Byte 3 = 2 Byte 4 = 0 Byte 5 = 0 Byte 6 = 8 Byte 7 = 0 + -> ID: 604 + -> Byte: 0 = 00, 1 = 0f, 2 = 13, 3 = 02, 4 = 00, 5 = 00, 6 = 08, 7 = 00 + + Example output with alerts: + -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus. + -> Bus error count: 171 + -> Alert: The RX queue is full causing a received frame to be lost. + -> RX buffered: 4 RX missed: 46 RX overrun 0 created 05-11-2022 by Stephan Martin (designer2k2) */ #include "driver/twai.h" -//Pins used to connect to CAN bus transceiver: -#define rxPin 21 -#define txPin 22 +// Pins used to connect to CAN bus transceiver: +#define RX_PIN 21 +#define TX_PIN 22 + +// Intervall: +#define POLLING_RATE_MS 1000 void setup() { // Start Serial: Serial.begin(115200); - //Initialize configuration structures using macro initializers - twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)txPin, (gpio_num_t)rxPin, TWAI_MODE_LISTEN_ONLY); + // Initialize configuration structures using macro initializers + twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_LISTEN_ONLY); twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS(); //Look in the api-reference for other speed sets. twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); - //Install TWAI driver + // Install TWAI driver if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) { Serial.println("Driver installed"); } else { @@ -41,7 +50,7 @@ void setup() { return; } - //Start TWAI driver + // Start TWAI driver if (twai_start() == ESP_OK) { Serial.println("Driver started"); } else { @@ -49,8 +58,8 @@ void setup() { return; } - //Reconfigure alerts to detect Bus-Off error and RX queue full states - uint32_t alerts_to_enable = TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL; + // Reconfigure alerts to detect frame receive, Bus-Off error and RX queue full states + uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL; if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) { Serial.println("CAN Alerts reconfigured"); } else { @@ -59,41 +68,50 @@ void setup() { } +static void handle_rx_message(twai_message_t& message) { + // Process received message + if (message.extd) { + Serial.println("Message is in Extended Format"); + } else { + Serial.println("Message is in Standard Format"); + } + Serial.printf("ID: %x\nByte:", message.identifier); + if (!(message.rtr)) { + for (int i = 0; i < message.data_length_code; i++) { + Serial.printf(" %d = %02x,", i, message.data[i]); + } + Serial.println(""); + } +} + void loop() { - //Check if alert happened + // Check if alert happened uint32_t alerts_triggered; - twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(1)); + twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(POLLING_RATE_MS)); + twai_status_info_t twaistatus; + twai_get_status_info(&twaistatus); + + // Handle alerts if (alerts_triggered & TWAI_ALERT_ERR_PASS) { Serial.println("Alert: TWAI controller has become error passive."); } if (alerts_triggered & TWAI_ALERT_BUS_ERROR) { Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus."); + Serial.printf("Bus error count: %d\n", twaistatus.bus_error_count); } if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) { Serial.println("Alert: The RX queue is full causing a received frame to be lost."); + Serial.printf("RX buffered: %d\t", twaistatus.msgs_to_rx); + Serial.printf("RX missed: %d\t", twaistatus.rx_missed_count); + Serial.printf("RX overrun %d\n", twaistatus.rx_overrun_count); } - //Wait for message to be received: - twai_message_t message; - if (twai_receive(&message, pdMS_TO_TICKS(1000)) == ESP_OK) { - Serial.println("Message received"); - } else { - Serial.println("No message received"); - return; - } - - //Process received message - if (message.extd) { - Serial.println("Message is in Extended Format"); - } else { - Serial.println("Message is in Standard Format"); - } - Serial.printf("ID is %x\n", message.identifier); - if (!(message.rtr)) { - for (int i = 0; i < message.data_length_code; i++) { - Serial.printf("Byte %d = %02x ", i, message.data[i]); + // Check if message is received + if (alerts_triggered & TWAI_ALERT_RX_DATA) { + // One or more messages received. Handle all. + twai_message_t message; + while (twai_receive(&message, 0) == ESP_OK) { + handle_rx_message(message); } - Serial.println(""); } - }