Time, Samples, or a Custom X Axis

Every plot needs an X axis. When to plot against time, against sample number, or against another dataset as an XY plot, and why a custom X axis matters.

The same signal shown three ways: against time, against sample number, and as an XY plot against another dataset

When you put a signal on a chart you are really plotting two things: the value on the Y axis, and whatever you are measuring it against on the X axis. Most tools quietly assume the X axis is time and never ask. That default is usually right, but not always, and the cases where it is wrong are exactly the ones that produce a "my graph looks weird" moment. Serial Studio lets a plot use one of three kinds of X axis, and picking the right one clears up a surprising amount of confusion.

Time: the scrolling default

By default, a plotted dataset uses a time axis. The chart scrolls, showing the most recent window of data. That window runs from minus T seconds up to now, with the newest reading pinned at the right edge, and you set T with the Time Range field. This is what you want almost all the time: watch a temperature drift, see a control loop settle, catch a spike as it happens.

But notice what "time" means here. It is the host's clock, the moment each sample arrived at Serial Studio. That is perfectly fine when samples arrive at a steady rate. It can mislead you when they do not, and that is where the other two options come in.

Samples: when the index is what matters

Set the X axis to Samples and the chart plots against sample number instead: 0, 1, 2, up to N, newest at the right. The width of the view is the Point Count (how many samples the plot keeps) rather than a number of seconds.

Reach for this when the sample index is the meaningful axis and wall-clock time is not:

  • Your device sends data in bursts, so arrival time is lumpy. On a time axis the points bunch up where a burst landed and leave gaps in between. Against sample number, every reading gets even spacing.
  • You are comparing fixed-length captures (say repeated 512-point runs) and want them aligned by index.
  • You do not have timestamps at all, and the order of the samples is the only thing that matters.

Samples is a plot setting and works in the free version.

Custom: plot one value against another

The third option is the interesting one. A custom X axis points the plot's X source at another dataset, so instead of value-versus-time you get value-versus-value. This is the XY (or scatter) plot, and it is a Pro feature.

XY plots answer a different kind of question:

  • Phase plots. Plot two axes of motion against each other, or a signal against a delayed copy of itself, to see the shape of the dynamics: a Lissajous figure, a limit cycle.
  • I-V curves. Plot current against voltage to characterize a diode, a solar cell, or a transistor.
  • Trajectories. Plot Y position against X position to draw the actual path a robot or a pen took, instead of watching each coordinate scroll past on its own.

In every one of these, time is not what belongs on the bottom of the chart. Another measured quantity is.

The case that makes it click: real timestamps

Here is a concrete reason the custom X axis exists, taken from a real question. Suppose your device batches high-rate data: each frame carries several accelerometer samples, and every sample has its own timestamp measured on the device. Plot those samples against the host's arrival time and they all land at nearly the same instant, because the whole batch arrived at once, so the real timing inside the batch is lost. Against sample number you see the order but not the actual intervals.

The fix is to treat the device's timestamp as data. Map timestamp as its own dataset, then set it as the plot's X-axis source. Now each sample is drawn at the exact device time it was recorded, not the moment its frame reached the host.

What makes this work is that the frame parser can return an array of rows. Each row is one complete sample, and each row becomes one point on the chart, so a single frame can deliver a whole batch of precisely-timed points:

// one frame carries a batch of samples; return one row per sample
function parse(frame) {
  const batch = JSON.parse(frame).samples;   // [{ t, ax, ay, az }, ...]
  return batch.map(s => [s.t, s.ax, s.ay, s.az]);
}

Map the first column to a timestamp dataset, set it as the X-axis source for the acceleration datasets, and the batch plots on a true device-time axis rather than on frame-arrival time.

Which one to pick

  • Watching a live signal? Time. It is the default for a reason.
  • Bursty arrival, fixed-length captures, or no timestamps? Samples.
  • Value against value, or samples that carry their own timestamps? Custom.

The Plots reference covers the axis settings and the oscilloscope-style Sweep and Trigger mode in full. If the parser side is new to you, How Serial Studio Turns Bytes Into Datasets explains where parsing belongs, and the frame parser reference covers returning multiple rows.

Comments

Copied to clipboard!