From ecc1c8eb3fc6fd010b2b1692527133480c76b0a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Mon, 7 Apr 2025 23:56:04 +0200
Subject: [PATCH] [RIGv2] Rework rocket and OX tank mass load cell sampling

The second load cell on the RIG now measures the rocket mass. The OX tank weight measurement is derived by applying an offset to the rocket mass.
The load cell has also been properly calibrated.
---
 scripts/logdecoder/General/logdecoder.cpp |  1 +
 scripts/logdecoder/RIGv2/logdecoder.cpp   |  1 +
 src/RIGv2/Configs/SensorsConfig.h         | 23 +++++----
 src/RIGv2/Radio/Radio.cpp                 |  4 +-
 src/RIGv2/Sensors/Sensors.cpp             | 60 +++++++++++++++++------
 src/RIGv2/Sensors/Sensors.h               |  5 ++
 src/RIGv2/Sensors/SensorsData.h           | 10 ++++
 7 files changed, 74 insertions(+), 30 deletions(-)

diff --git a/scripts/logdecoder/General/logdecoder.cpp b/scripts/logdecoder/General/logdecoder.cpp
index 056abac66..d6226ce7d 100644
--- a/scripts/logdecoder/General/logdecoder.cpp
+++ b/scripts/logdecoder/General/logdecoder.cpp
@@ -109,6 +109,7 @@ void registerTypes(Deserializer& ds)
     ds.registerType<RIGv2::ADC2Data>();
     ds.registerType<RIGv2::TC1Data>();
     ds.registerType<RIGv2::OxVesselWeightData>();
+    ds.registerType<RIGv2::RocketWeightData>();
     ds.registerType<RIGv2::OxTankWeightData>();
     ds.registerType<RIGv2::OxVesselPressureData>();
     ds.registerType<RIGv2::OxFillingPressureData>();
diff --git a/scripts/logdecoder/RIGv2/logdecoder.cpp b/scripts/logdecoder/RIGv2/logdecoder.cpp
index 66050b858..6062e9ff7 100644
--- a/scripts/logdecoder/RIGv2/logdecoder.cpp
+++ b/scripts/logdecoder/RIGv2/logdecoder.cpp
@@ -57,6 +57,7 @@ void registerTypes(Deserializer& ds)
     ds.registerType<ADC2Data>();
     ds.registerType<TC1Data>();
     ds.registerType<OxVesselWeightData>();
+    ds.registerType<RocketWeightData>();
     ds.registerType<OxTankWeightData>();
     ds.registerType<OxVesselPressureData>();
     ds.registerType<OxFillingPressureData>();
diff --git a/src/RIGv2/Configs/SensorsConfig.h b/src/RIGv2/Configs/SensorsConfig.h
index 7544c895a..ac9e7bea6 100644
--- a/src/RIGv2/Configs/SensorsConfig.h
+++ b/src/RIGv2/Configs/SensorsConfig.h
@@ -27,6 +27,7 @@
 #include <sensors/MAX31856/MAX31856.h>
 #include <units/Frequency.h>
 
+#include <chrono>
 #include <cstdint>
 
 namespace RIGv2
@@ -38,6 +39,7 @@ namespace Config
 namespace Sensors
 {
 
+/* linter off */ using namespace std::chrono;
 /* linter off */ using namespace Boardcore::Units::Frequency;
 
 namespace ADS131M08
@@ -71,7 +73,7 @@ constexpr auto N2_VESSEL_1_PT_CHANNEL = Channel::CHANNEL_2;
 constexpr auto N2_VESSEL_2_PT_CHANNEL = Channel::CHANNEL_3;
 constexpr auto SERVO_CURRENT_CHANNEL  = Channel::CHANNEL_4;
 constexpr auto OX_VESSEL_LC_CHANNEL   = Channel::CHANNEL_5;
-constexpr auto OX_TANK_LC_CHANNEL     = Channel::CHANNEL_6;
+constexpr auto ROCKET_LC_CHANNEL      = Channel::CHANNEL_6;
 constexpr auto N2_FILLING_PT_CHANNEL  = Channel::CHANNEL_7;
 
 constexpr float CH0_SHUNT_RESISTANCE = 29.283f;
@@ -124,17 +126,14 @@ constexpr float N2_TANK_MAX_PRESSURE    = 250;  // bar
 
 namespace LoadCell
 {
-constexpr unsigned int CALIBRATE_SAMPLE_COUNT  = 10;
-constexpr unsigned int CALIBRATE_SAMPLE_PERIOD = 40;
-
-// LC Tank sensor calibration data
-// - 1.866kg V: 0.000941
-// - 5.050kg V: 0.002550
-// - 6.916kg V: 0.003559
-constexpr float TANK_P0_VOLTAGE = 0.000941;
-constexpr float TANK_P0_MASS    = 1.866;
-constexpr float TANK_P1_VOLTAGE = 0.003559;
-constexpr float TANK_P1_MASS    = 6.916;
+constexpr auto CALIBRATE_SAMPLE_COUNT  = 10;
+constexpr auto CALIBRATE_SAMPLE_PERIOD = 40ms;
+
+// Rocket ramp loadcell calibration data
+constexpr float ROCKET_P0_VOLTAGE = -0.0004273;
+constexpr float ROCKET_P0_MASS    = 10.005;
+constexpr float ROCKET_P1_VOLTAGE = -0.0018125;
+constexpr float ROCKET_P1_MASS    = 40.290;
 
 /* OLD CALIBRATION DATA (before 07/09/2024, before new flipping)
 // LC Vessel sensor calibration data
diff --git a/src/RIGv2/Radio/Radio.cpp b/src/RIGv2/Radio/Radio.cpp
index 5422349cb..944fab614 100644
--- a/src/RIGv2/Radio/Radio.cpp
+++ b/src/RIGv2/Radio/Radio.cpp
@@ -564,7 +564,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             tm.timestamp = TimestampTimer::getTimestamp();
 
             // Sensors
-            tm.rocket_mass    = sensors->getOxTankWeight().load;
+            tm.rocket_mass    = sensors->getRocketWeight().load;
             tm.ox_vessel_mass = sensors->getOxVesselWeight().load;
 
             tm.ox_vessel_pressure   = sensors->getOxVesselPressure().pressure;
@@ -873,7 +873,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
 
             tm.timestamp = data.loadTimestamp;
             tm.load      = data.load;
-            strcpy(tm.sensor_name, "TankWeight");
+            strcpy(tm.sensor_name, "OxTankWeight");
 
             mavlink_msg_load_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                        Config::Radio::MAV_COMPONENT_ID, &msg,
diff --git a/src/RIGv2/Sensors/Sensors.cpp b/src/RIGv2/Sensors/Sensors.cpp
index 969505aa9..614a961aa 100644
--- a/src/RIGv2/Sensors/Sensors.cpp
+++ b/src/RIGv2/Sensors/Sensors.cpp
@@ -49,6 +49,7 @@ bool Sensors::start()
         n2Vessel2PressureInit();
         n2FillingPressureInit();
         oxVesselWeightInit();
+        rocketWeightInit();
         oxTankWeightInit();
     }
 
@@ -166,18 +167,17 @@ TemperatureData Sensors::getOxTankTemperature()
 
 LoadCellData Sensors::getOxVesselWeight()
 {
-    if (oxVesselWeight)
-        return oxVesselWeight->getLastSample();
-    else
-        return {};
+    return oxVesselWeight ? oxVesselWeight->getLastSample() : LoadCellData{};
+}
+
+LoadCellData Sensors::getRocketWeight()
+{
+    return rocketWeight ? rocketWeight->getLastSample() : LoadCellData{};
 }
 
 LoadCellData Sensors::getOxTankWeight()
 {
-    if (oxTankWeight)
-        return oxTankWeight->getLastSample();
-    else
-        return {};
+    return oxTankWeight ? oxTankWeight->getLastSample() : LoadCellData{};
 }
 
 CurrentData Sensors::getUmbilicalCurrent()
@@ -290,7 +290,9 @@ void Sensors::calibrate()
         oxVesselStats.add(oxVesselWeight->getLastSample().load);
         oxTankStats.add(oxTankWeight->getLastSample().load);
 
-        Thread::sleep(Config::Sensors::LoadCell::CALIBRATE_SAMPLE_PERIOD);
+        Thread::sleep(
+            milliseconds{Config::Sensors::LoadCell::CALIBRATE_SAMPLE_PERIOD}
+                .count());
     }
 
     oxVesselWeight->updateOffset(oxVesselStats.getStats().mean);
@@ -321,6 +323,7 @@ std::vector<SensorInfo> Sensors::getSensorInfos()
         PUSH_SENSOR_INFO(oxTankPressure, "OxTankPressure");
         PUSH_SENSOR_INFO(n2TankPressure, "N2TankPressure");
         PUSH_SENSOR_INFO(oxVesselWeight, "OxVesselWeight");
+        PUSH_SENSOR_INFO(rocketWeight, "RocketWeight");
         PUSH_SENSOR_INFO(oxTankWeight, "OxTankWeight");
 
         return infos;
@@ -401,7 +404,7 @@ void Sensors::adc1Init()
         .offset  = 0,
         .gain    = 1.0};
 
-    config.channelsConfig[(int)Config::Sensors::ADC_1::OX_TANK_LC_CHANNEL] = {
+    config.channelsConfig[(int)Config::Sensors::ADC_1::ROCKET_LC_CHANNEL] = {
         .enabled = true,
         .pga     = ADS131M08Defs::PGA::PGA_32,
         .offset  = 0,
@@ -628,19 +631,37 @@ void Sensors::oxVesselWeightCallback()
     sdLogger.log(OxVesselWeightData{getOxVesselWeight()});
 }
 
+void Sensors::rocketWeightInit()
+{
+    rocketWeight = std::make_unique<TwoPointAnalogLoadCell>(
+        [this]()
+        {
+            auto sample = getADC1LastSample();
+            return sample.getVoltage(Config::Sensors::ADC_1::ROCKET_LC_CHANNEL);
+        },
+        Config::Sensors::LoadCell::ROCKET_P0_VOLTAGE,
+        Config::Sensors::LoadCell::ROCKET_P0_MASS,
+        Config::Sensors::LoadCell::ROCKET_P1_VOLTAGE,
+        Config::Sensors::LoadCell::ROCKET_P1_MASS);
+}
+
+void Sensors::rocketWeightCallback()
+{
+    sdLogger.log(RocketWeightData{getRocketWeight()});
+}
+
 void Sensors::oxTankWeightInit()
 {
     oxTankWeight = std::make_unique<TwoPointAnalogLoadCell>(
         [this]()
         {
             auto sample = getADC1LastSample();
-            return sample.getVoltage(
-                Config::Sensors::ADC_1::OX_TANK_LC_CHANNEL);
+            return sample.getVoltage(Config::Sensors::ADC_1::ROCKET_LC_CHANNEL);
         },
-        Config::Sensors::LoadCell::TANK_P0_VOLTAGE,
-        Config::Sensors::LoadCell::TANK_P0_MASS,
-        Config::Sensors::LoadCell::TANK_P1_VOLTAGE,
-        Config::Sensors::LoadCell::TANK_P1_MASS);
+        Config::Sensors::LoadCell::ROCKET_P0_VOLTAGE,
+        Config::Sensors::LoadCell::ROCKET_P0_MASS,
+        Config::Sensors::LoadCell::ROCKET_P1_VOLTAGE,
+        Config::Sensors::LoadCell::ROCKET_P1_MASS);
 }
 
 void Sensors::oxTankWeightCallback()
@@ -739,6 +760,13 @@ bool Sensors::sensorManagerInit()
         map.emplace(std::make_pair(oxVesselWeight.get(), info));
     }
 
+    if (rocketWeight)
+    {
+        SensorInfo info("RocketWeight", Config::Sensors::ADS131M08::PERIOD,
+                        [this]() { rocketWeightCallback(); });
+        map.emplace(std::make_pair(rocketWeight.get(), info));
+    }
+
     if (oxTankWeight)
     {
         SensorInfo info("OxTankWeight", Config::Sensors::ADS131M08::PERIOD,
diff --git a/src/RIGv2/Sensors/Sensors.h b/src/RIGv2/Sensors/Sensors.h
index e38a2de50..f7f9bffe5 100644
--- a/src/RIGv2/Sensors/Sensors.h
+++ b/src/RIGv2/Sensors/Sensors.h
@@ -70,6 +70,7 @@ public:
 
     Boardcore::TemperatureData getOxTankTemperature();
     Boardcore::LoadCellData getOxVesselWeight();
+    Boardcore::LoadCellData getRocketWeight();
     Boardcore::LoadCellData getOxTankWeight();
 
     Boardcore::CurrentData getUmbilicalCurrent();
@@ -117,6 +118,9 @@ private:
     void oxVesselWeightInit();
     void oxVesselWeightCallback();
 
+    void rocketWeightInit();
+    void rocketWeightCallback();
+
     void oxTankWeightInit();
     void oxTankWeightCallback();
 
@@ -158,6 +162,7 @@ private:
     std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankPressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2TankPressure;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> oxVesselWeight;
+    std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> rocketWeight;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> oxTankWeight;
 
     // Digital sensors
diff --git a/src/RIGv2/Sensors/SensorsData.h b/src/RIGv2/Sensors/SensorsData.h
index 71ae7b241..ad36d2177 100644
--- a/src/RIGv2/Sensors/SensorsData.h
+++ b/src/RIGv2/Sensors/SensorsData.h
@@ -69,6 +69,16 @@ struct OxVesselWeightData : Boardcore::LoadCellData
     OxVesselWeightData() {}
 };
 
+struct RocketWeightData : Boardcore::LoadCellData
+{
+    explicit RocketWeightData(const Boardcore::LoadCellData& data)
+        : Boardcore::LoadCellData(data)
+    {
+    }
+
+    RocketWeightData() {}
+};
+
 struct OxTankWeightData : Boardcore::LoadCellData
 {
     explicit OxTankWeightData(const Boardcore::LoadCellData& data)
-- 
GitLab