48 lines
1.8 KiB
C++
48 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
namespace fgc {
|
|
|
|
// Sensirion SHT4x (SHT41) I2C protocol helpers: the command bytes, the CRC-8
|
|
// the sensor appends to each 16-bit word, and the decode from a raw 6-byte
|
|
// measurement response to physical units. Kept pure (no I/O) so it is
|
|
// unit-testable and lives in fgc_core — mirrors MtiProtocol / TelemetryParser.
|
|
// The I/O half (bus, poll thread, staleness) stays in Sht41EnvSensor.
|
|
//
|
|
// Measurement response layout, big-endian:
|
|
// [0..1] temperature raw [2] CRC of bytes 0..1
|
|
// [3..4] humidity raw [5] CRC of bytes 3..4
|
|
|
|
// Soft reset; the datasheet asks for ~1 ms to settle afterwards.
|
|
inline constexpr uint8_t kSht41CmdSoftReset = 0x94;
|
|
// Measure temperature + RH, high precision; ~10 ms conversion time.
|
|
inline constexpr uint8_t kSht41CmdMeasureHighPrec = 0xFD;
|
|
|
|
// Bytes in a measurement response.
|
|
inline constexpr size_t kSht41ResponseBytes = 6;
|
|
|
|
// SHT4x CRC-8: polynomial 0x31, init 0xFF, no reflection, no final XOR.
|
|
// Datasheet test vector: {0xBE, 0xEF} -> 0x92.
|
|
uint8_t sht41Crc8(const uint8_t* data, size_t len);
|
|
|
|
// One decoded measurement in physical units.
|
|
struct Sht41Reading {
|
|
float temp_c = 0.0f;
|
|
float humidity_pct = 0.0f;
|
|
};
|
|
|
|
// Decode a measurement response. Returns nullopt if the response is not
|
|
// kSht41ResponseBytes long or either word fails its CRC — a corrupt frame must
|
|
// be discarded rather than reported as a reading, since a garbled word is
|
|
// indistinguishable from a plausible temperature once converted.
|
|
//
|
|
// Conversions (datasheet): T[°C] = -45 + 175 * raw/65535,
|
|
// RH[%] = -6 + 125 * raw/65535, with RH clamped to 0..100 (the raw formula
|
|
// slightly overshoots both ends by design).
|
|
std::optional<Sht41Reading> decodeSht41Measurement(const std::vector<uint8_t>& rx);
|
|
|
|
} // namespace fgc
|