MultiSine

MultiSine adds together a set of sine waves and an offset.
3.30–3.34

MultiSine adds together a set of sine waves and an offset. Its job here is cancelling a repeating disturbance — motor cogging, a ballscrew’s lead error, a gearbox’s tooth-meshing ripple. Fit the error as a few harmonics, put them here, and the correction cancels it.

The input is not time. It is usually a position, so frequency is in cycles per unit of input, not hertz. The disturbances this block cancels repeat with position, not with the clock.

flowchart LR
    i1(["input — usually a position"]) --> B["MultiSine"]
    i2(["disable"]) --> B
    B --> o1(["output — the summed correction"])
    B --> o2(["isEnabled"])

The output is gain × Σ amplitude[i] · sin(2π · frequency[i] · input + phase[i]) + offset, summed over harmonics 1 to order.

Element 0 of amplitude, frequency and phase is never used. The first harmonic goes in element 1. Anything written to element 0 is ignored silently.

Never write order larger than the array length. It is not checked, and a value past the end reads memory outside the array. Find the ceiling with Setup step 2.

The block ships with gain at 0, so it produces nothing until you set it. That is deliberate — an unconfigured correction should inject nothing.

Signals

Inputs

Path Unit Range Description
input m or rad, usually a position unbounded What the correction is periodic in. The block writes zero here on every disabled cycle, so a trace reads zero while it is off.

Outputs

Path Unit Description
output N or N·m, or whatever you are correcting The summed correction. Zero — not a pass-through — while disabled, and zero whenever order is 0 or gain is 0.
isEnabled - True when enable is true and disable is false. It does not mean output is being produced: gain = 0 gives zero while this reads true.

Parameters

Path Unit Default Range Effect
enable - true - False makes the output zero.
order - 1 1 up to the array length minus 1 How many harmonics to sum. Not checked — a value past the array length reads out of bounds. 0 gives zero output.
gain - 0.0 any Scales the whole sum. This is the fade-in knob — raise it from 0 to bring a correction in without touching the fit.
offset output unit 0.0 any Added after the gain. A constant term.
amplitude output unit all 0 any One per harmonic. Element 0 is ignored — start at element 1.
frequency cycles per input unit all 0 any How many times each harmonic repeats per unit of input. Not hertz. Element 0 ignored.
phase rad all 0 any Where each harmonic starts. Element 0 ignored.

All are persistent and survive a restart, which is how a fitted correction ships with a machine. No parameters exist below this block.

Setup

  1. Measure the disturbance. Move the axis slowly through at least one full period of the effect you are cancelling and record the error against position.

  2. Find the array length by reading amplitude back from the parameter tree. order must stay at least one below it.

  3. Work out the fundamental spatial period. For motor cogging that is one pole pitch, so the frequency is the pole count per motor revolution — a number of cycles per revolution, not per second.

  4. Set order first, then the three arrays. Setting the order afterwards from an application clears everything, including offset.

  5. Write the fundamental into element 1, its second harmonic into element 2, and so on. Leave element 0 alone; it does nothing.

  6. Leave gain at 0 and confirm output is zero.

  7. Raise gain from 0 toward 1 in steps, watching the error you are trying to cancel.

    Step 7 injects a real force into the machine. A correction with the wrong phase adds to the disturbance instead of cancelling it, doubling it at full gain. Raise the gain slowly and watch the error get smaller, not larger.

  8. If the error grew, shift each phase by π and repeat.

Tuning

  1. Get the frequency right before anything else. A correction at the wrong spatial period cannot be rescued by amplitude or phase.
  2. Tune one harmonic at a time, starting with the fundamental in element 1. Set the others' amplitudes to zero while you do it.
  3. For each harmonic: raise its amplitude until the error stops improving, then adjust its phase to minimise what is left. The two interact, so go back and forth once or twice.
  4. Add the next harmonic only when the previous one has stopped improving. Two or three is usually enough; more fits noise.
  5. Use gain as the master switch. It lets you compare with and without the whole correction, and lets you ramp it in on a running machine.
  6. Re-check after any mechanical change. The fit belongs to the hardware.
  7. Nothing here depends on the task rate.

One, two and three harmonics summed: a single 2 Hz sine, plus a halfamplitude at 4 Hz, plus a quarter at 6 Hz — each addition making the waveformless sinusoidal.

Read each harmonic’s contribution off how the shape changes as one is added.

Symptom Cause Action
The output is zero and isEnabled reads true gain is 0 — the default — or order is 0 Set gain above 0
Writing an amplitude did nothing It went into element 0, which is ignored Start at element 1
The disturbance got worse The phase is inverted, so the correction adds instead of cancelling Shift every phase by π
The correction cancels at one position and adds at another The frequency is wrong Re-derive it as cycles per unit of input, per Setup step 3
The correction works at low speed and not at high speed It is periodic in position and something is adding a speed-dependent effect This block cannot cancel that; look at friction or damping
The frequency seems to be out by a large factor It was configured in hertz rather than cycles per input unit Recompute against the input’s units
The arrays went to zero after setting the order from an application Setting the order clears all three arrays and offset Write order first
input reads zero on a trace You are looking at a disabled cycle — the block zeroes its own input Enable it before judging the link
The controller behaves strangely after writing a large order It was written past the array length, which reads out of bounds Keep order below the array length; restart the controller
The output has a constant bias offset is non-zero Set it to 0 unless you meant it
The correction cannot be switched off without losing the fit Set gain to 0 — the coefficients are kept
A non-numeric input produced a non-numeric output that then cleared Expected: the block holds no state Fix the source
You need this on several axes Not possible — this block is single channel Use one instance per axis

A starting point for a cogging correction on a motor with 12 poles, before the amplitudes are fitted:

enable       = true
order        = 2
gain         = 0.0
offset       = 0.0
frequency    = 0, 12, 24
amplitude    = 0, 0, 0
phase        = 0, 0, 0

Element 0 is left at zero throughout because it is ignored. Fit the amplitudes with Tuning steps 2 and 3, then raise gain.

Limits and errors

Limit Set by What happens Reported
order below the array length Nothing Not checked. A larger value reads past the end of all three arrays, which is undefined and can crash or produce nonsense. Discover the length by reading amplitude back Not reported
Element 0 Fixed Ignored in all three arrays. Harmonics start at element 1 Not reported
order = 0 Fixed The output is zero Not reported; isEnabled still reads true
output Nothing Unbounded — the sum of the amplitudes times the gain, plus the offset. Limit it downstream if the consumer needs a bound Not reported
frequency units Fixed Cycles per unit of input, not hertz Not reported
Disabled behaviour Fixed Output zero, not a pass-through, and input is zeroed too Not reported
Non-numeric input Nothing Produces a non-numeric output. Stateless, so it recovers immediately Not reported
Channel count Fixed One channel per instance, always 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).