The problem
CAN guarantees that the highest-priority message wins arbitration, but lower-priority messages can wait behind others. Designers of EV networks must make sure safety-relevant messages meet deadlines as bus load grows. This project measures real latency distributions and checks how well the classic analytical model predicts them.
Objectives
- Define an EV-like message set with IDs, periods and lengths.
- Calculate bus load and worst-case response times analytically.
- Measure queuing and transmission latency with hardware timestamps.
- Study the effect of load, priority and transmit-mailbox handling on latency.
- Compare measured worst cases with analytical bounds.
What you need
From the EV Embedded Development Kit
- STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
- CAN bus interface with screw terminal
- Serial UART interface
- Analog potentiometer input
- 16×2 LCD with contrast control
Software
- STM32CubeIDE
- Embedded C with STM32 HAL
- Python with python-can, NumPy, pandas and matplotlib
Extra parts
- A second DIYguru EV Embedded Development Kit — Latency between nodes needs at least two nodes; the board has one CAN node. The second kit receives and timestamps frames and generates competing traffic.
- USB-CAN adapter for the PC — Acts as a third node to add background traffic at controlled load levels and to log the bus for cross-checking.
- Low-cost USB logic analyser (optional) — To capture CAN TX pins and GPIO markers with a common timebase as an independent check of the firmware timestamps.
Key concepts
- Bus load
- The fraction of time the bus is busy: the sum over messages of frame bits divided by period, divided by the bit rate. A standard 8-byte frame is 111 bits without stuffing and up to 135 bits with worst-case stuffing, including interframe space.
- Response time
- Time from when a message is queued to when it has been completely transmitted: queuing jitter, blocking by a lower-priority frame already on the bus, interference from higher-priority frames and its own transmission time.
- Worst-case response-time analysis
- An iterative calculation that bounds the response time of each message from the periods, lengths and priorities of all others. The corrected analysis by Davis and colleagues fixed an optimistic flaw in earlier versions.
- Priority inversion in mailboxes
- bxCAN has three transmit mailboxes. If a low-priority frame occupies a mailbox and the driver does not let a higher-priority frame overtake it, the high-priority frame can be delayed beyond the analysis.
Step-by-step guide
- 1
Define the message set and analysis
Create an EV-like message set of 15 to 25 messages: BMS status at 10 ms and 100 ms, motor controller commands at 10 ms, charger status, dashboard data and diagnostics, with lengths and IDs chosen by criticality. Calculate bus load at 500 kbit/s and implement the response-time analysis in Python. Scale periods to produce load levels from 20 to 80 per cent.
Checkpoint: A message table and computed worst-case response time for every message at each load level.
- 2
Build the bench
Connect both kits and the USB-CAN adapter on one twisted-pair bus, terminated at the two ends, with about 60 Ω between CAN_H and CAN_L when unpowered. Enable CAN and UART DIP switches. Configure bxCAN at 500 kbit/s on all nodes. Node A transmits the message set; node B timestamps reception; the adapter adds background load. Use a shared header of message definitions for all firmware so every node agrees on IDs.
Checkpoint: All three nodes exchange frames with zero error counters.
- 3
Set up timestamping
Enable time-triggered communication mode in the bxCAN configuration so the peripheral captures a 16-bit bit-time counter value at start of frame into each mailbox and FIFO. On node A also record a 1 MHz timer value when each frame is queued. Use HAL_CAN_GetTxTimestamp and the receive header timestamp, and extend the 16-bit values with an overflow counter. Check the counter's resolution and wrap time at 500 kbit/s and plan your overflow handling.
Checkpoint: Timestamps for a single periodic frame show the expected period with microsecond-level consistency.
- 4
Relate queue time to transmission
For each frame on node A, compute queuing delay (queue to start of frame) and transmission time (start of frame to end, from the frame length). Cross-check node A's start-of-frame stamp with node B's reception stamp using a periodic synchronisation frame, or with the optional logic analyser capturing both TX pins and a GPIO marker. Report the measured uncertainty of the method so later comparisons can account for it.
Checkpoint: Independent checks agree with firmware timestamps within a few microseconds.
- 5
Implement the transmit strategies
Write two transmit drivers on node A: a naive FIFO that queues frames into any free mailbox in order, and a priority-aware driver that keeps a software priority queue and aborts a lower-priority pending mailbox with HAL_CAN_AbortTxRequest when a higher-priority frame needs it. Enable transmit-mailbox priority by identifier in the bxCAN configuration for the second driver. Measure the extra CPU time the priority-aware driver needs.
Checkpoint: Both drivers send the full message set without loss at low load.
- 6
Run the load sweep
For each load level from 20 to 80 per cent, run both drivers for at least ten minutes, logging every frame's queue, start-of-frame and reception times over UART. Keep background traffic from the adapter consistent between runs. Record error counters and any missed deadlines. Run each configuration twice on different days to check repeatability, and keep the firmware build identical across runs. If logging over UART cannot keep up at high load, buffer the timestamps in RAM and send them after the run instead.
Checkpoint: A complete dataset for every load level and driver, with no logging losses.
- 7
Analyse distributions
In Python, compute for each message the minimum, mean, 99th percentile and maximum response time. Plot response time against priority and load. Compare the measured maximum with the analytical worst case; it should never exceed the bound unless the driver causes priority inversion or the model misses something. Also plot histograms for the highest and lowest priority messages at each load, which show how the spread of latency grows for low-priority messages while high-priority ones stay tightly bounded. Mark each message's deadline on the plots.
Checkpoint: Plots of measured versus analytical response time for each message and load level.
- 8
Investigate differences
Explain any measured value above the bound: mailbox priority inversion with the naive driver, interrupt latency, or bit stuffing assumptions. Explain how far typical values sit below the bound, and why the worst case is rarely observed. Add release jitter from your task timing into the analysis and recompute. Where possible, reproduce each unexpected result with a small targeted test, for example two messages only, to confirm the explanation before including it in the report.
Checkpoint: A written explanation for every case where measurement and analysis differ significantly.
- 9
Conclusions and design guidance
From the results, recommend a maximum safe bus load for this message set, the importance of priority-aware transmit drivers, and ID allocation rules for EV messages. Document the bench, timestamp method, analysis code and results. Present the guidance as a short checklist an EV network designer could follow, such as how to assign IDs by deadline, when to choose a priority-aware driver and how much headroom to leave. Include all analysis code and raw logs in the repository so others can reproduce the plots.
Checkpoint: A report with quantified design recommendations supported by both measurement and analysis.
Testing & validation
- Timestamp method cross-checked against an independent capture.
- Measured bus load against calculated load.
- Measured maximum response time against the analytical bound for every message.
- Naive versus priority-aware drivers at each load level.
Expected results
A measured latency dataset and validated response-time model for an EV-like message set, showing how load, priority and driver design affect latency.
Research angle for your M.Tech thesis
Research questions: how close do measured worst-case latencies come to analytical bounds on a low-cost bench, and how much do driver design and release jitter matter? Metrics: response-time distributions, maximum versus bound, deadline misses, bus load. Baseline: classic response-time analysis with and without jitter terms. A careful, reproducible comparison of analysis and measurement for an EV message set, with open data, is suitable for an M.Tech thesis and could support a conference paper.
Take it further
- Inject errors to study retransmission effects on latency.
- Add a third kit to study multi-node transmit queuing.
- Compare with an offset assignment that staggers message release times.
- Model the same message set on CAN FD in simulation and compare.
Viva and review questions
Why can a high-priority message still be delayed?
It must wait for a frame already being transmitted to finish (blocking), and it can be delayed by higher-priority messages and by driver mailbox handling.
Why does bit stuffing matter for latency analysis?
Stuff bits lengthen frames depending on data, so the analysis must use the worst-case frame length to remain a safe bound.
What is priority inversion in bxCAN mailboxes?
If low-priority frames fill the mailboxes, a high-priority frame waits behind them unless the driver aborts one or uses identifier-based mailbox priority.