Sampled controls
Eqiora.Controls.Sampled supplies a unit delay and a discrete integrator.
Each occurrence uses the caller’s clock and owns one initialized memory.
| Component | Input | Tick outputs |
|---|---|---|
UnitDelay |
u: 1 |
y is the previous memory; current u becomes the next memory |
DiscreteIntegrator |
rate: 1 / s |
before is old memory; after is old memory plus period times rate |
Compose a sampled model
Section titled “Compose a sampled model”import Eqiora.Controls.Sampled.sampled as sampled;
model SampledSignals( input signal: 1 at tick, input rate: 1 / s at tick, output delayed: 1 at tick, output accumulated: 1 at tick) { clock tick = periodic(1[s] / 4, phase = 0[s] / 1); instance delay: sampled.UnitDelay(tick = tick, initial_value = 5); instance integral: sampled.DiscreteIntegrator(tick = tick, initial_value = 3); connect signal -> delay.u; connect rate -> integral.rate; relation outputs at tick { delayed = delay.y; accumulated = integral.after; }}The first tick is at zero and the period is 1/4 s. With input samples
[2, -1, 3], delayed is [5, 2, -1]. With rate samples [2, -1, 3] /s,
accumulated is [3.5, 3.25, 4]. Select integral.before instead of
integral.after to observe memory before the current increment.
Place this source in src/main.eqi of a local project and add
Eqiora.Controls.Sampled at version 0.1.0 using the
package workflow.
Compile with entry="SampledSignals".
The complete sampled-controls example
shows how to supply timestamped values and run an execution_session.
Open the equations
Section titled “Open the equations”/// Publish the previous sample and then retain the current input.public component UnitDelay( clock tick: periodic, parameter initial_value: 1, input u: 1 at tick, output y: 1 at tick) { state memory: 1 at tick; initial { pre(memory) = initial_value; } relation update at tick { y = pre(memory); next(memory) = u; }}
/// Integrate the supplied rate once per tick, exposing both sides of the update.public component DiscreteIntegrator( clock tick: periodic, parameter initial_value: 1, input rate: 1 / s at tick, output before: 1 at tick, output after: 1 at tick) { state memory: 1 at tick; initial { pre(memory) = initial_value; } relation update at tick { next(memory) = pre(memory) + period(tick) * rate; before = pre(memory); after = next(memory); }}initial_value and tick are required bindings. The integrator uses the supplied
period, so changing the period changes its increment. No output sample exists
before the first tick. All equations at a tick hold simultaneously.
Physical quantities
Section titled “Physical quantities”These blocks use dimensionless memory. To integrate a physical rate, choose a
fixed nonzero scale in the desired output unit. Divide the physical rate by the
scale, use a dimensionless initial value, and multiply the output by the same scale.
For example, with a 2 V scale, 4 V/s becomes 2 /s; a quarter-second step
increases normalized memory by 0.5 and physical voltage by 1 V.
The example project contains voltage and displacement adapters. They are ordinary equations and introduce no additional state.
Inputs must use the same clock as their receiving blocks. Two separate clocks
with equal periods remain different clocks; sharing tick makes the intended
activation explicit.