Delay

Delay holds a signal back by a whole number of task cycles and passes it on unchanged.
3.30–3.34

Delay holds a signal back by a whole number of task cycles and passes it on unchanged. Use it to line signals up in time — a sensor reading against the command that produced it, a feedforward term against the feedback path it has to meet. It changes nothing about the signal’s size or shape: every frequency comes through at full amplitude, just later.

It is the one block here whose job is to add lag rather than avoid it.

flowchart LR
    i1(["input — signal to hold back"]) --> B["Delay"]
    B --> o1(["output — the same signal, later"])

Delay in seconds = delaysamples × task period [s]. On a 1 ms task, delaysamples 25 is 25 ms. The lag is the same at every frequency, and it reaches half a cycle of phase at $1/(2 \times$ delay$)$ Hz — 20 Hz for a 25 ms delay. Inside a feedback loop that is where the delay alone inverts the sign, so a delay in a loop costs stability directly.

This block has no enable, no disable, no isEnabled and no reset. It is always running. Set delaysamples to 0 to pass the signal straight through. The delay is counted in samples, not seconds — see Limits and errors.

Signals

Inputs

Path Unit Range Description
input signal unit unbounded The signal to hold back. One element per channel; the channel count is fixed by the machine configuration.

Outputs

Path Unit Description
output signal unit The same signal, delaysamples cycles later, unchanged in size and shape. Equals input exactly while delaysamples is 0. Reads zero for the first delaysamples cycles after every controller start, then begins reproducing the input.

Parameters

Path Unit Default Range Effect
delaysamples samples 0 0 – a ceiling fixed when the machine is built How many task cycles to hold the signal back, shared by all channels. 0 passes the signal straight through. A value above the ceiling is corrected silently — see Limits and errors. Note the path name is all lower case.

delaysamples is persistent and survives a controller restart. The input and output do not. No parameters exist below this block.

Setup

  1. Work out the delay you need in seconds, then divide by the task period to get samples. On a 1 ms task, 25 ms is 25 samples.

  2. Find the ceiling: write a large number to delaysamples and read it back. The value you get is the largest delay this instance supports, and it is fixed when the machine is built.

  3. Set delaysamples to 0 and link the source signal into input. output equals input sample for sample, which confirms the link.

  4. Set delaysamples to the value from step 1. Read it back and confirm it was accepted.

    Step 4 emits stale data for a moment. Raising the delay while the machine runs pushes out samples that were never recorded at the new depth. Change delaysamples with the axis at rest, or accept a brief burst of wrong values on output.

  5. Trace input and output together and measure the offset between the same feature on each. It should be your delay in seconds.

  6. Trace every element of both. An element that reads zero while the machine moves is an unwired channel.

Tuning

There is almost nothing to tune. The delay is either the right number of samples or it is not.

  1. Measure the misalignment you are correcting, in seconds, off a trace of the two signals you want to line up.
  2. Divide by the task period and round to the nearest whole number. This block cannot delay by a fraction of a sample, so the task rate sets how finely you can align.
  3. Set delaysamples, then re-measure the offset on a trace. Adjust by one sample at a time.
  4. If the alignment you need is finer than one task period, this block cannot deliver it. Raise the task rate, or accept the rounding.
  5. Re-check delaysamples after any task-rate change. The delay is counted in samples, so the same setting is a different delay in seconds. Rescale it by the ratio of the old and new task periods.
  6. If the delay sits inside a feedback loop, re-check the loop’s stability after every change. A delay costs phase margin at every frequency.

A 2 Hz sine and the same signal at two delay settings: the 25-sample tracelags the dashed input by 25 ms and the 100-sample trace by 100 ms, with nochange in amplitude.

Read the delay off any curve as its horizontal offset from the dashed input.

Symptom Cause Action
output reads zero for a while after every start Expected: the block has nothing recorded yet, so it emits zeros for delaysamples cycles Gate the consumer off a delay of at least that long after start
A burst of wrong values on output right after raising delaysamples Expected: the deeper slots hold data that was never recorded Change the delay at rest, not in motion
output jumped after lowering delaysamples Expected: the output skips forward in time by the difference Change the delay at rest, or step it down one sample at a time
The delay in seconds changed after a task-rate change Expected: the delay is counted in samples, not seconds Rescale delaysamples by the ratio of the task periods
delaysamples reads back lower than written Above the ceiling for this instance Work within the value you read back; the ceiling is fixed when the machine is built
You need a delay finer than one task period Not possible — only whole samples are available Raise the task rate, or accept the rounding
The loop that consumes output went unstable Expected: a delay costs phase margin at every frequency Reduce the delay, or retune the loop for it
You cannot switch the block off Expected: there is no enable of any kind Set delaysamples to 0, which is a true pass-through
You cannot flush the stored samples There is no reset in this block Set delaysamples to 0 and back, or restart the controller
output is a filtered version of input rather than a shifted one Not possible — this block cannot change a signal’s shape Check you are looking at this block’s output and not a filter’s
Some channels are delayed more than others Not possible — all channels share one delay Use a separate instance per channel group
A non-numeric value appeared on output A non-numeric value reached input delaysamples cycles ago Fix the source; the value clears itself after delaysamples cycles
The block costs more processing time than expected Expected: the work grows with the delay, not with the signal Use the smallest delay that does the job

A starting point for aligning a sensor reading with a 25 ms transport lag on a 1 ms task:

delaysamples = 25

Limits and errors

Limit Set by What happens Reported
delaysamples ≤ the instance ceiling Machine configuration A larger value is replaced by the ceiling. The ceiling is not readable directly — discover it with Setup step 2 Silently; read delaysamples back
Delay resolution Task rate Whole samples only. The task period is the finest alignment available Not reported
Delay in seconds Task rate Scales directly with the task period, so a task-rate change silently changes the delay in wall-clock terms Not reported
output Nothing Unbounded — whatever the input carries reaches the output unchanged. Limit it downstream if the consumer needs a bound Not reported
Stored samples Nothing There is no reset input and no enable. Setting delaysamples to 0 and back is the only way to flush from the parameter tree Not reported
Channel count Machine configuration Fixed once the controller starts; it cannot be changed at runtime Not reported

The block raises no errors or warnings and logs nothing. Every failure above shows as a value on a trace, not as a message.


Verified against motorcortex-control3 3.30.0 (bc348fd).