2022-03-15 20:07:53 +00:00
|
|
|
package lcd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2022-07-24 07:38:40 +00:00
|
|
|
"log"
|
2022-03-15 20:07:53 +00:00
|
|
|
"sync"
|
2022-07-24 07:38:40 +00:00
|
|
|
"time"
|
2022-03-15 20:07:53 +00:00
|
|
|
|
|
|
|
"git.joco.dk/sng/fermentord/internal/controllers"
|
|
|
|
"git.joco.dk/sng/fermentord/pkg/temperature"
|
|
|
|
device "github.com/d2r2/go-hd44780"
|
|
|
|
"github.com/d2r2/go-i2c"
|
|
|
|
)
|
|
|
|
|
|
|
|
type LCD struct {
|
|
|
|
ambient, chamber, setpoint, wort float64
|
|
|
|
state string
|
|
|
|
|
|
|
|
bus *i2c.I2C
|
|
|
|
lcd *device.Lcd
|
|
|
|
l1, l2 string
|
|
|
|
chTemp chan temperature.TemperatureReading
|
|
|
|
chState chan controllers.ChamberState
|
|
|
|
chSetpoint chan float64
|
2022-07-24 07:38:40 +00:00
|
|
|
lastUpdate time.Time
|
2022-03-15 20:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewLCD() (*LCD, error) {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
p := &LCD{
|
|
|
|
chTemp: make(chan temperature.TemperatureReading, 10),
|
|
|
|
chState: make(chan controllers.ChamberState, 10),
|
|
|
|
chSetpoint: make(chan float64, 10),
|
2022-07-24 07:38:40 +00:00
|
|
|
lastUpdate: time.Now(),
|
2022-03-15 20:07:53 +00:00
|
|
|
}
|
|
|
|
|
2022-07-23 18:03:30 +00:00
|
|
|
p.bus, err = i2c.NewI2C(0x27, 0)
|
2022-03-15 20:07:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
p.lcd, err = device.NewLcd(p.bus, device.LCD_16x2)
|
|
|
|
if err != nil {
|
|
|
|
p.bus.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = p.lcd.BacklightOn()
|
|
|
|
if err != nil {
|
|
|
|
p.bus.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-07-24 07:38:40 +00:00
|
|
|
err = p.lcd.ShowMessage("Fermentor", device.SHOW_LINE_1)
|
2022-03-15 20:07:53 +00:00
|
|
|
if err != nil {
|
|
|
|
p.bus.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-07-24 07:38:40 +00:00
|
|
|
err = p.lcd.ShowMessage("Initializing", device.SHOW_LINE_2 /*|device.SHOW_BLANK_PADDING*/)
|
2022-03-15 20:07:53 +00:00
|
|
|
if err != nil {
|
|
|
|
p.bus.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return p, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) Close() error {
|
2022-07-24 07:38:40 +00:00
|
|
|
if err := p.lcd.BacklightOff(); err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
}
|
|
|
|
|
2022-03-15 20:07:53 +00:00
|
|
|
return p.bus.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) SetTemperature(t temperature.TemperatureReading) {
|
|
|
|
p.chTemp <- t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) SetSetpointTemp(t float64) {
|
|
|
|
p.chSetpoint <- t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) SetState(state controllers.ChamberState) {
|
|
|
|
p.chState <- state
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) Run(ctx context.Context, wg *sync.WaitGroup) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case t := <-p.chTemp:
|
|
|
|
p.ambient = t.Ambient
|
|
|
|
p.chamber = t.Chamber
|
|
|
|
p.wort = t.Wort
|
|
|
|
p.update()
|
|
|
|
|
|
|
|
case state := <-p.chState:
|
|
|
|
switch state {
|
|
|
|
case controllers.ChamberStateIdle:
|
|
|
|
p.state = "Id"
|
|
|
|
|
|
|
|
case controllers.ChamberStateHeating:
|
|
|
|
p.state = "He"
|
|
|
|
|
|
|
|
case controllers.ChamberStateCooling:
|
|
|
|
p.state = "Co"
|
|
|
|
}
|
|
|
|
p.update()
|
|
|
|
|
|
|
|
case t := <-p.chSetpoint:
|
|
|
|
p.setpoint = t
|
|
|
|
p.update()
|
|
|
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
p.lcd.ShowMessage("Fermentor", device.SHOW_LINE_1|device.SHOW_BLANK_PADDING)
|
|
|
|
p.lcd.ShowMessage("Shutting down", device.SHOW_LINE_2|device.SHOW_BLANK_PADDING)
|
|
|
|
|
|
|
|
close(p.chSetpoint)
|
|
|
|
close(p.chState)
|
|
|
|
close(p.chTemp)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *LCD) update() error {
|
2022-07-24 07:38:40 +00:00
|
|
|
if time.Since(p.lastUpdate) < 3*time.Second {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-15 20:07:53 +00:00
|
|
|
l1 := fmt.Sprintf("W:%4.1f C:%4.1f %s", p.wort, p.chamber, p.state)
|
|
|
|
l2 := fmt.Sprintf("S:%4.1f A:%4.1f", p.ambient, p.setpoint)
|
|
|
|
|
|
|
|
if l1 != p.l1 {
|
|
|
|
if err := p.lcd.ShowMessage(l1, device.SHOW_LINE_1|device.SHOW_BLANK_PADDING); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
p.l1 = l1
|
|
|
|
}
|
|
|
|
|
|
|
|
if l2 != p.l2 {
|
|
|
|
if err := p.lcd.ShowMessage(l2, device.SHOW_LINE_2|device.SHOW_BLANK_PADDING); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
p.l2 = l2
|
|
|
|
}
|
|
|
|
|
2022-07-24 07:38:40 +00:00
|
|
|
p.lastUpdate = time.Now()
|
|
|
|
|
2022-03-15 20:07:53 +00:00
|
|
|
return nil
|
|
|
|
}
|