succd: factor out ringbuffer, do not recalculate average on every request
This commit is contained in:
parent
42c9ae2fa7
commit
4df00f0a63
|
@ -28,6 +28,8 @@ func main() {
|
||||||
|
|
||||||
d := daemon{}
|
d := daemon{}
|
||||||
d.daemonState.rpOn = true
|
d.daemonState.rpOn = true
|
||||||
|
d.daemonState.piraniVolts3.limit = 3
|
||||||
|
d.daemonState.piraniVolts100.limit = 100
|
||||||
|
|
||||||
d.aboveRough.threshold = float64(flagPressureThresholdRough)
|
d.aboveRough.threshold = float64(flagPressureThresholdRough)
|
||||||
d.aboveHigh.threshold = float64(flagPressureThresholdHigh)
|
d.aboveHigh.threshold = float64(flagPressureThresholdHigh)
|
||||||
|
|
|
@ -66,6 +66,33 @@ func (t *thresholdOutput) process(value float64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ringbufferInput accumulates analog data up to limit samples, and calculates
|
||||||
|
// an average.
|
||||||
|
type ringbufferInput struct {
|
||||||
|
data []float32
|
||||||
|
limit uint
|
||||||
|
avg float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ringbufferInput) process(input float32) {
|
||||||
|
// TODO(q3k): use actual ringbuffer
|
||||||
|
// TODO(q3k): optimize average calculation
|
||||||
|
// TODO(q3k): precalculate value in mbar
|
||||||
|
r.data = append(r.data, input)
|
||||||
|
trim := len(r.data) - int(r.limit)
|
||||||
|
if trim > 0 {
|
||||||
|
r.data = r.data[trim:]
|
||||||
|
}
|
||||||
|
avg := float32(0.0)
|
||||||
|
for _, v := range r.data {
|
||||||
|
avg += v
|
||||||
|
}
|
||||||
|
if len(r.data) != 0 {
|
||||||
|
avg /= float32(len(r.data))
|
||||||
|
}
|
||||||
|
r.avg = avg
|
||||||
|
}
|
||||||
|
|
||||||
// process runs the pain acquisition and control loop of succd.
|
// process runs the pain acquisition and control loop of succd.
|
||||||
func (d *daemon) process(ctx context.Context) {
|
func (d *daemon) process(ctx context.Context) {
|
||||||
ticker := time.NewTicker(time.Millisecond * 100)
|
ticker := time.NewTicker(time.Millisecond * 100)
|
||||||
|
@ -96,12 +123,9 @@ func (d *daemon) processOnce(_ context.Context) error {
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
// Process pirani ringbuffer.
|
// Process pirani ringbuffers.
|
||||||
d.adcPiraniVolts = append(d.adcPiraniVolts, v)
|
d.piraniVolts3.process(v)
|
||||||
trim := len(d.adcPiraniVolts) - 100
|
d.piraniVolts100.process(v)
|
||||||
if trim > 0 {
|
|
||||||
d.adcPiraniVolts = d.adcPiraniVolts[trim:]
|
|
||||||
}
|
|
||||||
|
|
||||||
d.pumpdown.process()
|
d.pumpdown.process()
|
||||||
d.vent.process()
|
d.vent.process()
|
||||||
|
|
|
@ -7,11 +7,11 @@ import "math"
|
||||||
type daemonState struct {
|
type daemonState struct {
|
||||||
safety safetyStatus
|
safety safetyStatus
|
||||||
|
|
||||||
// adcPiraniVolts is a moving window of read ADC values, used to calculate a
|
piraniVolts100 ringbufferInput
|
||||||
// moving average.
|
piraniVolts3 ringbufferInput
|
||||||
adcPiraniVolts []float32
|
|
||||||
rpOn bool
|
rpOn bool
|
||||||
dpOn bool
|
dpOn bool
|
||||||
|
|
||||||
vent momentaryOutput
|
vent momentaryOutput
|
||||||
pumpdown momentaryOutput
|
pumpdown momentaryOutput
|
||||||
|
@ -42,20 +42,18 @@ const (
|
||||||
piraniDetectionDisconnected = iota
|
piraniDetectionDisconnected = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func piraniVoltsToMbar(v float32) float32 {
|
||||||
|
// Per Pirani probe docs.
|
||||||
|
bar := math.Pow(10.0, float64(v)-8.5)
|
||||||
|
return float32(bar * 1000.0)
|
||||||
|
}
|
||||||
|
|
||||||
// piraniDetection guesses whether the pirani gauge is connected.
|
// piraniDetection guesses whether the pirani gauge is connected.
|
||||||
func (d *daemonState) piraniDetection() piraniDetection {
|
func (d *daemonState) piraniDetection() piraniDetection {
|
||||||
if len(d.adcPiraniVolts) < 3 {
|
if len(d.piraniVolts3.data) < int(d.piraniVolts3.limit) {
|
||||||
return piraniDetectionUnknown
|
return piraniDetectionUnknown
|
||||||
}
|
}
|
||||||
volts := float32(0.0)
|
mbar := piraniVoltsToMbar(d.piraniVolts3.avg)
|
||||||
for _, v := range d.adcPiraniVolts[len(d.adcPiraniVolts)-3:] {
|
|
||||||
volts += v
|
|
||||||
}
|
|
||||||
volts /= 3.0
|
|
||||||
|
|
||||||
bar := math.Pow(10.0, float64(volts)-8.5)
|
|
||||||
mbar := float32(bar * 1000.0)
|
|
||||||
|
|
||||||
if mbar < 4e-6 {
|
if mbar < 4e-6 {
|
||||||
return piraniDetectionDisconnected
|
return piraniDetectionDisconnected
|
||||||
}
|
}
|
||||||
|
@ -63,17 +61,8 @@ func (d *daemonState) piraniDetection() piraniDetection {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *daemonState) pirani() (volts float32, mbar float32) {
|
func (d *daemonState) pirani() (volts float32, mbar float32) {
|
||||||
volts = 0.0
|
volts = d.piraniVolts100.avg
|
||||||
for _, v := range d.adcPiraniVolts {
|
mbar = piraniVoltsToMbar(volts)
|
||||||
volts += v
|
|
||||||
}
|
|
||||||
if len(d.adcPiraniVolts) != 0 {
|
|
||||||
volts /= float32(len(d.adcPiraniVolts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per Pirani probe docs.
|
|
||||||
bar := math.Pow(10.0, float64(volts)-8.5)
|
|
||||||
mbar = float32(bar * 1000.0)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue