Global State Machines in the Variables Block
The BCM tracks state transitions across vehicle subsystemsโsuch as Central Locking, Interior Ambient Lighting, and Hazard Flashers. State variables must persist between event triggers, which means they must be defined in the global `variables { }` section rather than local event handlers.
Variables in CAPL Scripting
CAPL (CAN Application Programming Language) is a programming language used for writing scripts in CANoe and CANalyzer, tools developed by Vector for simulating, testing, and analyzing network communication on CAN networks. CAPL allows users to write scripts to interact with CAN, LIN, and other network protocols, making it an essential tool for automotive engineers working with embedded systems.
What Are Variables in CAPL?
A variable in CAPL is a named storage location that holds a data value. This value can change during the execution of the program. Variables are used to store information such as sensor values, states of a device, timestamps, etc.
Types of Variables in CAPL
Basic Data Types: CAPL supports several primitive data types which are essential for declaring variables:
int: Integer (whole number).
float: Floating-point number.
bool: Boolean value (TRUE or FALSE).
char: Single character.
string: Array of characters (string of text).
long: A larger integer type.
unsigned: Positive-only integer type.
double: Double precision floating-point number.
Special Data Types
enum: A user-defined type with a set of named integer values.
struct: A user-defined composite data type that groups different variables together.
To declare a variable, you use the following syntax
data_type variable_name;
Where data_type is the type of data the variable will store, and variable_name is the name you assign to it.
Example
int counter; // Declares an integer variable called 'counter'
float temperature; // Declares a floating-point variable called 'temperature'
Variable Initialization
You can also initialize a variable with a value at the time of declaration:
int counter = 0; // Integer variable initialized to 0
float temperature = 25.5; // Float variable initialized to 25.5
To assign a value to a variable after its declaration
counter = 10; // Assigns the value 10 to 'counter'
temperature = 30.2; // Assigns the value 30.2 to 'temperature'
Variable Scope
Global variables: These are declared outside of any function, making them accessible throughout the script.
Example:
capl
int globalVar; // Global variable
Local variables: These are declared inside functions and can only be used within the scope of that function.
Example:
capl
void myFunction() {
int localVar = 5; // Local variable inside 'myFunction'
}
Example with Different Types of Variables
// Declaring and initializing variables
int messageCounter = 0; // Integer variable
float voltageLevel = 3.3; // Float variable
bool isEngineRunning = true; // Boolean variable
char deviceStatus = 'A'; // Char variable
string carModel = "Tesla"; // String variable
// Using variables in a function
void onCanMessageReceived() {
messageCounter++; // Incrementing counter when a CAN message is received
if (isEngineRunning) { // Checking if engine is running
voltageLevel = 12.0; // Adjusting voltage level when engine is on
}
}
// Function to print device status
void printDeviceStatus() {
output("Device Status: %c", deviceStatus); // Printing char variable
output("Car Model: %s", carModel); // Printing string variable
}
Enumerations (enum)
Enumerations in CAPL are used to define a type with a set of predefined constants. This is useful for representing state machines, modes, or predefined sets of values.
enum EngineState {
OFF,
IDLE,
RUNNING
};
EngineState currentEngineState = OFF; // Declare an enum variable
Structures (struct)
Structures are used to define custom data types that can hold different types of data together. Each member of a structure can have a different type.
struct VehicleStatus {
bool engineStatus; // Engine running or not
int speed; // Vehicle speed in km/h
float fuelLevel; // Fuel level in percentage
};
VehicleStatus myCarStatus; // Declare a variable of type VehicleStatus
void updateVehicleStatus() {
myCarStatus.engineStatus = true; // Engine is running
myCarStatus.speed = 80; // Speed is 80 km/h
myCarStatus.fuelLevel = 45.5; // Fuel level is 45.5%
}
Variables in CAN Signal Communication
Variables can be linked to CAN signals or message signals. You can assign values to CAN signals, and their values can be monitored or modified.
variables
{
message MyMessage; // Declare a CAN message variable
}
on message MyMessage
{
// Accessing signals in the message
int speed = MyMessage.SignalSpeed; // Retrieve the speed from the CAN message
output("Speed: %d km/h", speed);
}
Useful Built-In Variables and Functions
CAPL provides some built-in functions and variables that make handling data easier, such as the ability to get timestamps, access message data, and more:
GetTime(): Returns the current simulation time.
getSignalValue(): Used to read the value of a signal from a CAN message.
setSignalValue(): Used to write a value to a CAN signal.
variables
{
message MyMessage;
}
on message MyMessage
{
int signalValue = getSignalValue(MyMessage.SignalSpeed); // Get signal value
output("Received Speed: %d km/h", signalValue);
// Modify the signal value
setSignalValue(MyMessage.SignalSpeed, 100);
}
Conclusion
In CAPL, variables are a fundamental concept for storing and manipulating data during the execution of scripts. They allow you to track the state of your system, handle CAN messages, and implement complex logic for testing and simulation. Understanding variable types, scope, and how to use them with CAN signals is key to writing effective CAPL scripts.
- Local variables inside event handlers (e.g. `on message`) lose their value once the handler returns. Never store cumulative counters or state machine states in local variables.
- Variable initialization in the `variables { }` block executes when the measurement starts. Dynamic initializations depending on bus values should be handled in `on start`.
Select your answer for each question below to receive immediate correctness evaluation and in-depth technical rationale.
Declare an enumeration 'enum eVehiclePowerMode { POWER_OFF = 0, POWER_ACCESSORY = 1, POWER_ON = 2, POWER_START = 3 }' and a global state variable. Write an event handler for key press 'p' that cycles through the power modes sequentially and logs the transition.
Verified CAPL implementation:
variables {
enum eVehiclePowerMode {
POWER_OFF = 0,
POWER_ACCESSORY = 1,
POWER_ON = 2,
POWER_START = 3
};
enum eVehiclePowerMode gCurrentPowerMode = POWER_OFF;
}
on key 'p' {
// Cycle to next mode
if (gCurrentPowerMode == POWER_START)
gCurrentPowerMode = POWER_OFF;
else
gCurrentPowerMode = (enum eVehiclePowerMode)(gCurrentPowerMode + 1);
write("Vehicle Power Mode transitioned to: %d", gCurrentPowerMode);
}