SHT41 bug resolved. It now logs reading failures.

This commit is contained in:
pgdalmeida 2026-09-02 12:08:31 +02:00
parent d3514f7d2b
commit 6c1941cc80
Signed by: pedro.almeida
GPG Key ID: D4A6C394DF13F1D7
2 changed files with 44 additions and 3 deletions

View File

@ -28,6 +28,11 @@ public:
bool writeRead(const std::vector<uint8_t>& tx, std::vector<uint8_t>& rx); bool writeRead(const std::vector<uint8_t>& tx, std::vector<uint8_t>& rx);
bool write(const std::vector<uint8_t>& tx); bool write(const std::vector<uint8_t>& tx);
// For diagnostics: what this bus is actually pointed at. A silent sensor is
// almost always the wrong bus or address, so error messages should name both.
const std::string& device() const { return device_; }
uint8_t address() const { return addr_; }
private: private:
std::string device_; std::string device_;
uint8_t addr_; uint8_t addr_;

View File

@ -5,6 +5,7 @@
#include "fgc/sensors/Sht41Protocol.h" #include "fgc/sensors/Sht41Protocol.h"
#include <atomic> #include <atomic>
#include <ios>
#include <chrono> #include <chrono>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
@ -36,11 +37,37 @@ struct Sht41EnvSensor::Impl {
EnvSample latest; EnvSample latest;
clock::time_point last_ok{}; clock::time_point last_ok{};
// Consecutive failed reads. The transfers run every `period` forever, so the
// failure is logged on the FIRST one only: a wrong bus would otherwise print
// the same line every couple of seconds for the life of the process. Reset on
// a good read, which also gives us a recovery message.
long long fail_streak = 0;
// A silent sensor is nearly always the wrong bus or address, and neither
// open() nor the I2C_SLAVE ioctl can tell you that - the ioctl only records
// the target address, it never probes. This is the first point where the
// absence of a device is actually observable, so it is where it gets said.
void reportFailure(const char* what) {
if (fail_streak++ > 0) return;
LOG_ERROR << "SHT41: " << what << " at address 0x" << std::hex
<< static_cast<int>(bus.address()) << std::dec << " on " << bus.device()
<< " - check [Env] i2c_device/i2c_addr and the wiring"
<< " (probe with: i2cdetect -l, then i2ctransfer -y <bus> w1@0x"
<< std::hex << static_cast<int>(bus.address()) << std::dec << " 0x89)";
LOG_ERROR << "SHT41: further read failures will not be logged until it responds";
}
void readOnce() { void readOnce() {
if (!bus.write({kSht41CmdMeasureHighPrec})) return; if (!bus.write({kSht41CmdMeasureHighPrec})) {
reportFailure("no response to the measure command");
return;
}
std::this_thread::sleep_for(kConversionDelay); std::this_thread::sleep_for(kConversionDelay);
std::vector<uint8_t> rx(kSht41ResponseBytes); std::vector<uint8_t> rx(kSht41ResponseBytes);
if (!bus.writeRead({}, rx)) return; if (!bus.writeRead({}, rx)) {
reportFailure("command acknowledged but no measurement came back");
return;
}
auto reading = decodeSht41Measurement(rx); auto reading = decodeSht41Measurement(rx);
if (!reading) { if (!reading) {
@ -48,6 +75,11 @@ struct Sht41EnvSensor::Impl {
return; return;
} }
if (fail_streak > 0) {
LOG_INFO << "SHT41: responding again after " << fail_streak << " failed read(s)";
fail_streak = 0;
}
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
latest.valid = true; latest.valid = true;
latest.temp_c = reading->temp_c; latest.temp_c = reading->temp_c;
@ -81,7 +113,11 @@ void Sht41EnvSensor::start() {
std::this_thread::sleep_for(kSoftResetSettle); std::this_thread::sleep_for(kSoftResetSettle);
impl_->running = true; impl_->running = true;
impl_->worker = std::thread([this] { impl_->run(); }); impl_->worker = std::thread([this] { impl_->run(); });
LOG_INFO << "SHT41 env sensor started"; // Deliberately not "started OK": opening the node proves nothing about the
// sensor being there. The first read either succeeds quietly or logs why not.
LOG_INFO << "SHT41 env sensor polling 0x" << std::hex << static_cast<int>(impl_->bus.address())
<< std::dec << " on " << impl_->bus.device() << " every "
<< impl_->period.count() << " ms";
} }
void Sht41EnvSensor::stop() { void Sht41EnvSensor::stop() {