firmware/src/modules/Telemetry/Sensor/NAU7802Sensor.cpp
Markus a71b47b5bb
Some checks are pending
CI / setup (all) (push) Waiting to run
CI / setup (check) (push) Waiting to run
CI / version (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build (push) Blocked by required conditions
CI / build-debian-src (push) Waiting to run
CI / package-pio-deps-native-tft (push) Waiting to run
CI / test-native (push) Waiting to run
CI / docker (alpine, native, linux/amd64) (push) Waiting to run
CI / docker (alpine, native, linux/arm64) (push) Waiting to run
CI / docker (alpine, native-tft, linux/amd64) (push) Waiting to run
CI / docker (debian, native, linux/amd64) (push) Waiting to run
CI / docker (debian, native, linux/arm/v7) (push) Waiting to run
CI / docker (debian, native, linux/arm64) (push) Waiting to run
CI / docker (debian, native-tft, linux/amd64) (push) Waiting to run
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (rp2350) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (rp2350) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
CI / publish-firmware (push) Blocked by required conditions
rework sensor instantiation to saves memory by removing the static allocation (#8054)
* rework I2C sensor init

the goal is to only instantiate sensors that are pressend to save memory.
side effacts:
 - easyer sensor integration (less C&P code)
 - nodeTelemetrySensorsMap can be removed when all devices are migrated

* add missing ifdef

* refactor a bunch of more sensors

RAM -816
Flash -916

* fix build for t1000

* refactor more sensors

RAM -192
Flash -60

* improve error handling

Flash -112

* fix build

* fix build

* fix IndicatorSensor

* fix tracker-t1000-e build

not sure what magic is used but it works

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/Telemetry/Sensor/DFRobotGravitySensor.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-13 11:09:33 -05:00

143 lines
4.8 KiB
C++

#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "FSCommon.h"
#include "NAU7802Sensor.h"
#include "SPILock.h"
#include "SafeFile.h"
#include "TelemetrySensor.h"
#include <Throttle.h>
#include <pb_decode.h>
#include <pb_encode.h>
meshtastic_Nau7802Config nau7802config = meshtastic_Nau7802Config_init_zero;
NAU7802Sensor::NAU7802Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_NAU7802, "NAU7802") {}
bool NAU7802Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
{
LOG_INFO("Init sensor: %s", sensorName);
status = nau7802.begin(*bus);
if (!status) {
return status;
}
nau7802.setSampleRate(NAU7802_SPS_320);
if (!loadCalibrationData()) {
LOG_ERROR("Failed to load calibration data");
}
nau7802.calibrateAFE();
LOG_INFO("Offset: %d, Calibration factor: %.2f", nau7802.getZeroOffset(), nau7802.getCalibrationFactor());
initI2CSensor();
return status;
}
bool NAU7802Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
LOG_DEBUG("NAU7802 getMetrics");
nau7802.powerUp();
// Wait for the sensor to become ready for one second max
uint32_t start = millis();
while (!nau7802.available()) {
delay(100);
if (!Throttle::isWithinTimespanMs(start, 1000)) {
nau7802.powerDown();
return false;
}
}
measurement->variant.environment_metrics.has_weight = true;
// Check if we have correct calibration values after powerup
LOG_DEBUG("Offset: %d, Calibration factor: %.2f", nau7802.getZeroOffset(), nau7802.getCalibrationFactor());
measurement->variant.environment_metrics.weight = nau7802.getWeight() / 1000; // sample is in kg
nau7802.powerDown();
return true;
}
void NAU7802Sensor::calibrate(float weight)
{
nau7802.calculateCalibrationFactor(weight * 1000, 64); // internal sample is in grams
if (!saveCalibrationData()) {
LOG_WARN("Failed to save calibration data");
}
LOG_INFO("Offset: %d, Calibration factor: %.2f", nau7802.getZeroOffset(), nau7802.getCalibrationFactor());
}
AdminMessageHandleResult NAU7802Sensor::handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response)
{
AdminMessageHandleResult result;
switch (request->which_payload_variant) {
case meshtastic_AdminMessage_set_scale_tag:
if (request->set_scale == 0) {
this->tare();
LOG_DEBUG("Client requested to tare scale");
} else {
this->calibrate(request->set_scale);
LOG_DEBUG("Client requested to calibrate to %d kg", request->set_scale);
}
result = AdminMessageHandleResult::HANDLED;
break;
default:
result = AdminMessageHandleResult::NOT_HANDLED;
}
return result;
}
void NAU7802Sensor::tare()
{
nau7802.calculateZeroOffset(64);
if (!saveCalibrationData()) {
LOG_WARN("Failed to save calibration data");
}
LOG_INFO("Offset: %d, Calibration factor: %.2f", nau7802.getZeroOffset(), nau7802.getCalibrationFactor());
}
bool NAU7802Sensor::saveCalibrationData()
{
auto file = SafeFile(nau7802ConfigFileName);
nau7802config.zeroOffset = nau7802.getZeroOffset();
nau7802config.calibrationFactor = nau7802.getCalibrationFactor();
bool okay = false;
LOG_INFO("%s state write to %s", sensorName, nau7802ConfigFileName);
pb_ostream_t stream = {&writecb, static_cast<Print *>(&file), meshtastic_Nau7802Config_size};
if (!pb_encode(&stream, &meshtastic_Nau7802Config_msg, &nau7802config)) {
LOG_ERROR("Error: can't encode protobuf %s", PB_GET_ERROR(&stream));
} else {
okay = true;
}
// Note: SafeFile::close() already acquires the lock and releases it internally
okay &= file.close();
return okay;
}
bool NAU7802Sensor::loadCalibrationData()
{
spiLock->lock();
auto file = FSCom.open(nau7802ConfigFileName, FILE_O_READ);
bool okay = false;
if (file) {
LOG_INFO("%s state read from %s", sensorName, nau7802ConfigFileName);
pb_istream_t stream = {&readcb, &file, meshtastic_Nau7802Config_size};
if (!pb_decode(&stream, &meshtastic_Nau7802Config_msg, &nau7802config)) {
LOG_ERROR("Error: can't decode protobuf %s", PB_GET_ERROR(&stream));
} else {
nau7802.setZeroOffset(nau7802config.zeroOffset);
nau7802.setCalibrationFactor(nau7802config.calibrationFactor);
okay = true;
}
file.close();
} else {
LOG_INFO("No %s state found (File: %s)", sensorName, nau7802ConfigFileName);
}
spiLock->unlock();
return okay;
}
#endif