You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devices/sen6x/status.go

191 lines
6.0 KiB
Go

// Copyright 2026 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package sen6x
import "encoding/binary"
// Status represents the status of the sensor's various components, indicating
// whether or not each is in an error state.
//
// If a status value is sticky then it remains set even if the error disappears
// or if the sensor leaves measurement mode. The status will only be reset by
// [Dev.ReadAndClearDeviceStatus] or by a reset, either by calling [Dev.DeviceReset]
// or power cycling the sensor.
type Status struct {
// FanSpeedErr is the fan speed error status. A value of true indicates that the fan
// speed is too high or too low.
//
// Applies to: SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C
//
// Sticky: No
//
// Description from the datasheet:
//
// Fan is switched on, but its speed is more than 10% off the target speed
// for multiple consecutive measurement intervals. During the first 10 seconds
// after starting the measurement, the fan speed is not checked (settling time).
// Very low or very high ambient temperature could trigger this warning during
// startup. If this flag is set constantly, it might indicate a problem with
// the power supply or with the fan, and the measured PM values might be wrong.
// This flag is automatically cleared as soon as the measured speed is within 10%
// of the target speed or when leaving the measurement mode.
// Can occur only in measurement mode.
FanSpeedErr bool
// FanErr is the fan error status.
//
// Applies to: SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Fan is switched on, but 0 RPM is measured for multiple consecutive measurement
// intervals. This can occur if the fan is mechanically blocked or broken. Note
// that the measured values are most likely wrong if this error is reported.
// Can occur only in measurement mode.
FanErr bool
// PMSensorErr is the particulate matter sensor error status.
//
// Applies to: SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Error related to the PM sensor. The particulate matter values might be unknown
// or wrong if this flag is set, [and] relative humidity and temperature values
// might be out of specs due to compensation algorithms depending on PM sensor state.
// Can occur only in measurement mode.
PMSensorErr bool
// RHTSensorErr is the relative humidity and temperature sensor error status.
//
// Applies to: SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Error related to the RH&T sensor. The temperature and humidity values might be
// unknown or wrong if this flag is set, and other measured values might be out of
// specs due compensation algorithms depending on RH&T sensor values.
// Can occur only in measurement mode.
RHTSensorErr bool
// CO2SensorErr is the CO2 sensor error status.
//
// Applies to: SEN63C, SEN66, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Error related to the CO2 sensor. The CO2 values might be unknown or wrong if
// this flag is set, [and] relative humidity and temperature values might be out of
// specs due to compensation algorithms depending on CO2 sensor state.
// Can occur only in measurement mode.
CO2SensorErr bool
// GasSensorErr is the gas (VOC and NOx) sensor error status.
//
// Applies to: SEN65, SEN66, SEN68, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Error related to the gas sensor. The VOC index and NOx index might be unknown
// or wrong if this flag is set, [and] relative humidity and temperature values
// might be out of specs due to compensation algorithms depending on gas sensor state.
// Can occur only in measurement mode.
GasSensorErr bool
// HCHOSensorErr is the formaldehyde sensor error status.
//
// Applies to: SEN68, SEN69C
//
// Sticky: Yes
//
// Description from the datasheet:
//
// Error related to the formaldehyde sensor. The formaldehyde values might be
// unknown or wrong if this flag is set, [and] relative humidity and temperature
// values might be out of specs due to compensation algorithms depending on
// formaldehyde sensor state.
// Can occur only in measurement mode.
HCHOSensorErr bool
}
func (s *Status) AnyErr() bool {
return s.FanSpeedErr ||
s.FanErr ||
s.PMSensorErr ||
s.RHTSensorErr ||
s.CO2SensorErr ||
s.GasSensorErr ||
s.HCHOSensorErr
}
// ReadDeviceStatus reads and decodes the current value of the device status register.
func (d *Dev) ReadDeviceStatus() (*Status, error) {
d.mu.Lock()
defer d.mu.Unlock()
data, err := d.writeAndRead(cmdReadDeviceStatus, nil)
if err != nil {
return nil, err
}
return d.statusFromRegister(binary.BigEndian.Uint32(data)), nil
}
// ReadAndClearDeviceStatus reads the current device status (like [Dev.ReadDeviceStatus])
// and afterwards clears all flags.
func (d *Dev) ReadAndClearDeviceStatus() (*Status, error) {
d.mu.Lock()
defer d.mu.Unlock()
data, err := d.writeAndRead(cmdReadAndClearDeviceStatus, nil)
if err != nil {
return nil, err
}
return d.statusFromRegister(binary.BigEndian.Uint32(data)), nil
}
func (d *Dev) statusFromRegister(register uint32) *Status {
status := &Status{
FanSpeedErr: registerBitBool(register, 21),
FanErr: registerBitBool(register, 4),
PMSensorErr: registerBitBool(register, 11),
RHTSensorErr: registerBitBool(register, 6),
}
if d.model.hasCO2() {
if d.model == SEN66 {
status.CO2SensorErr = registerBitBool(register, 9)
} else {
// SEN63C and SEN69C.
status.CO2SensorErr = registerBitBool(register, 12)
}
}
if d.model.hasVOCNOx() {
status.GasSensorErr = registerBitBool(register, 7)
}
if d.model.hasHCHO() {
status.HCHOSensorErr = registerBitBool(register, 10)
}
return status
}
func registerBitBool(register uint32, bit uint) bool {
return uint8((register>>bit)&1) == 1
}