From b859dd8531c7bd1e8b2ea48f8397cd1189020e6f Mon Sep 17 00:00:00 2001
From: Stephan Martin <designer2k2@gmail.com>
Date: Tue, 27 Jun 2023 20:28:17 +0200
Subject: [PATCH] Add TWAI transmit example

Example showing how to transmit messages using the TWAI interface and a CAN transceiver.
---
 .../TWAI/TWAItransmit/TWAItransmit.ino        | 123 ++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 libraries/ESP32/examples/TWAI/TWAItransmit/TWAItransmit.ino

diff --git a/libraries/ESP32/examples/TWAI/TWAItransmit/TWAItransmit.ino b/libraries/ESP32/examples/TWAI/TWAItransmit/TWAItransmit.ino
new file mode 100644
index 00000000000..df0f1cfd266
--- /dev/null
+++ b/libraries/ESP32/examples/TWAI/TWAItransmit/TWAItransmit.ino
@@ -0,0 +1,123 @@
+/* ESP32 TWAI transmit example.
+  This transmits a message every second.
+
+  Connect a CAN bus transceiver to the RX/TX pins.
+  For example: SN65HVD230
+
+  The API gives other possible speeds and alerts:
+  https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html
+
+  created 27-06-2023 by Stephan Martin (designer2k2)
+*/
+
+#include "driver/twai.h"
+
+// Pins used to connect to CAN bus transceiver:
+#define RX_PIN 21
+#define TX_PIN 22
+
+// Intervall:
+#define TRANSMIT_RATE_MS 1000
+
+#define POLLING_RATE_MS 1000
+
+static bool driver_installed = false;
+
+unsigned long previousMillis = 0;  // will store last time a message was send
+
+
+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)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_NORMAL);
+  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 TX alerts and Bus-Off errors
+  uint32_t alerts_to_enable = TWAI_ALERT_TX_IDLE | TWAI_ALERT_TX_SUCCESS | TWAI_ALERT_TX_FAILED | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR;
+  if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
+    Serial.println("CAN Alerts reconfigured");
+  } else {
+    Serial.println("Failed to reconfigure alerts");
+    return;
+  }
+
+  // TWAI driver is now successfully installed and started
+  driver_installed = true;
+}
+
+static void send_message() {
+  // Send message
+
+  // Configure message to transmit
+  twai_message_t message;
+  message.identifier = 0x0F6;
+  message.data_length_code = 4;
+  for (int i = 0; i < 4; i++) {
+    message.data[i] = 0;
+  }
+
+  // Queue message for transmission
+  if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
+    printf("Message queued for transmission\n");
+  } else {
+    printf("Failed to queue message for transmission\n");
+  }
+}
+
+void loop() {
+  if (!driver_installed) {
+    // Driver not installed
+    delay(1000);
+    return;
+  }
+  // Check if alert happened
+  uint32_t alerts_triggered;
+  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_TX_FAILED) {
+    Serial.println("Alert: The Transmission failed.");
+    Serial.printf("TX buffered: %d\t", twaistatus.msgs_to_tx);
+    Serial.printf("TX error: %d\t", twaistatus.tx_error_counter);
+    Serial.printf("TX failed: %d\n", twaistatus.tx_failed_count);
+  }
+  if (alerts_triggered & TWAI_ALERT_TX_SUCCESS) {
+    Serial.println("Alert: The Transmission was successful.");
+    Serial.printf("TX buffered: %d\t", twaistatus.msgs_to_tx);
+  }
+
+  // Send message
+  unsigned long currentMillis = millis();
+  if (currentMillis - previousMillis >= TRANSMIT_RATE_MS) {
+    previousMillis = currentMillis;
+    send_message();
+  }
+}