fermentord/internal/controllers/chamber.go

78 lines
1.8 KiB
Go

package controllers
import (
"sync"
"time"
"github.com/rs/zerolog/log"
)
type ChamberState int
const (
ChamberStateIdle ChamberState = iota
ChamberStateCooling
ChamberStateHeating
)
type ChamberController struct {
config *Config
// Current state.
chamberState ChamberState
lastChamberStateChange time.Time
C chan ChamberState
mutex *sync.Mutex
name string
// Current temperature readings.
ambientTemperature float64
chamberTemperature float64
wortTemperature float64
pid *PIDController
initialized bool
}
func NewChamberController(name string, config *Config) *ChamberController {
return &ChamberController{
C: make(chan ChamberState),
name: name,
config: config,
pid: NewPIDController(config.PID.Kp, config.PID.Ki, config.PID.Kd),
mutex: &sync.Mutex{},
}
}
func (p *ChamberController) Run() {
for {
offset := p.pid.Compute(p.wortTemperature, p.config.FermentationTemperature)
chamberTargetTemp := p.config.FermentationTemperature + offset
log.Debug().Float64("chamber_target_temp", chamberTargetTemp).Send()
// TODO Merge hysteresis algorithm into this one.
if !p.initialized {
// heater off
// cooler off
continue
}
if p.wortTemperature < p.config.FermentationTemperature && p.chamberTemperature < chamberTargetTemp {
// heater on
} else if p.wortTemperature >= p.config.FermentationTemperature || p.chamberTemperature >= chamberTargetTemp {
// heater off
} else {
// heater off
}
if p.wortTemperature > p.config.FermentationTemperature && p.chamberTemperature > chamberTargetTemp {
// cooler on
} else if p.wortTemperature <= p.config.FermentationTemperature || p.chamberTemperature <= chamberTargetTemp {
// cooler off
} else {
// cooler off
}
}
}