Compare commits

...

2 commits

Author SHA1 Message Date
Rahix 152290f5a3 succd: Fix -KEC1 relay board updates
All checks were successful
/ test (push) Successful in 10s
/ test (pull_request) Successful in 10s
The accesses to -KEC1 always time out on the attempt to update the
output values.  We noticed that this is related to the timing between
the reading of the inputs and the following write to the outputs.

Fix -KEC1 accesses by waiting before sending the next request to the
board after receiving the reply for the previous one.
2024-11-10 06:36:43 +01:00
hmelder 6f93b96c39 succd: do not early return on error in modbusUpdate
When one device fails, this should not influence updates of the other
devices.  Thus, early return was the wrong strategy here.

Instead, when communication with a device fails, skip the process data
update and continue with the next device.
2024-11-10 06:35:50 +01:00

View file

@ -2,11 +2,10 @@ package main
import ( import (
"context" "context"
"errors"
"fmt"
"time" "time"
"github.com/simonvetter/modbus" "github.com/simonvetter/modbus"
"k8s.io/klog"
) )
func modbusValuesToFloat(v uint16) float32 { func modbusValuesToFloat(v uint16) float32 {
@ -39,7 +38,7 @@ func (d *daemon) modbusConnect() error {
// There are currently two devices connected to the modbus. // There are currently two devices connected to the modbus.
// The first one (slave 1) is a temperature/humidity sensor. // The first one (slave 1) is a temperature/humidity sensor.
// The second one (slave 2) is a PTA8D08 transmitter // The second one (slave 2) is a PTA8D08 transmitter
func (d *daemon) modbusUpdate() error { func (d *daemon) modbusUpdate() {
var err error var err error
// Switch to slave 1 (BTA1) // Switch to slave 1 (BTA1)
@ -49,19 +48,16 @@ func (d *daemon) modbusUpdate() error {
var registersBTA1 []uint16 // temperature, humidity var registersBTA1 []uint16 // temperature, humidity
registersBTA1, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER) registersBTA1, err = d.modbusClient.ReadRegisters(1, 2, modbus.INPUT_REGISTER)
if err != nil { if err != nil {
return err klog.Warningf("error while reading registers from BTA1 %v", err)
} else if len(registersBTA1) != 2 {
klog.Warningf("expected two registers from modbus slave 1, but got %d", len(registersBTA1))
} else {
d.mu.Lock()
d.daemonState.tempSEM = modbusValuesToFloat(registersBTA1[0])
d.daemonState.humiditySEM = modbusValuesToFloat(registersBTA1[1])
d.mu.Unlock()
} }
if len(registersBTA1) != 2 {
msg := fmt.Sprintf("Expected two registers from modbus slave 1, but got %d", len(registersBTA1))
return errors.New(msg)
}
d.mu.Lock()
d.daemonState.tempSEM = modbusValuesToFloat(registersBTA1[0])
d.daemonState.humiditySEM = modbusValuesToFloat(registersBTA1[1])
d.mu.Unlock()
// Switch to slave 2 (KEC2) // Switch to slave 2 (KEC2)
d.modbusClient.SetUnitId(2) d.modbusClient.SetUnitId(2)
@ -72,19 +68,17 @@ func (d *daemon) modbusUpdate() error {
var registersKEC2 []uint16 // temperatures dp var registersKEC2 []uint16 // temperatures dp
registersKEC2, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER) registersKEC2, err = d.modbusClient.ReadRegisters(0, 3, modbus.HOLDING_REGISTER)
if err != nil { if err != nil {
return err klog.Warningf("error while reading registers from KEC2 %v", err)
} else if len(registersKEC2) != 3 {
klog.Warningf("expected three registers from modbus slave 2, but got %d", len(registersKEC2))
} else {
d.mu.Lock()
d.daemonState.tempDPBottom = modbusValuesToFloat(registersKEC2[0])
d.daemonState.tempDPInlet = modbusValuesToFloat(registersKEC2[1])
d.daemonState.tempDPTop = modbusValuesToFloat(registersKEC2[2])
d.mu.Unlock()
} }
if len(registersKEC2) != 3 {
return fmt.Errorf("expected three registers from modbus slave 2, but got %d", len(registersKEC2))
}
d.mu.Lock()
d.daemonState.tempDPBottom = modbusValuesToFloat(registersKEC2[0])
d.daemonState.tempDPInlet = modbusValuesToFloat(registersKEC2[1])
d.daemonState.tempDPTop = modbusValuesToFloat(registersKEC2[2])
d.mu.Unlock()
// Switch to slave 3 (KEC1) // Switch to slave 3 (KEC1)
d.modbusClient.SetUnitId(3) d.modbusClient.SetUnitId(3)
@ -94,17 +88,23 @@ func (d *daemon) modbusUpdate() error {
digitalInputRegisters, err = d.modbusClient.ReadRegisters(0x81, 8, modbus.HOLDING_REGISTER) digitalInputRegisters, err = d.modbusClient.ReadRegisters(0x81, 8, modbus.HOLDING_REGISTER)
if err != nil { if err != nil {
return err klog.Warningf("error while reading digital inputs from KEC1 %v", err)
} } else {
// Convert MODBUS words into bools // Convert MODBUS words into bools
for idx, value := range digitalInputRegisters { for idx, value := range digitalInputRegisters {
if value != 0 { if value != 0 {
digitalInputs[idx] = true digitalInputs[idx] = true
} else { } else {
digitalInputs[idx] = false digitalInputs[idx] = false
}
} }
// TODO: Input mapping goes here
} }
// TODO: Input mapping goes here
// We must wait between reading and writing to the -KEC1 relay board
// because otherwise it chokes and times out the write registers
// command.
time.Sleep(time.Millisecond * 10)
// KFA1-KFA8 // KFA1-KFA8
var relayState [8]bool var relayState [8]bool
@ -140,10 +140,8 @@ func (d *daemon) modbusUpdate() error {
err = d.modbusClient.WriteRegisters(0x01, registerValuesKEC1[:]) err = d.modbusClient.WriteRegisters(0x01, registerValuesKEC1[:])
if err != nil { if err != nil {
return err klog.Warningf("error while updating registers %v", err)
} }
return nil
} }
// Call modbusUpdate every 100 milliseconds // Call modbusUpdate every 100 milliseconds