| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|---|
TWAI Network Example
This example demonstrates TWAI (Two-Wire Automotive Interface) network communication using the ESP-IDF TWAI driver. It consists of two programs that showcase different aspects of TWAI bus communication.
Overview
Programs
- twai_sender: Sends periodic heartbeat messages and large data packets
- twai_listen_only: Monitors specific message ID using a filter
Key Features
- Event-driven message handling with callbacks
- Message filtering using acceptance filters in listen-only mode
- Single/Burst data transmission and reception
- Local transmit queue prioritization for urgent frames
- Real-time bus error and node status reporting
Hardware Setup
Wiring
For multi-device testing:
- Connect TWAI transceivers to each ESP32xx
- Wire TWAI_H and TWAI_L between all devices using line topology
- Add 120Ω termination resistors at both ends of the bus
For single-device testing, enable self_test mode in the sender.
GPIO Configuration
The GPIO pins can be configured using menuconfig:
idf.py menuconfig
Navigate to: Example Configuration → Configure the following:
- TWAI TX GPIO Num: GPIO pin for TWAI TX
- TWAI RX GPIO Num: GPIO pin for TWAI RX
Default configuration:
#define TWAI_TX_GPIO GPIO_NUM_4
#define TWAI_RX_GPIO GPIO_NUM_5
#define TWAI_BITRATE 1000000 // 1 Mbps
Message Types
| ID | Type | Frequency | Size | Description |
|---|---|---|---|---|
| 0x7FF | Heartbeat | 1 Hz | 8 bytes | Timestamp data |
| 0x100 | Data | Every 10s | 1000 bytes | Test data (125 frames) |
| 0x080 | Emergency | During data burst | 0 bytes | High-priority frame inserted into the transmit queue |
Building and Running
Build each program (sender, listen_only):
Enter the sub-application directory and run:
idf.py set-target esp32 build flash monitor
Expected Output
Sender
===================TWAI Sender Example Starting...===================
I (xxx) twai_sender: TWAI Sender started successfully
I (xxx) twai_sender: Sending messages with IDs: 0x100 (data), 0x7FF (heartbeat)
I (xxx) twai_sender: Sending heartbeat message: 1234567890
I (xxx) twai_sender: Sending packet of 1000 bytes in 125 frames
I (xxx) twai_sender: Inserting Emergency message: 0x080
Listen-Only Monitor
===================TWAI Listen Only Example Starting...===================
I (xxx) twai_listen: Buffer initialized: 200 slots for burst data
I (xxx) twai_listen: TWAI node created
I (xxx) twai_listen: Filter enabled for ID: 0x100 Mask: 0x7F0
I (xxx) twai_listen: TWAI start listening...
I (xxx) twai_listen: RX: 100 [8] 0 0 0 0 0 0 0 0
I (xxx) twai_listen: RX: 100 [8] 1 1 1 1 1 1 1 1
Implementation Details
Message Buffering
Each program uses a buffer pool to handle incoming messages efficiently:
- Sender: Small buffer for transmission completion tracking
- Listen-Only: 100-slot buffer for monitoring filtered traffic
Operating Modes
- Normal Mode (Sender): Participates in bus communication, sends ACK frames
- Listen-Only Mode (Monitor): Receives filtered messages without transmitting anything
Transmit Queue Priority
The sender inserts an emergency frame while a burst of data frames is pending in the transmit queue:
twai_frame_t emergency_frame = {
.header.id = TWAI_EMERGENCY_ID,
.tx_queue_priority = 10,
};
The tx_queue_priority field controls the driver's local transmit queue. Frames with a higher priority value are dequeued before lower-priority frames, while frames with the same priority keep their enqueue order. This allows urgent frames, such as the emergency frame in this example, to be transmitted before queued burst data frames.
The local queue priority is separate from TWAI bus arbitration. Once a frame is sent to the bus, arbitration is still determined by the frame ID, where lower IDs have higher bus priority.
Message Filtering
The listen-only monitor uses hardware acceptance filters to receive only specific message IDs:
twai_mask_filter_config_t data_filter = {
.id = TWAI_DATA_ID,
.mask = 0x7F0, // Match high 7 bits of the ID, ignore low 4 bits
.is_ext = false, // Receive only standard ID
};
Error Handling
- Bus error logging and status monitoring
Configuration
Customizing Buffer Sizes
Adjust buffer sizes in each program as needed:
#define POLL_DEPTH 200 // Listen-only buffer size
Changing Message IDs
Update the message ID definitions:
#define TWAI_DATA_ID 0x100
#define TWAI_HEARTBEAT_ID 0x7FF
#define TWAI_EMERGENCY_ID 0x080
Use Cases
This example is suitable for:
- Learning TWAI bus communication
- Testing TWAI network setups
- Developing custom TWAI protocols
- Bus monitoring and debugging
- Prototyping automotive communication systems
Troubleshooting
No Communication
- Check GPIO pin connections
- Verify bitrate settings match between devices
- Ensure proper bus termination
Buffer Overflows
- Increase buffer size (
POLL_DEPTH) - Reduce bus message transmission rate
- Optimize message processing code
Bus Errors
- Check physical bus wiring
- Verify termination resistors (120Ω at each end)
- Monitor error counters with
twai_node_get_info()