CAPL Script

CAN Message Timestamp Update

This example demonstrates how to update and display timestamps for received CAN messages in real-time.

Overview

The script monitors all CAN messages and updates a timestamp each time a message is received on CAN channel 1. This is useful for debugging and monitoring message traffic.

Complete Example

/* File: TimestampUpdate.capl */

/* Variables */
variables {
    // Timestamp tracking
    long lastTimestamp;
    long currentTimestamp;
    long timeDifference;

    // Message counter
    int messageCount = 0;

    // Timing control
    msTimer updateTimer;
    const int UPDATE_INTERVAL = 100; // Update every 100ms
}

/* Initialization */
on start {
    write("Starting CAN Timestamp Monitor");
    lastTimestamp = 0;
    messageCount = 0;

    // Start update timer
    setTimer(updateTimer, UPDATE_INTERVAL);
}

/* Main event handler for all CAN1 messages */
on message CAN1::* {
    messageCount++;

    // Get current system time in microseconds
    currentTimestamp = timeNowUs();

    // Calculate time difference from last message
    if (lastTimestamp > 0) {
        timeDifference = currentTimestamp - lastTimestamp;
    } else {
        timeDifference = 0;
    }

    // Update last timestamp
    lastTimestamp = currentTimestamp;

    // Display message information
    write("=== Message #%d ===", messageCount);
    write("ID: 0x%03X (%d)", this.ID, this.ID);
    write("DLC: %d bytes", this.DLC);
    write("Timestamp: %d μs", currentTimestamp);
    write("Time since last: %d μs", timeDifference);

    // Display data bytes
    write("Data: ");
    int i;
    for (i = 0; i < this.DLC; i++) {
        write("  Byte %d: 0x%02X (%d)", i, this.byte(i), this.byte(i));
    }
    write("==================");
}

/* Periodic update */
on timer updateTimer {
    float frequency;
    float messageRate;

    if (timeDifference > 0) {
        frequency = 1000000.0 / timeDifference; // Convert to Hz
        write("Current frequency: %.2f Hz", frequency);
    }

    // Calculate messages per second (based on last 1 second)
    messageRate = messageCount / (UPDATE_INTERVAL / 1000.0);
    write("Average rate: %.2f msg/s", messageRate);

    // Reset counter for next interval
    messageCount = 0;

    // Restart timer
    setTimer(updateTimer, UPDATE_INTERVAL);
}

/* Cleanup */
on stop {
    write("Stopping CAN Timestamp Monitor");
    write("Final message count: %d", messageCount);
}

Key Functions Used

timeNowUs()

Returns the current system time in microseconds. This provides high-resolution timing for precise measurements.

long timestamp = timeNowUs();

setTimer(timer, interval)

Sets a timer to trigger after a specified interval in milliseconds.

setTimer(updateTimer, 100); // Trigger after 100ms

on timer timerName

Event handler that executes when the specified timer expires.

on timer updateTimer {
    // Timer logic here
}

Output Example

When you run this script, you'll see output similar to:

=== Message #1 ===
ID: 0x100 (256)
DLC: 8 bytes
Timestamp: 15478923 μs
Time since last: 0 μs
Data:
  Byte 0: 0x01 (1)
  Byte 1: 0x02 (2)
  Byte 2: 0x03 (3)
  Byte 3: 0x04 (4)
  Byte 4: 0x05 (5)
  Byte 5: 0x06 (6)
  Byte 6: 0x07 (7)
  Byte 7: 0x08 (8)
==================

Use Cases

This example is useful for:

  1. Message Frequency Monitoring: Track how often messages are transmitted
  2. Timing Analysis: Measure time intervals between messages
  3. Debugging: Verify message reception and timing
  4. Performance Testing: Monitor message rates and throughput
  5. Bus Load Calculation: Determine actual bus utilization

Variations

Log to File Instead of Write Window

on message CAN1::* {
    char logFile[100];
    sysLogWrite(logFile, LOG_MODE_FILE, "ID: 0x%03X", this.ID);
}

Filter Specific Messages

on message CAN1::EngineData {
    // Only process EngineData messages
    write("Engine speed: %d RPM", this.EngineSpeed);
}

Calculate Running Average

variables {
    float frequencyHistory[10];
    int historyIndex = 0;
}

on timer updateTimer {
    frequencyHistory[historyIndex] = frequency;
    historyIndex = (historyIndex + 1) % 10;

    // Calculate average
    float sum = 0;
    int i;
    for (i = 0; i < 10; i++) {
        sum += frequencyHistory[i];
    }
    float average = sum / 10.0;

    write("Average frequency: %.2f Hz", average);
}

Best Practices

  1. Use appropriate timers: Match timer interval to your update needs
  2. Handle edge cases: Check for first message (no previous timestamp)
  3. Performance: Don't do heavy processing in message handlers
  4. Formatting: Use consistent formatting in output
  5. Logging: Consider file logging for long-term monitoring

Next Steps

  • Implement message filtering for specific IDs
  • Add statistical analysis (min, max, average times)
  • Create graphical display of timing data
  • Log data to file for post-processing