Reset 1-wire bus when temperature readings fail 60 consecutive times
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
dac484d802
commit
e25905c20f
5 changed files with 79 additions and 26 deletions
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -68,6 +67,11 @@ func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config
|
|||
go temperature.PollSensors(ctx, wg, 1*time.Second, config.Sensors.Weight)
|
||||
go tilt.PollSensors(ctx, wg, 1*time.Minute, 20*time.Second)
|
||||
|
||||
oneWirePowerUpChannel := make(chan bool)
|
||||
oneWirePowerUpTimer := time.AfterFunc(1*time.Millisecond, func() {
|
||||
oneWirePowerUpChannel <- true
|
||||
})
|
||||
|
||||
for {
|
||||
select {
|
||||
case reading := <-temperature.Reading:
|
||||
|
@ -75,6 +79,25 @@ func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config
|
|||
ingest.AddReading(reading)
|
||||
//display.SetTemperature(reading)
|
||||
|
||||
case <-temperature.RequestReset:
|
||||
log.Print("Powering down one wire bus for 20 seconds")
|
||||
gpio.StopOneWirePower()
|
||||
oneWirePowerUpTimer.Reset(20 * time.Second)
|
||||
|
||||
// Publish to NATS
|
||||
e := dwingest.Event{
|
||||
Time: time.Now().UTC(),
|
||||
Event: "ONEWIRE_RESET",
|
||||
}
|
||||
if err := ingest.Publish(config.NATS.Subject.Event, js, e); err != nil {
|
||||
hub.CaptureException(err)
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
case <-oneWirePowerUpChannel:
|
||||
log.Print("Powering up one wire bus")
|
||||
gpio.StartOneWirePower()
|
||||
|
||||
case ev := <-gpio.C:
|
||||
var evs string
|
||||
|
||||
|
@ -96,19 +119,12 @@ func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config
|
|||
evs = "DOOR_OPENED"
|
||||
}
|
||||
|
||||
b, err := json.Marshal(map[string]interface{}{
|
||||
"time": time.Now().UTC(),
|
||||
"event": evs,
|
||||
})
|
||||
if err != nil {
|
||||
hub.CaptureException(err)
|
||||
log.Printf("Error marshaling JSON: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
// Publish to NATS
|
||||
_, err = js.Publish(config.NATS.Subject.Event, b, nats.AckWait(1*time.Second))
|
||||
if err != nil {
|
||||
e := dwingest.Event{
|
||||
Time: time.Now().UTC(),
|
||||
Event: evs,
|
||||
}
|
||||
if err := ingest.Publish(config.NATS.Subject.Event, js, e); err != nil {
|
||||
hub.CaptureException(err)
|
||||
log.Print(err)
|
||||
}
|
||||
|
|
|
@ -64,16 +64,16 @@ func (p *DWIngest) Run(ctx context.Context, wg *sync.WaitGroup, js nats.JetStrea
|
|||
for {
|
||||
select {
|
||||
case reading := <-p.chTemperatureReading:
|
||||
p.publish(config.NATS.Subject.Temp, js, reading)
|
||||
p.Publish(config.NATS.Subject.Temp, js, reading)
|
||||
|
||||
case state := <-p.chState:
|
||||
p.publish(config.NATS.Subject.State, js, State{
|
||||
p.Publish(config.NATS.Subject.State, js, State{
|
||||
Time: time.Now().UTC(),
|
||||
State: controllers.ChamberStateMap[state],
|
||||
})
|
||||
|
||||
case t := <-tilt.C:
|
||||
p.publish(config.NATS.Subject.Tilt, js, Tilt{
|
||||
p.Publish(config.NATS.Subject.Tilt, js, Tilt{
|
||||
Time: time.Now().UTC(),
|
||||
Color: string(t.Color()),
|
||||
Gravity: t.Gravity(),
|
||||
|
@ -86,7 +86,7 @@ func (p *DWIngest) Run(ctx context.Context, wg *sync.WaitGroup, js nats.JetStrea
|
|||
}
|
||||
}
|
||||
|
||||
func (p *DWIngest) publish(subject string, js nats.JetStream, reading any) error {
|
||||
func (p *DWIngest) Publish(subject string, js nats.JetStream, reading any) error {
|
||||
b, err := json.Marshal(reading)
|
||||
if err != nil {
|
||||
p.hub.CaptureException(err)
|
||||
|
|
|
@ -13,3 +13,8 @@ type Tilt struct {
|
|||
Gravity float64 `json:"gravity"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Time time.Time `json:"time"`
|
||||
Event string `json:"event"`
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ const (
|
|||
pinHeaterPower = 24
|
||||
pinLightsPower = 25
|
||||
|
||||
// GPIO21 is located at pin 13 on RPi 1B rev 1. Rev 2 and never boards
|
||||
// has GPIO27 here.
|
||||
pinOneWirePower = 21
|
||||
|
||||
off = 0
|
||||
on = 1
|
||||
)
|
||||
|
@ -28,6 +32,7 @@ const (
|
|||
type Gpio struct {
|
||||
chip *gpiod.Chip
|
||||
doorOpen *gpiod.Line
|
||||
oneWirePower *gpiod.Line
|
||||
lightsPower *gpiod.Line
|
||||
fanPower *gpiod.Line
|
||||
coolerPower *gpiod.Line
|
||||
|
@ -71,6 +76,11 @@ func NewGpio() (*Gpio, error) {
|
|||
p.C <- DoorClosed
|
||||
}
|
||||
|
||||
p.oneWirePower, err = p.chip.RequestLine(pinOneWirePower, gpiod.AsOutput(0))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.lightsPower, err = p.chip.RequestLine(pinLightsPower, gpiod.AsOutput(0))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -99,7 +109,9 @@ func (p *Gpio) Close() {
|
|||
p.heaterPower.SetValue(off)
|
||||
p.fanPower.SetValue(off)
|
||||
p.lightsPower.SetValue(off)
|
||||
p.oneWirePower.SetValue(off)
|
||||
|
||||
p.oneWirePower.Close()
|
||||
p.heaterPower.Close()
|
||||
p.coolerPower.Close()
|
||||
p.fanPower.Close()
|
||||
|
@ -142,6 +154,16 @@ func (p *Gpio) LightsOff() {
|
|||
p.lightsPower.SetValue(off)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (p *Gpio) onDoorStateChanged(le gpiod.LineEvent) {
|
||||
switch le.Type {
|
||||
case gpiod.LineEventFallingEdge:
|
||||
|
|
|
@ -42,6 +42,7 @@ var (
|
|||
// Reading receives the temperature readings
|
||||
Reading chan TemperatureReading
|
||||
ConfigUpdate chan configuration.Configuration
|
||||
RequestReset chan bool
|
||||
|
||||
accErrTrigger int
|
||||
sensors []Sensor
|
||||
|
@ -50,6 +51,7 @@ var (
|
|||
func init() {
|
||||
Reading = make(chan TemperatureReading, 30)
|
||||
ConfigUpdate = make(chan configuration.Configuration, 1)
|
||||
RequestReset = make(chan bool)
|
||||
sensors = make([]Sensor, 0)
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,6 @@ func PollSensors(ctx context.Context, wg *sync.WaitGroup, readingInterval time.D
|
|||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
work_loop:
|
||||
select {
|
||||
case <-ticker.C:
|
||||
poll_bus:
|
||||
|
@ -100,7 +101,7 @@ func PollSensors(ctx context.Context, wg *sync.WaitGroup, readingInterval time.D
|
|||
accErrTrigger++
|
||||
hub.CaptureException(err)
|
||||
log.Print(err)
|
||||
break work_loop
|
||||
break
|
||||
}
|
||||
|
||||
accErrTrigger = 0
|
||||
|
@ -119,8 +120,17 @@ func PollSensors(ctx context.Context, wg *sync.WaitGroup, readingInterval time.D
|
|||
}
|
||||
|
||||
if accErrTrigger > 60 {
|
||||
select {
|
||||
case RequestReset <- true:
|
||||
log.Print("Thermal bulk read failed 60 times in a row -- bus reset")
|
||||
|
||||
// Reset counter to allow 60 more reads
|
||||
accErrTrigger = 0
|
||||
|
||||
default:
|
||||
log.Fatal("Thermal bulk read failed 60 times in a row -- terminating")
|
||||
}
|
||||
}
|
||||
|
||||
case c := <-ConfigUpdate:
|
||||
configure(c)
|
||||
|
|
Loading…
Reference in a new issue