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.daemonState.rpOn = true
|
||||
d.daemonState.piraniVolts3.limit = 3
|
||||
d.daemonState.piraniVolts100.limit = 100
|
||||
|
||||
d.aboveRough.threshold = float64(flagPressureThresholdRough)
|
||||
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.
|
||||
func (d *daemon) process(ctx context.Context) {
|
||||
ticker := time.NewTicker(time.Millisecond * 100)
|
||||
|
@ -96,12 +123,9 @@ func (d *daemon) processOnce(_ context.Context) error {
|
|||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
// Process pirani ringbuffer.
|
||||
d.adcPiraniVolts = append(d.adcPiraniVolts, v)
|
||||
trim := len(d.adcPiraniVolts) - 100
|
||||
if trim > 0 {
|
||||
d.adcPiraniVolts = d.adcPiraniVolts[trim:]
|
||||
}
|
||||
// Process pirani ringbuffers.
|
||||
d.piraniVolts3.process(v)
|
||||
d.piraniVolts100.process(v)
|
||||
|
||||
d.pumpdown.process()
|
||||
d.vent.process()
|
||||
|
|
|
@ -7,11 +7,11 @@ import "math"
|
|||
type daemonState struct {
|
||||
safety safetyStatus
|
||||
|
||||
// adcPiraniVolts is a moving window of read ADC values, used to calculate a
|
||||
// moving average.
|
||||
adcPiraniVolts []float32
|
||||
rpOn bool
|
||||
dpOn bool
|
||||
piraniVolts100 ringbufferInput
|
||||
piraniVolts3 ringbufferInput
|
||||
|
||||
rpOn bool
|
||||
dpOn bool
|
||||
|
||||
vent momentaryOutput
|
||||
pumpdown momentaryOutput
|
||||
|
@ -42,20 +42,18 @@ const (
|
|||
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.
|
||||
func (d *daemonState) piraniDetection() piraniDetection {
|
||||
if len(d.adcPiraniVolts) < 3 {
|
||||
if len(d.piraniVolts3.data) < int(d.piraniVolts3.limit) {
|
||||
return piraniDetectionUnknown
|
||||
}
|
||||
volts := float32(0.0)
|
||||
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)
|
||||
|
||||
mbar := piraniVoltsToMbar(d.piraniVolts3.avg)
|
||||
if mbar < 4e-6 {
|
||||
return piraniDetectionDisconnected
|
||||
}
|
||||
|
@ -63,17 +61,8 @@ func (d *daemonState) piraniDetection() piraniDetection {
|
|||
}
|
||||
|
||||
func (d *daemonState) pirani() (volts float32, mbar float32) {
|
||||
volts = 0.0
|
||||
for _, v := range d.adcPiraniVolts {
|
||||
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)
|
||||
volts = d.piraniVolts100.avg
|
||||
mbar = piraniVoltsToMbar(volts)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue