The CAN bench, with Zelos plugged in

The bench from part one with Zelos on it: live plots from another desk, poking the bus, handing a recording to a coworker, and checks that run in CI.

Michael Jaradah5 minute read

Part 2 of 2 in The CAN bench

A board from the CAN bench wired into a Zelos agent.
Contents8 sections

In part one we built a small CAN bench: a BMS, a DC-DC converter and a VCU running Zephyr in Renode, all from one git repo, on a laptop or a CI machine. It has a bug planted in it. When the BMS cuts the converter's allowance, the defective DC-DC build ramps its current down instead of dropping it.

Part one needed nothing from Zelos. This part puts our tools on the same bench and tours what working on it looks like: watching it live, poking at it, asking questions about it, handing a recording to a coworker, and checking it in CI. The DC-DC bug is what we chase throughout.

What runs on the bench

just up starts the same three containers as in part one. The third runs a Zelos agent: a service that takes in signals, stores them and serves them to the app, to notebooks and to anything else that asks.

The BMS, DC-DC and VCU on vcan0 inside Renode. The Zelos agent's CAN extension reads vcan0 and fills the agent's store.
What runs on the bench.

The agent runs our CAN extension as a child process that it starts and restarts. The extension reads vcan0, decodes every frame with the same bench.dbc the firmware is built from, and writes named signals into the agent's store, so you see InputCurrent in amps instead of bytes 4 and 5 of 0x300. On this bench the store keeps the last 15 minutes.

Watching it from another desk

The bench doesn't have to be on your machine. Ours runs on a Linux box in the lab. In the app, New agent in the Data view takes the bench's name, and the bus appears in the Explorer: one folder per message, one signal per field.

The bench and its agent in the lab, and a laptop at another desk connected to it with New agent. The laptop plots the allowance against the draw.
The bench in the lab, watched from your laptop.

The app runs an agent of its own, and that agent keeps a copy of everything the bench publishes. Plots, checks and notebooks on the laptop read that copy. Actions and extension settings go the other way, to the bench.

The bench agent in the lab sends a copy of everything to the agent the app runs on your laptop, where plots, checks and notebooks read it. Actions and extension settings go the other way, back to the bench.
Data comes to your laptop as a copy; actions and settings go back to the bench.

Put AuxCurrentLimit and InputCurrent on one plot and you can watch the control loop work. The allowance steps with every mode change, and the draw follows it. Load the defective build, give it a drive cycle, and the bug from part one shows up as soon as charging starts: the allowance drops to 2 A, and the draw walks down after it.

You don't have to build views by hand. Zelos AI, in the app's sidebar, can put one together from a sentence:

Make a DC-DC tab: its draw against the allowance the BMS gives it, the rail voltage, and the converter temperature.

Zelos AI reports that it created a DC-DC tab with three plot panels. Beside it, the tab it built: draw against the BMS allowance, with the allowance dropping from 6 A to 2 A and the draw ramping down after it, then the rail voltage and the converter temperature.
Zelos AI built this tab on the live bench running the defective DC-DC build. The timeline is paused just after a cut.

Save the workspace as a shared layout from Layouts in the Data view, and a coworker who connects to the same bench can load the same view.

Asking what happened

The same assistant can read the data for you. Zelos AI reaches its model through Zelos Cloud, so it needs you signed in, and the model sees the results of the tools it calls. Those tools run in your app and agents. Reading data and building plots happen straight away; anything that runs code, sends a frame or changes a setting asks first. With the defective build running, we asked it:

After each cut in the DC-DC's allowance, how long does its draw stay above the new limit?

Zelos AI's answer: the allowance was cut 13 times, each from 6 A to 2 A; it lists how long InputCurrent stayed above 2 A after each cut, from 0.971 to 1.018 s, about 1.01 s on average, and names the two signals it compared.
About a second of wall clock each time. This bench host, an Intel N100, ran at about a quarter of real time, so each is about 250 ms of firmware time, which is what the firmware's 10 A/s ramp predicts.

It found 13 cuts in the laptop's copy, measured each one, and said which signals it compared and where it put the threshold. We checked with our own script on the same data and got the same 13 durations.

Poking the bus

The CAN extension ships its own actions: send a frame, start or stop a periodic one, look up a message in the DBC, and a few more. They appear under Actions in the Explorer, and dropping one into an Action panel gives you a form for it. Zelos AI can call them too, and it asks before anything that sends a frame.

CAN Transmit is a separate app extension in the marketplace: a frame composer built on those same actions. Pick a message from the DBC, fill in its signals and save the row, then send it once or start it on a period.

The CAN Transmit dialog in DBC mode with VCU_Command selected: RequestedMode set to 2, with its range shown as 0 to 3, TorqueRequest in Nm, Heartbeat, and a 100 ms period.
Composing a VCU_Command from the DBC. Each signal shows its unit and range; RequestedMode also lists its named values in the dropdown; 2 is Charge.

A frame you send goes onto the bus like any other. The VCU keeps sending its own command every 100 ms, though, so a one-off VCU_Command holds only until the next one.

Handing a recording to a coworker

Say you've caught the bug and want someone else to look at it. Save trace in the timeline captures the time range you have selected; the app calls a recording a trace. Export writes it to a single .trz file, and Upload puts it in your organization's library in Zelos Cloud, with a link only members of your organization can open.

The Save trace dialog with the name dcdc-overdraw-on-charge, an empty tags field, and Cancel, Export and Upload buttons.
Save trace, from the timeline of a live workspace.

A recording opens in the app like the live bench does, and the same layouts work on it, so the person you send it to doesn't need the bench at all.

A plot panel in the Zelos app showing about eighty seconds of a recording: the allowance sitting at 2 A, stepping to 3 A, then to 6 A for the drive leg, then back to 2 A, with the draw tracking it.
A recording open in the app, not a running bench: eighty seconds of the defective build, both signals in amps from the DBC.

Checks that run in CI

For the things that should always hold, the repo has two notebooks: Markdown files with Python cells, which an agent runs. bench-health checks that every node is still sending and that its values make sense. dcdc-respects-allowance checks that the converter stays under the allowance the BMS gives it, allowing for a sample or two already in flight when the allowance drops.

Clone the repo, open a notebook in the app, and it runs on the laptop's own agent, reading the bench through its copy:

The dcdc-respects-allowance notebook open in the Zelos app with its code hidden: a section called The last cut with a chart of AuxCurrentLimit dropping from 6 A to 2 A and InputCurrent stepping down after it, then a section called The check with a Checks board showing one row, the DC-DC stays under its allowance, 28 ≤ 8, FAILED.
The allowance notebook run in the app against the defective build. 28 rows of the joined data sat above the allowance, against a budget of 8: two per cut, four cuts in the window.

On the good build both notebooks pass. On the defective one, the allowance check goes red, and the chart above it plots the most recent cut. In CI, the same two notebooks run on the agent inside the bench's container whenever a push or pull request touches the bench, and the run keeps their reports, including from the runs that fail. CI runs the good build, so there they should stay green.

A pipeline. A push or pull request that touches the bench runs two notebooks, bench-health and dcdc-respects-allowance, on the agent in the bench's container, and the run keeps their reports.
The two notebooks in CI.

Pointing it at real hardware

The workflows above don't depend on the emulator, but the bench's containers can't see a USB adapter on the host. On real hardware, run an agent on the machine the adapter is plugged into and install the CAN extension there. Its settings live on that agent, and you edit them from the app with the gear next to the extension in the Explorer: choose the interface and channel your adapter shows up as, and add your DBC. Plots and recordings work as they are; the notebooks need your signal names.

The Configure CAN dialog: an Interface dropdown set to socketcan, a Channel field set to vcan0, a Channel Display Name, and Database Files listing /dbc/bench.dbc.
The form behind the gear, here showing the bench agent's CAN extension.

Try it

Everything is in zelos-examples/can-bench. Download the Zelos app, connect to the bench with New agent, and have a look around. Questions or ideas go to [email protected], or open an issue on the repo.