2021-08-10 21:29:24 +00:00
|
|
|
package hw
|
|
|
|
|
|
|
|
import (
|
2022-03-12 19:51:15 +00:00
|
|
|
"time"
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
"github.com/warthog618/go-gpiocdev"
|
2021-08-10 21:29:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-03-12 19:51:15 +00:00
|
|
|
pinDoorOpen = 17
|
|
|
|
pinFanPower = 22
|
2022-03-05 19:42:17 +00:00
|
|
|
pinCoolerPower = 23
|
|
|
|
pinHeaterPower = 24
|
2022-03-12 19:51:15 +00:00
|
|
|
pinLightsPower = 25
|
2021-08-10 21:29:24 +00:00
|
|
|
|
2022-08-01 17:49:52 +00:00
|
|
|
// GPIO21 is located at pin 13 on RPi 1B rev 1. Rev 2 and never boards
|
|
|
|
// has GPIO27 here.
|
|
|
|
pinOneWirePower = 21
|
|
|
|
|
2021-08-10 21:29:24 +00:00
|
|
|
off = 0
|
|
|
|
on = 1
|
|
|
|
)
|
|
|
|
|
2022-03-12 19:51:15 +00:00
|
|
|
type HWEvent int
|
|
|
|
|
|
|
|
const (
|
|
|
|
NoOp HWEvent = iota
|
|
|
|
DoorClosed
|
|
|
|
DoorOpened
|
|
|
|
)
|
|
|
|
|
2021-08-10 21:29:24 +00:00
|
|
|
type Gpio struct {
|
2024-06-15 13:58:47 +00:00
|
|
|
chip *gpiocdev.Chip
|
|
|
|
doorOpen *gpiocdev.Line
|
|
|
|
oneWirePower *gpiocdev.Line
|
|
|
|
lightsPower *gpiocdev.Line
|
|
|
|
fanPower *gpiocdev.Line
|
|
|
|
coolerPower *gpiocdev.Line
|
|
|
|
heaterPower *gpiocdev.Line
|
2022-03-12 19:51:15 +00:00
|
|
|
|
|
|
|
C chan HWEvent
|
2021-08-10 21:29:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewGpio() (*Gpio, error) {
|
|
|
|
var err error
|
2022-03-12 19:51:15 +00:00
|
|
|
p := &Gpio{
|
2022-07-23 23:16:40 +00:00
|
|
|
C: make(chan HWEvent, 1),
|
2022-03-12 19:51:15 +00:00
|
|
|
}
|
2021-08-10 21:29:24 +00:00
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.chip, err = gpiocdev.NewChip("gpiochip0", gpiocdev.WithConsumer("fermentord"))
|
2021-08-10 21:29:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-03-12 19:51:15 +00:00
|
|
|
p.doorOpen, err = p.chip.RequestLine(
|
|
|
|
pinDoorOpen,
|
2024-06-15 13:58:47 +00:00
|
|
|
gpiocdev.AsInput,
|
|
|
|
gpiocdev.LineBiasPullUp,
|
|
|
|
gpiocdev.WithDebounce(200*time.Millisecond),
|
|
|
|
gpiocdev.WithBothEdges,
|
|
|
|
gpiocdev.WithEventHandler(p.onDoorStateChanged),
|
2022-03-12 19:51:15 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-07-23 23:16:40 +00:00
|
|
|
// Add an initial door reading to the channel to ensure correct state when booting
|
|
|
|
isDoorOpen, err := p.doorOpen.Value()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
switch isDoorOpen {
|
|
|
|
case 0: // Line is pulled low when door is open (circuit is closed)
|
|
|
|
p.C <- DoorOpened
|
|
|
|
default: // Pull-up resistor sets line high when door is closed (open circuit)
|
|
|
|
p.C <- DoorClosed
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.oneWirePower, err = p.chip.RequestLine(pinOneWirePower, gpiocdev.AsOutput(0))
|
2022-08-01 17:49:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.lightsPower, err = p.chip.RequestLine(pinLightsPower, gpiocdev.AsOutput(0))
|
2022-03-12 19:51:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.fanPower, err = p.chip.RequestLine(pinFanPower, gpiocdev.AsOutput(0))
|
2022-03-12 19:51:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.coolerPower, err = p.chip.RequestLine(pinCoolerPower, gpiocdev.AsOutput(0))
|
2021-08-10 21:29:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
p.heaterPower, err = p.chip.RequestLine(pinHeaterPower, gpiocdev.AsOutput(0))
|
2021-08-10 21:29:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return p, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) Close() {
|
|
|
|
p.coolerPower.SetValue(off)
|
|
|
|
p.heaterPower.SetValue(off)
|
2022-03-12 19:51:15 +00:00
|
|
|
p.fanPower.SetValue(off)
|
|
|
|
p.lightsPower.SetValue(off)
|
2022-08-01 17:49:52 +00:00
|
|
|
p.oneWirePower.SetValue(off)
|
2021-08-10 21:29:24 +00:00
|
|
|
|
2022-08-01 17:49:52 +00:00
|
|
|
p.oneWirePower.Close()
|
2021-08-10 21:29:24 +00:00
|
|
|
p.heaterPower.Close()
|
|
|
|
p.coolerPower.Close()
|
2022-03-12 19:51:15 +00:00
|
|
|
p.fanPower.Close()
|
|
|
|
p.lightsPower.Close()
|
|
|
|
p.doorOpen.Close()
|
2021-08-10 21:29:24 +00:00
|
|
|
p.chip.Close()
|
2022-03-12 19:51:15 +00:00
|
|
|
|
|
|
|
close(p.C)
|
2021-08-10 21:29:24 +00:00
|
|
|
}
|
2021-08-30 20:46:38 +00:00
|
|
|
|
|
|
|
func (p *Gpio) StartCooler() {
|
|
|
|
p.coolerPower.SetValue(on)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) StopCooler() {
|
|
|
|
p.coolerPower.SetValue(off)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) StartHeater() {
|
|
|
|
p.heaterPower.SetValue(on)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) StopHeater() {
|
|
|
|
p.heaterPower.SetValue(off)
|
|
|
|
}
|
2022-03-12 19:51:15 +00:00
|
|
|
|
|
|
|
func (p *Gpio) StartFan() {
|
|
|
|
p.fanPower.SetValue(on)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) StopFan() {
|
|
|
|
p.fanPower.SetValue(off)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) LightsOn() {
|
|
|
|
p.lightsPower.SetValue(on)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) LightsOff() {
|
|
|
|
p.lightsPower.SetValue(off)
|
|
|
|
}
|
|
|
|
|
2022-08-01 17:49:52 +00:00
|
|
|
func (p *Gpio) StartOneWirePower() {
|
|
|
|
// Inverted logic due to PNP transistor switch
|
|
|
|
p.oneWirePower.SetValue(off)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Gpio) StopOneWirePower() {
|
|
|
|
// Inverted logic due to PNP transistor switch
|
|
|
|
p.oneWirePower.SetValue(on)
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
func (p *Gpio) onDoorStateChanged(le gpiocdev.LineEvent) {
|
2022-03-12 19:51:15 +00:00
|
|
|
switch le.Type {
|
2024-06-15 13:58:47 +00:00
|
|
|
case gpiocdev.LineEventFallingEdge:
|
2022-03-12 19:51:15 +00:00
|
|
|
p.C <- DoorOpened
|
|
|
|
|
2024-06-15 13:58:47 +00:00
|
|
|
case gpiocdev.LineEventRisingEdge:
|
2022-03-12 19:51:15 +00:00
|
|
|
p.C <- DoorClosed
|
|
|
|
}
|
|
|
|
}
|