SignalConverter

SignalConverter converts a quantity in both directions at once.
3.30–3.34

SignalConverter converts a quantity in both directions at once. One port multiplies by a gain and adds an offset; the other subtracts the offset and divides. The two are exact inverses, so a value sent out and read back comes home unchanged.

Use it wherever a quantity crosses a unit boundary both ways — a setpoint going out to hardware and a measurement coming back.

flowchart LR
    i1(["input"]) --> B["SignalConverter"]
    i2(["inverseInput"]) --> B
    p1(["gain"]) --> B
    p2(["offset"]) --> B
    p3(["inverseOutputReference"]) --> B
    p4(["doReferencing"]) --> B
    p5(["doReferencingAll"]) --> B
    p6(["invert"]) --> B
    B --> o1(["output"])
    B --> o2(["inverseOutput"])

invert decides which port multiplies. With it false — the default — inverseOutput multiplies and output divides. With it true they swap. Everything else about the block is the same.

Automatic referencing does not work correctly at the default invert setting. It computes an offset that suits the other direction, so unless your gain is 1 the result will be wrong. Set the offset by hand, or set invert to true, until this is fixed.

Signals

Inputs

Path Unit Range Description
input input unit unbounded With invert false this port divides: output = (input − offset) ÷ gain.
inverseInput output unit unbounded With invert false this port multiplies: inverseOutput = gain × inverseInput + offset.

Outputs

Path Unit Description
output output unit The result on the input side. Reads 0 on any channel whose gain is 0, deliberately.
inverseOutput input unit The result on the inverseInput side. This is the port that referencing aims at.

Parameters

Path Unit Default Range Effect
gain - 1.0 unbounded The conversion factor, per channel. Shared by both directions, which is what makes them exact inverses. A gain of 0 makes the dividing side output 0 rather than failing.
offset output unit 0.0 unbounded Added on the multiplying side, subtracted on the dividing side, per channel. Referencing overwrites this.
inverseOutputReference input unit zeros unbounded The value referencing aims inverseOutput at, per channel.
doReferencing - false - Per channel: solve for the offset that puts inverseOutput at its reference. Cleared automatically. See the caveat above.
doReferencingAll - false - The same for every channel at once. Also cleared automatically.
invert - false - Swaps which port multiplies and which divides.

All are persistent and survive a controller restart. doReferencing and doReferencingAll are persistent too, so a configuration saved while one was set will re-reference on the next startup, against whatever the inputs happen to read then. Save your configuration after referencing, not during.

No parameters exist below this block.

Setup

  1. Connect the two directions. With invert false, the multiplying direction is inverseInput to inverseOutput.
  2. Set gain per channel, from the units: it is the multiplying side’s output unit divided by its input unit.
  3. Leave offset at 0 for now.
  4. Feed a known value into inverseInput and confirm inverseOutput is that value times the gain.
  5. Feed inverseOutput back into input and confirm output returns the original. The round trip should be exact.
  6. Set the offset by hand from a known reference point — see the caveat about automatic referencing above.

Tuning

  1. There is nothing dynamic here. Both parameters take effect on the next cycle, with no fade and no filtering.
  2. Set the gain from the units first, and check the round trip before worrying about the offset.
  3. Set the offset from one known point: put the machine at a position you can measure, read inverseInput, and compute the offset that makes inverseOutput read the true value.
  4. If you use doReferencing, verify the result rather than trusting it — read offset back and check inverseOutput really lands on inverseOutputReference. At a gain of 1 it will; away from 1 it will not.
  5. Check both directions after every change. The two share one gain and one offset, so a change intended for one affects the other.
  6. Use a gain of 0 deliberately if you want a channel’s dividing side muted — it outputs 0 rather than failing.
  7. Nothing here depends on the task rate.

The two paths with a gain of 2 and an offset of 0.5. One multiplies, theother divides, and sending a value through both returns itunchanged.

The dashed line is the round trip. It should always be the identity.

Symptom Cause Action
Referencing put the offset in the wrong place The referencing formula suits invert true, and the default is false Set the offset by hand, or set invert to true
Referencing looked right at a gain of 1 Expected: the two formulas agree only there Verify at your real gain
The round trip does not return the input The gain or offset changed between the two directions They are shared, so check nothing else wrote them
One direction is scaled and the other is not That is what the block does — one multiplies, one divides Check invert
The multiplying and dividing ports are the wrong way round invert is set the other way Flip it
A channel’s output is 0 Its gain is 0, so the dividing side outputs 0 deliberately Set a non-zero gain
The offset changed by itself A referencing trigger fired Check whether doReferencing was saved as true
Referencing happened at startup The triggers are persistent, and one was saved as true Save your configuration after referencing completes
Only some channels converted gain and offset are per channel Set every channel
The outputs are invalid An input that is not a valid number passes straight through Fix the upstream signal
I need the two directions scaled differently Not possible — they share one gain, which is what makes them exact inverses Use two Gain blocks
I need a non-linear conversion Wrong block Use Lookup
I need to switch it off Not possible — there is no enable Set gain to 1 and offset to 0
I need more channels The count is fixed when the controller is built Rebuild, or use a second instance

A starting point for a two-channel pass-through:

gain    = [1.0, 1.0]
offset  = [0.0, 0.0]
invert  = false

Limits and errors

Limit Set by What happens Reported
Conversion gain, offset One port multiplies and adds, the other subtracts and divides. Exact inverses output, inverseOutput
Direction invert Chooses which port does which Not reported
A gain of 0 Checked The dividing side outputs 0 rather than failing Not reported
Automatic referencing doReferencing Computes an offset for the wrong direction when invert is false. Correct only at a gain of 1 Not reported — read offset and inverseOutput back
Referencing triggers Fixed Self-clearing, and persistent — a saved true fires once at startup Not reported
offset after referencing Fixed Overwritten. A later configuration reload restores the saved value, not the referenced one Read it back
Values that are not numbers Nothing Not checked. They pass through both paths Not reported
State None The block has no memory, deliberately — some parent blocks run it twice in one cycle Not applicable
Enable None There is no enable, disable or isEnabled Not applicable
Channel count Fixed at build time Cannot be changed from the tree Not reported

This block logs nothing, ever. Every condition above shows as a value on a trace, or not at all.


Verified against motorcortex-control3 3.30.0 (bc348fd).