Add hysteresis to vacuum thresholds and also fix the web-fronted layout #7
|
@ -30,13 +30,20 @@ type thresholdOutput struct {
|
||||||
debounce time.Time
|
debounce time.Time
|
||||||
// threshold is the setpoint of the block.
|
// threshold is the setpoint of the block.
|
||||||
threshold float64
|
threshold float64
|
||||||
|
// hysteresis around the process setpoint (min/max is threshold +- hysteresis)
|
||||||
|
hysteresis float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *thresholdOutput) process(value float64) {
|
func (t *thresholdOutput) process(value float64) {
|
||||||
if time.Now().Before(t.debounce) {
|
if time.Now().Before(t.debounce) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
new := value > t.threshold
|
new := t.output
|
||||||
|
if t.output {
|
||||||
|
new = value > (t.threshold - t.hysteresis)
|
||||||
|
} else {
|
||||||
|
new = value > (t.threshold + t.hysteresis)
|
||||||
|
}
|
||||||
if new != t.output {
|
if new != t.output {
|
||||||
t.output = new
|
t.output = new
|
||||||
t.debounce = time.Now().Add(time.Second * 5)
|
t.debounce = time.Now().Add(time.Second * 5)
|
||||||
|
|
|
@ -27,19 +27,36 @@ func TestMomentaryOutput(t *testing.T) {
|
||||||
func TestThresholdOutput(t *testing.T) {
|
func TestThresholdOutput(t *testing.T) {
|
||||||
to := thresholdOutput{
|
to := thresholdOutput{
|
||||||
threshold: 1,
|
threshold: 1,
|
||||||
|
hysteresis: 0.2,
|
||||||
}
|
}
|
||||||
to.process(0)
|
to.process(0.7)
|
||||||
if to.output {
|
if to.output {
|
||||||
t.Fatalf("output shouldn't have triggered")
|
t.Fatalf("output shouldn't have triggered")
|
||||||
}
|
}
|
||||||
to.process(2)
|
to.process(1)
|
||||||
|
if to.output {
|
||||||
|
t.Fatalf("output shouldn't have triggered")
|
||||||
|
}
|
||||||
|
to.process(1.3)
|
||||||
if !to.output {
|
if !to.output {
|
||||||
t.Fatalf("output should have triggered")
|
t.Fatalf("output should have triggered")
|
||||||
}
|
}
|
||||||
to.process(0)
|
to.process(1)
|
||||||
|
if !to.output {
|
||||||
|
t.Fatalf("output should have triggered")
|
||||||
|
}
|
||||||
|
to.process(0.7)
|
||||||
if !to.output {
|
if !to.output {
|
||||||
t.Fatalf("output should have triggered (in debounce)")
|
t.Fatalf("output should have triggered (in debounce)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let debounce timeout pass
|
||||||
|
time.Sleep(time.Second * 6)
|
||||||
|
|
||||||
|
to.process(0.7)
|
||||||
|
if to.output {
|
||||||
|
t.Fatalf("output shouldn't have triggered")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRingbufferInput(t *testing.T) {
|
func TestRingbufferInput(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue