Create esp32can_rtos.ino
This commit is contained in:
parent
dde827a338
commit
8e59fdeac9
1 changed files with 112 additions and 0 deletions
112
examples/esp32can_rtos/esp32can_rtos.ino
Normal file
112
examples/esp32can_rtos/esp32can_rtos.ino
Normal file
|
@ -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…
Reference in a new issue