<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title> – Signal generation</title>
    <link>/docs/developing-control-applications/control-blocks/signal-generation/</link>
    <description>Recent content in Signal generation on </description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="/docs/developing-control-applications/control-blocks/signal-generation/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Docs: SignalGenerator</title>
      <link>/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/</guid>
      <description>
        
        
        &lt;div class=&#34;c3-version&#34;&gt;
  &lt;span class=&#34;c3-version__control c3-version__control--static&#34;&gt;
    &lt;span class=&#34;c3-version__label&#34; aria-hidden=&#34;true&#34;&gt;Control3&lt;/span&gt;
    &lt;span class=&#34;c3-version__value&#34;&gt;3.30–3.34&lt;/span&gt;
  &lt;/span&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;SignalGenerator&lt;/code&gt; produces a test waveform — sine, block, triangle, sawtooth,
two smooth profiles, or Gaussian noise — for commissioning, system
identification and frequency-response work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Every setting is faded in, not stepped.&lt;/strong&gt; Amplitude, frequency, phase,
offset, the enable, and &lt;strong&gt;the waveform itself&lt;/strong&gt; each ramp to their new value
over a configurable time. Changing the signal type mid-run cross-fades between
the two shapes, so nothing this block does puts a discontinuity into a moving
machine.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    i1([&amp;quot;enable&amp;quot;]) --&amp;gt; B[&amp;quot;SignalGenerator&amp;quot;]
    i2([&amp;quot;signalType&amp;quot;]) --&amp;gt; B
    i3([&amp;quot;frequency&amp;quot;]) --&amp;gt; B
    i4([&amp;quot;amplitude&amp;quot;]) --&amp;gt; B
    i5([&amp;quot;phase&amp;quot;]) --&amp;gt; B
    i6([&amp;quot;offset&amp;quot;]) --&amp;gt; B
    i7([&amp;quot;dwellTime&amp;quot;]) --&amp;gt; B
    i8([&amp;quot;noiseAmplitude&amp;quot;]) --&amp;gt; B
    i9([&amp;quot;resetEnableSwitch&amp;quot;]) --&amp;gt; B
    B --&amp;gt; o1([&amp;quot;output — the generated signal&amp;quot;])
    B --&amp;gt; o2([&amp;quot;allOutputs — all seven types at once&amp;quot;])
    B --&amp;gt; o3([&amp;quot;sincos — sine and cosine of the phase&amp;quot;])
    B --&amp;gt; o4([&amp;quot;isStable&amp;quot;])
    B --&amp;gt; o5([&amp;quot;stableCycleCnt&amp;quot;])
    B --&amp;gt; o6([&amp;quot;enableIsOn&amp;quot;])
    B --&amp;gt; o7([&amp;quot;enableIsOff&amp;quot;])
    B --&amp;gt; o8([&amp;quot;time — the phase, 0 to 2 pi&amp;quot;])
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;frequency&lt;/code&gt; is in rad/s, not hertz&lt;/strong&gt; — 6.283 is 1 Hz. &lt;code&gt;amplitude&lt;/code&gt; is the
peak, so a sine swings ±&lt;code&gt;amplitude&lt;/code&gt; around &lt;code&gt;offset&lt;/code&gt;. For the noise type,
&lt;code&gt;amplitude&lt;/code&gt; is a 3σ bound: about 99.7% of samples fall inside it and the rest
are clipped, so the noise&amp;rsquo;s RMS is roughly a third of what you set.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nothing here survives a controller restart.&lt;/strong&gt; Every signal setting is a live
input, not a stored parameter, and the block comes back with &lt;code&gt;amplitude&lt;/code&gt; and
&lt;code&gt;frequency&lt;/code&gt; at &lt;strong&gt;0&lt;/strong&gt; — a flat line at &lt;code&gt;offset&lt;/code&gt;. That is deliberate: a generator
that resurrected itself at full amplitude would be dangerous. Keep your test
settings somewhere else.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wait for &lt;code&gt;isStable&lt;/code&gt; before trusting a measurement.&lt;/strong&gt; With the default
five-second fades, a value you write now is not fully applied until five
seconds later.&lt;/p&gt;
&lt;h2 id=&#34;signals&#34;&gt;Signals&lt;/h2&gt;
&lt;h3 id=&#34;inputs&#34;&gt;Inputs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Ramps the whole output up to the waveform, or down to &lt;code&gt;offset&lt;/code&gt;, over &lt;code&gt;enableFadeTime&lt;/code&gt;. &lt;strong&gt;Not persistent&lt;/strong&gt; — the block starts disabled.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;resetEnableSwitch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Makes the enable ramp &lt;strong&gt;jump&lt;/strong&gt; instead of fading, once. Use it to start a test from a known state. The block clears it itself.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;signalType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;0 – 6&lt;/td&gt;
&lt;td&gt;Which waveform. &lt;strong&gt;Changing it cross-fades&lt;/strong&gt; between the old and new shape over &lt;code&gt;newSettingFadeTime&lt;/code&gt; — during the change the output is a blend of both.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rad/s&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;The waveform&amp;rsquo;s frequency. &lt;strong&gt;Defaults to 0&lt;/strong&gt;, which gives a flat line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;signal unit&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Peak value. &lt;strong&gt;Defaults to 0.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;phase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rad&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Where in the cycle the waveform starts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;signal unit&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Added to everything. The output sits here when the generator is disabled.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dwellTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;Holds the waveform at each peak for this long, turning a sine into a rounded trapezoid. 0 is off.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;noiseAmplitude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;signal unit&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;Gaussian noise added &lt;strong&gt;on top of whichever type is selected&lt;/strong&gt;, so you can put noise on a sine. Also a 3σ bound.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;outputs&#34;&gt;Outputs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;output&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;signal unit&lt;/td&gt;
&lt;td&gt;The generated signal, including any added noise, faded by the enable and shifted by &lt;code&gt;offset&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allOutputs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;signal unit&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;All seven waveforms at once&lt;/strong&gt;, in signal-type order — so you can see what a different type would look like without switching to it. These exclude the added noise.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sincos&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;The sine and cosine of the current phase, normalised. Useful as a reference for correlating a measurement.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isStable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;True when the generator is fully enabled &lt;strong&gt;and&lt;/strong&gt; every setting has finished fading. &lt;strong&gt;Do not trust a measurement until this is true.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stableCycleCnt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;cycles&lt;/td&gt;
&lt;td&gt;How many complete periods have passed since &lt;code&gt;isStable&lt;/code&gt; went true. A frequency-response analyser uses this to know how much clean data it has.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableIsOn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;The enable ramp has fully reached the waveform.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableIsOff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;It has fully reached &lt;code&gt;offset&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;time&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rad&lt;/td&gt;
&lt;td&gt;The current phase, 0 to 2π. Reset to 0 once the generator is fully off.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;parameters&#34;&gt;Parameters&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;newSettingFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;How long every setting change takes to apply — including a change of waveform. Lower it for quick commissioning, raise it for a machine that must not be disturbed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;How long enabling and disabling take.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jlpAccFactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;see below&lt;/td&gt;
&lt;td&gt;0 – 1&lt;/td&gt;
&lt;td&gt;Shapes the &lt;code&gt;JERK_LIMITED&lt;/code&gt; waveform: how much of each ramp is spent at constant acceleration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jlpJerkFactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;see below&lt;/td&gt;
&lt;td&gt;0 – 1&lt;/td&gt;
&lt;td&gt;How much is spent changing acceleration. Together these set how rounded that waveform&amp;rsquo;s turns are.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These four &lt;strong&gt;are&lt;/strong&gt; persistent and survive a restart.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;signalType&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;What the machine does&lt;/th&gt;
&lt;th&gt;Parameters that matter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt; &lt;code&gt;SINE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A pure sine. The default, and the right choice for frequency response&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;amplitude&lt;/code&gt;, &lt;code&gt;phase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1&lt;/strong&gt; &lt;code&gt;BLOCK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A square wave. Excites everything at once; hard on mechanics&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt; &lt;code&gt;TRIANGLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Constant slope, sharp turns&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt; &lt;code&gt;SAWTOOTH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ramp with a step back&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4&lt;/strong&gt; &lt;code&gt;JERK_LIMITED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Triangle with rounded turns, bounded jerk. Gentle on a machine&lt;/td&gt;
&lt;td&gt;plus &lt;code&gt;jlpAccFactor&lt;/code&gt;, &lt;code&gt;jlpJerkFactor&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5&lt;/strong&gt; &lt;code&gt;QUINTIC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Smooth throughout, zero slope at each turn. The gentlest of the periodic shapes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;, &lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;6&lt;/strong&gt; &lt;code&gt;AWGN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gaussian noise. Excites a wide band at once&lt;/td&gt;
&lt;td&gt;&lt;code&gt;amplitude&lt;/code&gt; as a 3σ bound&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;offset&lt;/code&gt; to where the machine should sit at rest, and &lt;code&gt;amplitude&lt;/code&gt; and
&lt;code&gt;frequency&lt;/code&gt; to 0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;enable&lt;/code&gt; true. &lt;code&gt;output&lt;/code&gt; should move to &lt;code&gt;offset&lt;/code&gt; over &lt;code&gt;enableFadeTime&lt;/code&gt;
and &lt;code&gt;enableIsOn&lt;/code&gt; should go true.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;code&gt;signalType&lt;/code&gt;. Start with &lt;strong&gt;5, QUINTIC&lt;/strong&gt;, or 4 — both are gentle on
mechanics and neither excites a resonance the way a block wave does.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raise &lt;code&gt;amplitude&lt;/code&gt; from 0 in steps, watching the machine. Remember each step
takes &lt;code&gt;newSettingFadeTime&lt;/code&gt; to apply.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 4 moves the machine.&lt;/strong&gt; The fade means the full amplitude arrives
seconds after you write it, so raise it in small steps and wait for
&lt;code&gt;isStable&lt;/code&gt; between them rather than writing a large value and watching.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;frequency&lt;/code&gt;. Convert from hertz by multiplying by 6.283.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wait for &lt;code&gt;isStable&lt;/code&gt;, then take your measurement. Use &lt;code&gt;stableCycleCnt&lt;/code&gt; to
confirm you have enough complete periods.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To stop, set &lt;code&gt;enable&lt;/code&gt; false. The output ramps down to &lt;code&gt;offset&lt;/code&gt; — it does not
step.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;tuning&#34;&gt;Tuning&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Choose the waveform for what you are measuring. Sine for frequency
response one point at a time; noise for a whole band at once; a smooth
profile when the mechanics matter more than the spectrum.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;newSettingFadeTime&lt;/code&gt; shorter — one second, say — while sweeping through
many frequencies, so each point settles quickly. Set it longer on a
delicate machine.&lt;/li&gt;
&lt;li&gt;Sweep by writing each new &lt;code&gt;frequency&lt;/code&gt; and waiting for &lt;code&gt;isStable&lt;/code&gt;, then
counting periods on &lt;code&gt;stableCycleCnt&lt;/code&gt;. That is the intended workflow and the
two outputs exist for it.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;sincos&lt;/code&gt; as the correlation reference if you are computing a gain and
phase yourself — it is the generator&amp;rsquo;s own phase, with no measurement lag.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;dwellTime&lt;/code&gt; when you want to hold at the extremes rather than pass
through them, for example to check settling at both ends of travel.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;noiseAmplitude&lt;/code&gt; on top of a sine to test how a loop rejects noise while
tracking.&lt;/li&gt;
&lt;li&gt;Watch &lt;code&gt;allOutputs&lt;/code&gt; to compare shapes before committing to one — no need to
switch and wait for a cross-fade.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/control3/img/signal-generator-waveforms-a93b2c4f.svg&#34; alt=&#34;Three signal types at 1 Hz and amplitude 1: a sine, a triangle with sharpturns, and the quintic profile which is smooth through eachturn.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Read how gentle a waveform is off how rounded its turns are.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The output is a flat line&lt;/td&gt;
&lt;td&gt;Expected after a restart: &lt;code&gt;amplitude&lt;/code&gt; and &lt;code&gt;frequency&lt;/code&gt; both default to 0&lt;/td&gt;
&lt;td&gt;Set them; nothing here is persistent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything I set is gone after a restart&lt;/td&gt;
&lt;td&gt;Expected: the signal settings are live inputs, not stored parameters&lt;/td&gt;
&lt;td&gt;Keep your test settings in your own configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A change takes seconds to appear&lt;/td&gt;
&lt;td&gt;Expected: every setting fades over &lt;code&gt;newSettingFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lower that time, or wait for &lt;code&gt;isStable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The measurement does not match the settings&lt;/td&gt;
&lt;td&gt;You measured before the fades finished&lt;/td&gt;
&lt;td&gt;Wait for &lt;code&gt;isStable&lt;/code&gt;, then count periods on &lt;code&gt;stableCycleCnt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The waveform looks like neither type during a change&lt;/td&gt;
&lt;td&gt;Expected: a type change cross-fades, so the output is a blend&lt;/td&gt;
&lt;td&gt;Wait for &lt;code&gt;isStable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The frequency is out by a factor of about six&lt;/td&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt; is in rad/s, not hertz&lt;/td&gt;
&lt;td&gt;Multiply your hertz figure by 6.283&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The noise looks smaller than the amplitude I set&lt;/td&gt;
&lt;td&gt;Expected: for the noise type &lt;code&gt;amplitude&lt;/code&gt; is a 3σ bound, so the RMS is about a third of it&lt;/td&gt;
&lt;td&gt;Set three times the RMS you want&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The noise is different on every run&lt;/td&gt;
&lt;td&gt;Expected: the noise is seeded from the system, so it is not repeatable&lt;/td&gt;
&lt;td&gt;Two runs cannot be compared sample by sample&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The machine jolted when I disabled the generator&lt;/td&gt;
&lt;td&gt;Not possible — disabling ramps down over &lt;code&gt;enableFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;resetEnableSwitch&lt;/code&gt; is not being held&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The output jumped instead of fading&lt;/td&gt;
&lt;td&gt;&lt;code&gt;resetEnableSwitch&lt;/code&gt; was set, which makes the enable jump&lt;/td&gt;
&lt;td&gt;Clear it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The waveform kept its phase across a disable&lt;/td&gt;
&lt;td&gt;Expected: the phase only resets once &lt;code&gt;enableIsOff&lt;/code&gt; is true&lt;/td&gt;
&lt;td&gt;Wait for the fade to finish before re-enabling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The block wave shook the machine&lt;/td&gt;
&lt;td&gt;Expected: a square wave excites every frequency at once&lt;/td&gt;
&lt;td&gt;Use type 4 or 5 instead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The peaks are flat and I did not ask for that&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dwellTime&lt;/code&gt; is non-zero&lt;/td&gt;
&lt;td&gt;Set it to 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I want to see another waveform without switching&lt;/td&gt;
&lt;td&gt;Read &lt;code&gt;allOutputs&lt;/code&gt; — all seven are published continuously&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A starting point for a gentle 1 Hz excitation, quick to retune:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;signalType         = 5
frequency          = 6.283
amplitude          = 0.01
phase              = 0.0
offset             = 0.0
dwellTime          = 0.0
noiseAmplitude     = 0.0
newSettingFadeTime = 1.0
enableFadeTime     = 2.0
enable             = true
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Raise &lt;code&gt;amplitude&lt;/code&gt; from there as Setup step 4 describes.&lt;/p&gt;
&lt;h2 id=&#34;limits-and-errors&#34;&gt;Limits and errors&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;Set by&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Reported&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No signal setting survives a restart.&lt;/strong&gt; The block comes up disabled with zero amplitude and frequency&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting changes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;newSettingFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Every change ramps rather than steps, including a change of waveform&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isStable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enabling and disabling&lt;/td&gt;
&lt;td&gt;&lt;code&gt;enableFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ramps between &lt;code&gt;offset&lt;/code&gt; and the waveform. &lt;code&gt;resetEnableSwitch&lt;/code&gt; makes it jump instead&lt;/td&gt;
&lt;td&gt;&lt;code&gt;enableIsOn&lt;/code&gt;, &lt;code&gt;enableIsOff&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amplitude&lt;/code&gt;, &lt;code&gt;frequency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nothing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not checked. A negative amplitude inverts the waveform and a negative frequency runs the phase backwards; both are harmless&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fade times&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nothing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not checked. A negative value is passed through unchecked&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise amplitude&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Interpreted as a 3σ bound and clipped there, so about 0.3% of samples are clipped&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise repeatability&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Seeded from the system, so &lt;strong&gt;the sequence differs on every run&lt;/strong&gt; and two runs cannot be compared sample by sample&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;output&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Unbounded — whatever &lt;code&gt;amplitude&lt;/code&gt; plus &lt;code&gt;offset&lt;/code&gt; produces. Bound it downstream before it reaches an actuator&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-numeric settings&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Not guarded&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channel count&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;One channel per instance. Use the group block for several&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The block raises no errors or warnings and logs nothing. Every failure above
shows as a value on a trace, not as a message.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Verified against motorcortex-control3 3.30.0 (bc348fd).&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: SignalGenerators</title>
      <link>/docs/developing-control-applications/control-blocks/signal-generation/signal-generators/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/developing-control-applications/control-blocks/signal-generation/signal-generators/</guid>
      <description>
        
        
        &lt;div class=&#34;c3-version&#34;&gt;
  &lt;span class=&#34;c3-version__control c3-version__control--static&#34;&gt;
    &lt;span class=&#34;c3-version__label&#34; aria-hidden=&#34;true&#34;&gt;Control3&lt;/span&gt;
    &lt;span class=&#34;c3-version__value&#34;&gt;3.30–3.34&lt;/span&gt;
  &lt;/span&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;SignalGenerators&lt;/code&gt; holds one &lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;SignalGenerator&lt;/code&gt;&lt;/a&gt; per
channel and drives them as a group. Setting &lt;code&gt;enable&lt;/code&gt; here starts and stops
every channel at once, and the two fade times apply to all of them — so a
multi-axis test is one write rather than several.&lt;/p&gt;
&lt;p&gt;Everything else stays per channel. Each generator keeps its own waveform,
amplitude, frequency, phase and offset in its own sub-tree, so a group can run
three axes at three phases, or one sine and two flat lines.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    i1([&amp;quot;enable — starts and stops every channel&amp;quot;]) --&amp;gt; B[&amp;quot;SignalGenerators&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;This block publishes &lt;strong&gt;no outputs of its own.&lt;/strong&gt; Read each channel&amp;rsquo;s signal
from its own sub-tree: &lt;code&gt;signalGenerator01/output&lt;/code&gt;,
&lt;code&gt;signalGenerator02/output&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;While group control is on, three of each generator&amp;rsquo;s settings are
overwritten every cycle&lt;/strong&gt; — its &lt;code&gt;enable&lt;/code&gt;, &lt;code&gt;enableFadeTime&lt;/code&gt; and
&lt;code&gt;newSettingFadeTime&lt;/code&gt;. Writing them in a sub-tree has no effect. Set
&lt;code&gt;disableGroupControl&lt;/code&gt; if you need per-channel control of those three.&lt;/p&gt;
&lt;h2 id=&#34;signals&#34;&gt;Signals&lt;/h2&gt;
&lt;h3 id=&#34;inputs&#34;&gt;Inputs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Starts or stops &lt;strong&gt;every&lt;/strong&gt; channel, unless &lt;code&gt;disableGroupControl&lt;/code&gt; is set. Each channel ramps over &lt;code&gt;enableFadeTime&lt;/code&gt; rather than stepping. Not persistent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;outputs&#34;&gt;Outputs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;None at this level.&lt;/strong&gt; The group&amp;rsquo;s signals are only available per channel, at
&lt;code&gt;signalGeneratorNN/output&lt;/code&gt;. The same applies to every diagnostic — &lt;code&gt;isStable&lt;/code&gt;,
&lt;code&gt;stableCycleCnt&lt;/code&gt;, &lt;code&gt;enableIsOn&lt;/code&gt; and the rest are all per channel.&lt;/p&gt;
&lt;h2 id=&#34;parameters&#34;&gt;Parameters&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enable&lt;/code&gt; — see above&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;newSettingFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;How long a setting change takes to apply, &lt;strong&gt;for every channel&lt;/strong&gt;. Lower it for quick commissioning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableFadeTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;0 upward&lt;/td&gt;
&lt;td&gt;How long starting and stopping takes, for every channel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;disableGroupControl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;False lets this block drive every channel&amp;rsquo;s enable and fade times. &lt;strong&gt;True hands those three back to each channel&amp;rsquo;s own sub-tree.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These three are persistent and survive a restart.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The signal settings live below this block&lt;/strong&gt;, one sub-tree per channel:
&lt;code&gt;signalGenerator01&lt;/code&gt;, &lt;code&gt;signalGenerator02&lt;/code&gt; and so on, numbered from 1. Each
carries the full set described in &lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;signal-generator.md&lt;/code&gt;&lt;/a&gt;
— waveform, amplitude, frequency, phase, offset, dwell and noise, plus that
channel&amp;rsquo;s outputs and diagnostics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;None of those signal settings is persistent.&lt;/strong&gt; Every channel comes back after
a restart with zero amplitude and zero frequency.&lt;/p&gt;
&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Count the &lt;code&gt;signalGeneratorNN&lt;/code&gt; sub-trees to find how many channels this
instance has. They are numbered from 1, so &lt;code&gt;signalGenerator01&lt;/code&gt; is the first.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leave &lt;code&gt;disableGroupControl&lt;/code&gt; false so the group drives every channel&amp;rsquo;s
enable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;newSettingFadeTime&lt;/code&gt; and &lt;code&gt;enableFadeTime&lt;/code&gt;. One or two seconds suits
commissioning; the five-second defaults are conservative.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure each channel&amp;rsquo;s waveform, amplitude, frequency, phase and offset in
its own sub-tree, following
&lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;signal-generator.md&lt;/code&gt;&lt;/a&gt;. Start every amplitude at 0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;enable&lt;/code&gt; true. Every channel ramps to its &lt;code&gt;offset&lt;/code&gt;; confirm each
channel&amp;rsquo;s own &lt;code&gt;enableIsOn&lt;/code&gt; goes true.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raise the amplitudes one channel at a time, watching the machine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 6 moves the machine on every channel you have configured.&lt;/strong&gt; The
group enable started all of them at once, so an amplitude left over from
earlier work on another channel will move that axis too. Check every
channel&amp;rsquo;s amplitude before enabling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Before measuring, confirm &lt;strong&gt;every&lt;/strong&gt; channel&amp;rsquo;s &lt;code&gt;isStable&lt;/code&gt; is true. There is
no aggregate flag — you have to check them individually.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;tuning&#34;&gt;Tuning&lt;/h2&gt;
&lt;p&gt;All the waveform tuning is per channel and is described in
&lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;signal-generator.md&lt;/code&gt;&lt;/a&gt;. What is specific to the group:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the group &lt;code&gt;enable&lt;/code&gt; as the master switch for a multi-axis test. It is the
reason the block exists.&lt;/li&gt;
&lt;li&gt;Set the two fade times here rather than per channel — they are overwritten
in the sub-trees anyway while group control is on.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;disableGroupControl&lt;/code&gt; only when channels genuinely need different
enable timing. It hands back all three settings at once, not just the one
you wanted.&lt;/li&gt;
&lt;li&gt;For a phased multi-axis excitation, give each channel the same waveform,
amplitude and frequency, and stagger the &lt;code&gt;phase&lt;/code&gt; values.&lt;/li&gt;
&lt;li&gt;When sweeping, write each channel&amp;rsquo;s new frequency, then wait until every
channel&amp;rsquo;s &lt;code&gt;isStable&lt;/code&gt; is true before measuring.&lt;/li&gt;
&lt;li&gt;Remember the cost. Every channel evaluates all seven waveforms and draws
noise every cycle whether or not it is in use — an unused channel in a group
costs the same as a used one.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/control3/img/signal-generators-channels-9f24ebb6.svg&#34; alt=&#34;Three channels of one group running the same waveform at three differentphases.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Each channel is independent apart from the enable and the two fade times.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;There is no output on this block&lt;/td&gt;
&lt;td&gt;Expected: it publishes none&lt;/td&gt;
&lt;td&gt;Read &lt;code&gt;signalGeneratorNN/output&lt;/code&gt; per channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting a channel&amp;rsquo;s &lt;code&gt;enable&lt;/code&gt; does nothing&lt;/td&gt;
&lt;td&gt;Expected: the group overwrites it every cycle&lt;/td&gt;
&lt;td&gt;Use the group &lt;code&gt;enable&lt;/code&gt;, or set &lt;code&gt;disableGroupControl&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting a channel&amp;rsquo;s fade time does nothing&lt;/td&gt;
&lt;td&gt;Same cause — both fade times are overwritten too&lt;/td&gt;
&lt;td&gt;Set them here, at the group level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An axis moved that I did not expect&lt;/td&gt;
&lt;td&gt;The group enable started every channel, and that one still had an amplitude set&lt;/td&gt;
&lt;td&gt;Zero the amplitudes you are not using&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One channel is flat and the others work&lt;/td&gt;
&lt;td&gt;That channel&amp;rsquo;s amplitude or frequency is 0&lt;/td&gt;
&lt;td&gt;Set them in its sub-tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything is flat after a restart&lt;/td&gt;
&lt;td&gt;Expected: no channel&amp;rsquo;s signal settings are persistent&lt;/td&gt;
&lt;td&gt;Reconfigure them; keep your test settings elsewhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I cannot tell when the whole group is settled&lt;/td&gt;
&lt;td&gt;There is no aggregate flag&lt;/td&gt;
&lt;td&gt;Check each channel&amp;rsquo;s own &lt;code&gt;isStable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels started at slightly different times&lt;/td&gt;
&lt;td&gt;Not possible with group control on — they share one enable and one fade time&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;disableGroupControl&lt;/code&gt; is false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels need different enable timing&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;disableGroupControl&lt;/code&gt;, then set each channel&amp;rsquo;s own enable and fade times&lt;/td&gt;
&lt;td&gt;Note this hands back all three settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The block costs more processing time than expected&lt;/td&gt;
&lt;td&gt;Every channel computes all seven waveforms and two noise draws every cycle&lt;/td&gt;
&lt;td&gt;Size the instance to the channels you actually use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I cannot reset the group&amp;rsquo;s fades from the parameter tree&lt;/td&gt;
&lt;td&gt;Those helpers are available only from an application&lt;/td&gt;
&lt;td&gt;Use each channel&amp;rsquo;s own &lt;code&gt;resetEnableSwitch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A starting point for a three-channel group, quick to retune:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;disableGroupControl = false
newSettingFadeTime  = 1.0
enableFadeTime      = 2.0
enable              = false
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then configure each &lt;code&gt;signalGeneratorNN&lt;/code&gt; sub-tree from
&lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;signal-generator.md&lt;/code&gt;&lt;/a&gt;&amp;rsquo;s starting point and enable the
group last.&lt;/p&gt;
&lt;h2 id=&#34;limits-and-errors&#34;&gt;Limits and errors&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;Set by&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Reported&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Group outputs&lt;/td&gt;
&lt;td&gt;Not published&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;This block registers no outputs.&lt;/strong&gt; Every signal and diagnostic is per channel, in its own sub-tree&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-channel &lt;code&gt;enable&lt;/code&gt; and fade times&lt;/td&gt;
&lt;td&gt;Overwritten&lt;/td&gt;
&lt;td&gt;While &lt;code&gt;disableGroupControl&lt;/code&gt; is false, all three are written from this block every cycle and a sub-tree write is discarded&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aggregate status&lt;/td&gt;
&lt;td&gt;Not available&lt;/td&gt;
&lt;td&gt;There is no group &lt;code&gt;isStable&lt;/code&gt;, &lt;code&gt;isEnabled&lt;/code&gt; or cycle count. Check each channel&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;The three group parameters persist. &lt;strong&gt;No channel&amp;rsquo;s signal settings do&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fade times&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nothing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not checked&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processing cost&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Every channel runs its full generator every cycle regardless of whether it is producing anything&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group reset helpers&lt;/td&gt;
&lt;td&gt;Not exposed&lt;/td&gt;
&lt;td&gt;Resetting every channel&amp;rsquo;s fades at once is available only from an application&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channel count&lt;/td&gt;
&lt;td&gt;Machine configuration&lt;/td&gt;
&lt;td&gt;Fixed once the controller starts. Count the sub-trees to discover it&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything else&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;See &lt;a href=&#34;/docs/developing-control-applications/control-blocks/signal-generation/signal-generator/&#34;&gt;&lt;code&gt;signal-generator.md&lt;/code&gt;&lt;/a&gt;, which applies per channel&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The block raises no errors or warnings and logs nothing. Every failure above
shows as a value on a trace, not as a message.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Verified against motorcortex-control3 3.30.0 (bc348fd).&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: MultiSine</title>
      <link>/docs/developing-control-applications/control-blocks/signal-generation/multi-sine/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/docs/developing-control-applications/control-blocks/signal-generation/multi-sine/</guid>
      <description>
        
        
        &lt;div class=&#34;c3-version&#34;&gt;
  &lt;span class=&#34;c3-version__control c3-version__control--static&#34;&gt;
    &lt;span class=&#34;c3-version__label&#34; aria-hidden=&#34;true&#34;&gt;Control3&lt;/span&gt;
    &lt;span class=&#34;c3-version__value&#34;&gt;3.30–3.34&lt;/span&gt;
  &lt;/span&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;MultiSine&lt;/code&gt; adds together a set of sine waves and an offset. Its job here is
&lt;strong&gt;cancelling a repeating disturbance&lt;/strong&gt; — motor cogging, a ballscrew&amp;rsquo;s lead
error, a gearbox&amp;rsquo;s tooth-meshing ripple. Fit the error as a few harmonics, put
them here, and the correction cancels it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The input is not time.&lt;/strong&gt; It is usually a position, so &lt;code&gt;frequency&lt;/code&gt; is in
&lt;strong&gt;cycles per unit of input&lt;/strong&gt;, not hertz. The disturbances this block cancels
repeat with position, not with the clock.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    i1([&amp;quot;input — usually a position&amp;quot;]) --&amp;gt; B[&amp;quot;MultiSine&amp;quot;]
    i2([&amp;quot;disable&amp;quot;]) --&amp;gt; B
    B --&amp;gt; o1([&amp;quot;output — the summed correction&amp;quot;])
    B --&amp;gt; o2([&amp;quot;isEnabled&amp;quot;])
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;The output is &lt;code&gt;gain&lt;/code&gt; × Σ &lt;code&gt;amplitude[i]&lt;/code&gt; · sin(2π · &lt;code&gt;frequency[i]&lt;/code&gt; · input +
&lt;code&gt;phase[i]&lt;/code&gt;) + &lt;code&gt;offset&lt;/code&gt;, summed over harmonics &lt;strong&gt;1 to &lt;code&gt;order&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Element 0 of &lt;code&gt;amplitude&lt;/code&gt;, &lt;code&gt;frequency&lt;/code&gt; and &lt;code&gt;phase&lt;/code&gt; is never used.&lt;/strong&gt; The first
harmonic goes in element &lt;strong&gt;1&lt;/strong&gt;. Anything written to element 0 is ignored
silently.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Never write &lt;code&gt;order&lt;/code&gt; larger than the array length.&lt;/strong&gt; It is not checked, and a
value past the end reads memory outside the array. Find the ceiling with Setup
step 2.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The block ships with &lt;code&gt;gain&lt;/code&gt; at 0&lt;/strong&gt;, so it produces nothing until you set it.
That is deliberate — an unconfigured correction should inject nothing.&lt;/p&gt;
&lt;h2 id=&#34;signals&#34;&gt;Signals&lt;/h2&gt;
&lt;h3 id=&#34;inputs&#34;&gt;Inputs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;input&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;m or rad, usually a position&lt;/td&gt;
&lt;td&gt;unbounded&lt;/td&gt;
&lt;td&gt;What the correction is periodic in. &lt;strong&gt;The block writes zero here on every disabled cycle&lt;/strong&gt;, so a trace reads zero while it is off.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;outputs&#34;&gt;Outputs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;output&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N or N·m, or whatever you are correcting&lt;/td&gt;
&lt;td&gt;The summed correction. &lt;strong&gt;Zero — not a pass-through — while disabled&lt;/strong&gt;, and zero whenever &lt;code&gt;order&lt;/code&gt; is 0 or &lt;code&gt;gain&lt;/code&gt; is 0.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isEnabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;True when &lt;code&gt;enable&lt;/code&gt; is true and &lt;code&gt;disable&lt;/code&gt; is false. It does &lt;strong&gt;not&lt;/strong&gt; mean output is being produced: &lt;code&gt;gain&lt;/code&gt; = 0 gives zero while this reads true.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;parameters&#34;&gt;Parameters&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;False makes the output zero.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 up to the array length minus 1&lt;/td&gt;
&lt;td&gt;How many harmonics to sum. &lt;strong&gt;Not checked — a value past the array length reads out of bounds.&lt;/strong&gt; 0 gives zero output.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Scales the whole sum. &lt;strong&gt;This is the fade-in knob&lt;/strong&gt; — raise it from 0 to bring a correction in without touching the fit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;output unit&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Added after the gain. A constant term.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amplitude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;output unit&lt;/td&gt;
&lt;td&gt;all 0&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;One per harmonic. &lt;strong&gt;Element 0 is ignored — start at element 1.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;cycles per input unit&lt;/td&gt;
&lt;td&gt;all 0&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;How many times each harmonic repeats per unit of input. &lt;strong&gt;Not hertz.&lt;/strong&gt; Element 0 ignored.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;phase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rad&lt;/td&gt;
&lt;td&gt;all 0&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Where each harmonic starts. Element 0 ignored.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All are persistent and survive a restart, which is how a fitted correction
ships with a machine. &lt;strong&gt;No parameters exist below this block.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find the array length&lt;/strong&gt; by reading &lt;code&gt;amplitude&lt;/code&gt; back from the parameter
tree. &lt;code&gt;order&lt;/code&gt; must stay at least one below it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Work out the fundamental &lt;strong&gt;spatial&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;order&lt;/code&gt; &lt;strong&gt;first&lt;/strong&gt;, then the three arrays. Setting the order afterwards
from an application clears everything, including &lt;code&gt;offset&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write the fundamental into element &lt;strong&gt;1&lt;/strong&gt;, its second harmonic into element
2, and so on. &lt;strong&gt;Leave element 0 alone; it does nothing.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leave &lt;code&gt;gain&lt;/code&gt; at 0 and confirm &lt;code&gt;output&lt;/code&gt; is zero.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raise &lt;code&gt;gain&lt;/code&gt; from 0 toward 1 in steps, watching the error you are trying to
cancel.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 7 injects a real force into the machine.&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the error grew, shift each &lt;code&gt;phase&lt;/code&gt; by π and repeat.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;tuning&#34;&gt;Tuning&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Get the frequency right before anything else. A correction at the wrong
spatial period cannot be rescued by amplitude or phase.&lt;/li&gt;
&lt;li&gt;Tune one harmonic at a time, starting with the fundamental in element 1.
Set the others&#39; amplitudes to zero while you do it.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;Add the next harmonic only when the previous one has stopped improving.
Two or three is usually enough; more fits noise.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;gain&lt;/code&gt; as the master switch. It lets you compare with and without the
whole correction, and lets you ramp it in on a running machine.&lt;/li&gt;
&lt;li&gt;Re-check after any mechanical change. The fit belongs to the hardware.&lt;/li&gt;
&lt;li&gt;Nothing here depends on the task rate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/control3/img/multi-sine-harmonics-e7b7596d.svg&#34; alt=&#34;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.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Read each harmonic&amp;rsquo;s contribution off how the shape changes as one is added.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The output is zero and &lt;code&gt;isEnabled&lt;/code&gt; reads true&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gain&lt;/code&gt; is 0 — the default — or &lt;code&gt;order&lt;/code&gt; is 0&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;gain&lt;/code&gt; above 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Writing an amplitude did nothing&lt;/td&gt;
&lt;td&gt;It went into element 0, which is ignored&lt;/td&gt;
&lt;td&gt;Start at element 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The disturbance got &lt;strong&gt;worse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The phase is inverted, so the correction adds instead of cancelling&lt;/td&gt;
&lt;td&gt;Shift every &lt;code&gt;phase&lt;/code&gt; by π&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The correction cancels at one position and adds at another&lt;/td&gt;
&lt;td&gt;The frequency is wrong&lt;/td&gt;
&lt;td&gt;Re-derive it as cycles per unit of input, per Setup step 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The correction works at low speed and not at high speed&lt;/td&gt;
&lt;td&gt;It is periodic in position and something is adding a speed-dependent effect&lt;/td&gt;
&lt;td&gt;This block cannot cancel that; look at friction or damping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The frequency seems to be out by a large factor&lt;/td&gt;
&lt;td&gt;It was configured in hertz rather than cycles per input unit&lt;/td&gt;
&lt;td&gt;Recompute against the input&amp;rsquo;s units&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The arrays went to zero after setting the order from an application&lt;/td&gt;
&lt;td&gt;Setting the order clears all three arrays &lt;strong&gt;and&lt;/strong&gt; &lt;code&gt;offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Write &lt;code&gt;order&lt;/code&gt; first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;input&lt;/code&gt; reads zero on a trace&lt;/td&gt;
&lt;td&gt;You are looking at a disabled cycle — the block zeroes its own input&lt;/td&gt;
&lt;td&gt;Enable it before judging the link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The controller behaves strangely after writing a large &lt;code&gt;order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;It was written past the array length, which reads out of bounds&lt;/td&gt;
&lt;td&gt;Keep &lt;code&gt;order&lt;/code&gt; below the array length; restart the controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The output has a constant bias&lt;/td&gt;
&lt;td&gt;&lt;code&gt;offset&lt;/code&gt; is non-zero&lt;/td&gt;
&lt;td&gt;Set it to 0 unless you meant it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The correction cannot be switched off without losing the fit&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;gain&lt;/code&gt; to 0 — the coefficients are kept&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A non-numeric input produced a non-numeric output that then cleared&lt;/td&gt;
&lt;td&gt;Expected: the block holds no state&lt;/td&gt;
&lt;td&gt;Fix the source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need this on several axes&lt;/td&gt;
&lt;td&gt;Not possible — this block is single channel&lt;/td&gt;
&lt;td&gt;Use one instance per axis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A starting point for a cogging correction on a motor with 12 poles, before the
amplitudes are fitted:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;enable       = true
order        = 2
gain         = 0.0
offset       = 0.0
frequency    = 0, 12, 24
amplitude    = 0, 0, 0
phase        = 0, 0, 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Element 0 is left at zero throughout because it is ignored. Fit the amplitudes
with Tuning steps 2 and 3, then raise &lt;code&gt;gain&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;limits-and-errors&#34;&gt;Limits and errors&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;th&gt;Set by&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Reported&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt; below the array length&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nothing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not checked. A larger value reads past the end of all three arrays&lt;/strong&gt;, which is undefined and can crash or produce nonsense. Discover the length by reading &lt;code&gt;amplitude&lt;/code&gt; back&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Element 0&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Ignored in all three arrays. Harmonics start at element 1&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order&lt;/code&gt; = 0&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;The output is zero&lt;/td&gt;
&lt;td&gt;Not reported; &lt;code&gt;isEnabled&lt;/code&gt; still reads true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;output&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Unbounded — the sum of the amplitudes times the gain, plus the offset. Limit it downstream if the consumer needs a bound&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frequency&lt;/code&gt; units&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Cycles per unit of &lt;strong&gt;input&lt;/strong&gt;, not hertz&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disabled behaviour&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Output &lt;strong&gt;zero&lt;/strong&gt;, not a pass-through, and &lt;code&gt;input&lt;/code&gt; is zeroed too&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-numeric input&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Produces a non-numeric output. Stateless, so it recovers immediately&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channel count&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;One channel per instance, always&lt;/td&gt;
&lt;td&gt;Not reported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The block raises no errors or warnings and logs nothing. Every failure above
shows as a value on a trace, not as a message.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Verified against motorcortex-control3 3.30.0 (bc348fd).&lt;/p&gt;

      </description>
    </item>
    
  </channel>
</rss>
