High-Frequency Wheel Speed Frame Construction
The ABS module transmits wheel speed data (WheelSpeed_FL, WheelSpeed_FR, WheelSpeed_RL, WheelSpeed_RR) at 10ms intervals on ID 0x1A0 with DLC 8. Each 16-bit word represents speed in 0.01 km/h. In CAPL, constructing and transmitting this frame involves setting the message identifier, DLC, populating the 8 data bytes, and calling `output()`.
Overview & Key Concepts
CAN Messages in CAPL Scripting (CAN Protocol in CAPL)
In CAPL (CAN Application Programming Language), a powerful language for automotive network testing, particularly used in the context of CAN (Controller Area Network) communication, "CAN messages" are a key element in designing tests, simulations, and communications between ECUs (Electronic Control Units). CAPL allows you to simulate CAN networks and exchange messages between ECUs, which is essential for automotive diagnostics, testing, and validation.
Message Types
Standard CAN Message: Identified by an 11-bit identifier.
Extended CAN Message: Identified by a 29-bit identifier.
Working with CAN Messages in CAPL
Defining a CAN Message in CAPL: In CAPL, CAN messages are defined using message keywords and can be interacted with either through predefined or custom CAN message objects. Basic Message Definition capl message TestMessage {
byte data[8]; // 8 bytes of data
}
Sending CAN Messages: You can send CAN messages with the output() function or send predefined messages using the send() function.
Example 1: Sending a Simple CAN Message
capl
variables {
message TestMessage msg; // Define the message variable
}
on start {
// Initialize message data
msg.data[0] = 0x01;
msg.data[1] = 0x02;
msg.data[2] = 0x03;
msg.data[3] = 0x04;
msg.data[4] = 0x05;
msg.data[5] = 0x06;
msg.data[6] = 0x07;
msg.data[7] = 0x08;
// Send message on CAN bus
output(msg);
}
In this example:
A message TestMessage with an array data[8] is created.
The message is populated with hexadecimal values.
The output() function sends the message to the CAN network.
Sending Standard CAN Message Using send(): To send predefined CAN messages like CAN_Msg_1, CAN_Msg_2, etc., you can use the send() function, which works with messages configured in the CAN database (DBC file).
Example 2: Sending a CAN Message from DBC Database
capl
on start {
// Send a message named "EngineData" from the DBC file
send(EngineData);
}
In this case, EngineData is a message defined in the DBC file, and calling send() will transmit the message with all its data fields.
Receiving CAN Messages: You can receive CAN messages by specifying on message for predefined CAN messages or using the message event handler for custom messages.
Example 3: Receiving a CAN Message
capl
on message EngineData {
output("Received Engine Data:");
output("Engine RPM: %d", EngineData.RPM);
output("Engine Temp: %d", EngineData.Temperature);
}
Here:
The on message EngineData handler listens for incoming EngineData messages.
When the message is received, it outputs the RPM and temperature data to the log.
Setting Message Filters: CAPL allows filtering for specific CAN message IDs or certain conditions. Example 4: Filtering CAN Messages capl on message {
if (this.id == 0x100) {
output("Message with ID 0x100 received.");
}
}
In this example:
The on message event will be triggered for any message.
The if statement filters messages based on their ID (in this case, 0x100).
Using Message Timing: You can schedule periodic messages or delay sending messages using timers. Example 5: Periodic Sending of a CAN Message capl variables {
message TestMessage msg;
msTimer timer1;
}
on start {
setTimer(timer1, 1000); // Set a timer for 1000ms (1 second)
}
on timer timer1 {
msg.data[0] = 0xAA;
msg.data[1] = 0xBB;
output(msg); // Send message
setTimer(timer1, 1000); // Reset the timer
}
Here, the message is sent every 1000 milliseconds using a timer.
Single Message Types
Define custom message types in CAPL using message to structure the data you need to send or receive.
CAN Signals
Signals are individual data fields within a CAN message. They represent specific parameters, such as speed, temperature, etc.
Example 6: Defining a Signal and Sending It capl message EngineData {
byte EngineSpeed;
byte EngineTemperature;
}
on start {
EngineData.EngineSpeed = 5000; // RPM
EngineData.EngineTemperature = 90; // Temperature in °C
output(EngineData);
}
This example defines a message EngineData with two signals: EngineSpeed and EngineTemperature.
Extended CAN Messages: Extended messages are supported in CAPL as well. The message ID is 29 bits in this case. Example 7: Sending an Extended CAN Message capl message ExtendedMessage {
byte data[8];
}
on start {
ExtendedMessage msg;
msg.data[0] = 0x01;
msg.data[1] = 0x02;
msg.data[2] = 0x03;
msg.data[3] = 0x04;
msg.data[4] = 0x05;
msg.data[5] = 0x06;
msg.data[6] = 0x07;
msg.data[7] = 0x08;
msg.id = 0x18FF0100; // 29-bit ID for extended message
output(msg);
}
Conclusion
CAPL provides a powerful, flexible way to simulate, send, and receive CAN messages. It allows for detailed control over CAN network communication, enabling testing, simulation, and diagnostics of automotive systems. By combining message structures, signal handling, and timing, CAPL scripts can emulate real-world CAN networks and help automate testing processes.
- Forgetting to set `msg.dlc` defaults to 0 or uninitialized length in raw messages, resulting in truncated frames on the bus.
- Extended 29-bit CAN IDs must have the extended flag set or use the 'x' suffix (e.g. `message 0x18FEF100x myMsg;`).
Select your answer for each question below to receive immediate correctness evaluation and in-depth technical rationale.
Write a CAPL script that sets up a 10ms cyclic timer to transmit CAN message ID 0x1A0 (DLC 8). In each cycle, pack 16-bit speed values for Front-Left (50 km/h = 5000 raw) and Front-Right (50 km/h = 5000 raw) into bytes 0-3, increment an alive counter in byte 7 (0..15), and call `output()`.
Verified CAPL implementation:
variables {
message 0x1A0 msgABS;
msTimer tABS_Cycle;
byte gAliveCounter = 0;
}
on start {
msgABS.dlc = 8;
setTimer(tABS_Cycle, 10); // 10ms periodic cycle
}
on timer tABS_Cycle {
word rawSpeed = 5000; // 50.00 km/h
// Front-Left Wheel Speed (Bytes 0-1, Big Endian)
msgABS.byte(0) = (rawSpeed >> 8) & 0xFF;
msgABS.byte(1) = rawSpeed & 0xFF;
// Front-Right Wheel Speed (Bytes 2-3, Big Endian)
msgABS.byte(2) = (rawSpeed >> 8) & 0xFF;
msgABS.byte(3) = rawSpeed & 0xFF;
// Alive counter in byte 7
msgABS.byte(7) = gAliveCounter;
gAliveCounter = (gAliveCounter + 1) % 16;
output(msgABS);
setTimer(tABS_Cycle, 10); // Re-arm timer
}