Skip to content

fix speed halved in ESP32-WROOM-32E module #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
# Arduino Library for the ESP32 CAN Bus (ESP32-Arduino-CAN)

## Features

* Support the CAN Bus from the ESP32 (SJA1000)
* CAN Messages send and receive
* Various Bus speeds
* Standard and Extended Frames
* CAN Message Filter

## V2.0
This is a rewrite of the original library created by [miwagner](https://github.com/miwagner/ESP32-Arduino-CAN). The old version of this library used registry commands to configure the TWAI[^1] peripheral and has not been updated in years. Newer versions of the Espressif IDF have built in functions to configure the TWAI peripheral that are more reliable. V2.0 of this library incorporates these new IDF functions in the original function calls of the ESP32-Arduino-CAN library.

## Features
* Easily configure the ESP32 TWAI[^1] peripheral
* Send and receive CAN Bus messages
* Various bus speeds
* Standard (11bit) and extended (29bit) frames
* ~~CAN Message Filter~~

## Third Party Components
## Usage
See the examples in the [/examples](examples) folder.

- Arduino-ESP32-CAN-Demo
- Arduino CAN Demo from [iotsharing.com - nhatuan84](https://github.com/nhatuan84/arduino-esp32-can-demo)
## Espressif IDF Documentation
The Espressif IDF documentation at the link below should be reference first if you encounter any errors. Make sure you are using the most recent IDF version, V5.0 when writing this.

- ESPCan Driver
- Base CAN Driver from [Thomas Barth](https://github.com/ThomasBarth/ESP32-CAN-Driver) and [Nayar Systems](https://github.com/nayarsystems/ESP32-CAN-Driver)
- General [Component CAN Driver Pack](https://github.com/ESP32DE/ESP32-CAN-Driver/tree/Component_CAN_Driver_Pack) Work for ESP-IDF with menuconfig from [rudi ;-)](http://esp32.de)
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html#examples

## Usage
## TODO
- [x] Advanced example with RTOS tasks
- [x] Release to main branch, no push to miwagner version
- [ ] Implement CAN Message Filter

See the examples in the [/examples](examples) folder.
[^1]: TWAI is the name that Esperssif uses for the CAN peripheral. It stands for *two wire automotive interface*
65 changes: 0 additions & 65 deletions examples/esp32can_basic/esp32can_basic.ino

This file was deleted.

66 changes: 0 additions & 66 deletions examples/esp32can_filter/esp32can_filter.ino

This file was deleted.

46 changes: 0 additions & 46 deletions examples/esp32can_mirror/esp32can_mirror.ino

This file was deleted.

37 changes: 37 additions & 0 deletions examples/esp32can_receive/esp32can_receive.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* ESP32 Arduino CAN Receive Basic Demo
* This example will receive messages on the CAN bus
*
* An external transceiver is required and should be connected
* to the CAN_tx and CAN_rx gpio pins specified by CANInit. Be sure
* to use a 3.3V compatable transceiver such as the SN65HVD23x
*
*/

#include <Arduino.h>
#include <ESP32CAN.h>

void setup() {
Serial.begin(115200);
Serial.println("ESP32-Arduino-CAN Receive Basic Demo");

/* initialize and start, use pin 5 as CAN_tx and pin 4 as CAN_rx, CAN bus is set to 500kbps */
ESP32Can.CANInit(GPIO_NUM_5, GPIO_NUM_4, ESP32CAN_SPEED_500KBPS);
}

void loop() {
twai_message_t rx_frame;

if (ESP32CAN_OK == ESP32Can.CANReadFrame(&rx_frame)) { /* only print when CAN message is received*/
Serial.print(rx_frame.identifier, HEX); /* print the CAN ID*/
Serial.print(" ");
Serial.print(rx_frame.data_length_code); /* print number of bytes in data frame*/

for (int i=0; i<rx_frame.data_length_code; i++) { /* print the data frame*/
Serial.print(rx_frame.data[i], HEX);
}

Serial.println();
}

delay(1000);
}
112 changes: 112 additions & 0 deletions examples/esp32can_rtos/esp32can_rtos.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* ESP32 Arduino CAN RTOS Example
* This example will send and receive messages on the CAN bus using RTOS tasks
*
* When controlling a device over CAN bus that device may expect a CAN message to be received at a specific frequency.
* Using RTOS tasks simplifies sending dataframes and makes the timing more consistent.
*
* An external transceiver is required and should be connected
* to the CAN_tx and CAN_rx gpio pins specified by CANInit. Be sure
* to use a 3.3V compatable transceiver such as the SN65HVD23x
*
*/

#include <Arduino.h>
#include <ESP32CAN.h>

/* RTOS priorities, higher number is more important */
#define CAN_TX_PRIORITY 3
#define CAN_RX_PRIORITY 1

#define CAN_TX_RATE_ms 500
#define CAN_RX_RATE_ms 1000

/* can frame to send */
twai_message_t tx_frame;

/* CAN RTOS callback functions */
void canSend(void *pvParameters);
void canReceive(void *pvParameters);

/* CAN RTOS task handles */
static TaskHandle_t canTxTask = NULL;
static TaskHandle_t canRxTask = NULL;

void setup() {
Serial.begin(115200);
Serial.println("ESP32-Arduino-CAN RTOS Example");

/* initialize and start, use pin 5 as CAN_tx and pin 4 as CAN_rx, CAN bus is set to 500kbps */
ESP32Can.CANInit(GPIO_NUM_5, GPIO_NUM_4, ESP32CAN_SPEED_500KBPS);

/* setup can send RTOS task */
xTaskCreatePinnedToCore(canSend, /* callback function */
"CAN TX", /* name of task */
1024, /* stack size (bytes in ESP32, words in FreeRTOS */
NULL, /* parameter to pass to function */
CAN_TX_PRIORITY, /* task priority (0 to configMAX_PRIORITES - 1 */
&canTxTask, /* task handle */
1); /* CPU core, Arduino runs on 1 */

/* setup can receive RTOS task */
xTaskCreatePinnedToCore(canReceive, /* callback function */
"CAN RX", /* name of task */
2048, /* stack size (bytes in ESP32, words in FreeRTOS */
NULL, /* parameter to pass to function */
CAN_RX_PRIORITY, /* task priority (0 to configMAX_PRIORITES - 1 */
&canRxTask, /* task handle */
1); /* CPU core, Arduino runs on 1 */


/* setup can send frame */
tx_frame.extd = 0; /* standard 11bit ID */
tx_frame.identifier = 0x123; /* CAN ID */
tx_frame.data_length_code = 8; /* 8 bytes of data */
for (int8_t i= 0; i<8; i++) {
tx_frame.data[i] = 0xFF; /* pad frame with 0xFF */
}
}

void loop() {
/* place time in seconds into first two bytes of dataframe */
uint16_t time = millis()/1000;
tx_frame.data[0] = highByte(time);
tx_frame.data[1] = lowByte(time);

delay(500);
}

/* CAN Send function called by RTOS can send task */
void canSend(void *pvParameters) {
TickType_t xLastWakeTime; /* keep track of last time can message was sent */
TickType_t xFrequency = CAN_TX_RATE_ms / portTICK_PERIOD_MS; /* set the transmit frequency */

/* this task will run forever at frequency set above
* to stop this task from running call vTaskSuspend(canTxTask) in the main loop */
for (;;) {
ESP32Can.CANWriteFrame(&tx_frame); /* send dataframe */

vTaskDelayUntil(&xLastWakeTime, xFrequency); /* do something else until it is time to send again */
/* the above delay function was used since it specifies an absolute wake time.
* Make sure the code in the forever for loop can run faster then desired send frequency or this task will take all of the CPU time available */
}
}

void canReceive(void *pvParameters) {
const TickType_t xDelay = CAN_RX_RATE_ms / portTICK_PERIOD_MS;
twai_message_t rx_frame;

for (;;) {
if (ESP32CAN_OK == ESP32Can.CANReadFrame(&rx_frame)) { /* only print when CAN message is received*/
Serial.print(rx_frame.identifier, HEX); /* print the CAN ID*/
Serial.print(" ");
Serial.print(rx_frame.data_length_code); /* print number of bytes in data frame*/

for (int i=0; i<rx_frame.data_length_code; i++) { /* print the data frame*/
Serial.print(rx_frame.data[i], HEX);
}

Serial.println();
}
vTaskDelay(xDelay); /* do something else until it is time to receive again. This is a simple delay task. */
}
}
Loading