From 6fd57022bdb5b43e168ff9a23057a99b5d2a99e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 13 Mar 2025 11:25:55 +0100
Subject: [PATCH 01/13] [RIGv2] Improve sensor initialization

* Add missing pressure transducers initialization
* Improve failure reporting
* Add ADC specific enable flags
---
 src/RIGv2/Configs/SensorsConfig.h |  5 ++++-
 src/RIGv2/Sensors/Sensors.cpp     | 26 ++++++++++++++++++--------
 src/RIGv2/rig-v2-entry.cpp        |  9 +++++----
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/src/RIGv2/Configs/SensorsConfig.h b/src/RIGv2/Configs/SensorsConfig.h
index 397a5bd8a..225da353d 100644
--- a/src/RIGv2/Configs/SensorsConfig.h
+++ b/src/RIGv2/Configs/SensorsConfig.h
@@ -46,7 +46,6 @@ constexpr auto OSR = Boardcore::ADS131M08Defs::OversamplingRatio::OSR_8192;
 constexpr bool GLOBAL_CHOP_MODE_EN = true;
 
 constexpr Hertz PERIOD = 100_hz;
-constexpr bool ENABLED = true;
 
 // Servo current sensor calibration data
 // - A: 0.0 V: 2.520
@@ -62,6 +61,8 @@ constexpr float SERVO_CURRENT_ZERO  = 2.520 / SERVO_CURRENT_SCALE;
 
 namespace ADC_1
 {
+constexpr bool ENABLED = true;
+
 using Channel = Boardcore::ADS131M08Defs::Channel;
 
 constexpr auto OX_VESSEL_PT_CHANNEL   = Channel::CHANNEL_0;
@@ -82,6 +83,8 @@ constexpr float CH7_SHUNT_RESISTANCE = 29.0;     // TODO: measure
 
 namespace ADC_2
 {
+constexpr bool ENABLED = true;
+
 using Channel = Boardcore::ADS131M08Defs::Channel;
 
 constexpr auto OX_TANK_TOP_PT_CHANNEL    = Channel::CHANNEL_0;
diff --git a/src/RIGv2/Sensors/Sensors.cpp b/src/RIGv2/Sensors/Sensors.cpp
index a6f3aed84..5eec560c6 100644
--- a/src/RIGv2/Sensors/Sensors.cpp
+++ b/src/RIGv2/Sensors/Sensors.cpp
@@ -26,6 +26,9 @@
 #include <drivers/timer/TimestampTimer.h>
 #include <interfaces-impl/hwmapping.h>
 
+#include <chrono>
+
+using namespace std::chrono;
 using namespace Boardcore;
 using namespace miosix;
 using namespace RIGv2;
@@ -37,18 +40,25 @@ bool Sensors::start()
     if (Config::Sensors::InternalADC::ENABLED)
         internalAdcInit();
 
-    if (Config::Sensors::ADS131M08::ENABLED)
+    if (Config::Sensors::ADC_1::ENABLED)
     {
         adc1Init();
-        adc2Init();
         oxVesselPressureInit();
         oxFillingPressureInit();
-        oxTankTopPressureInit();
-        oxTankBottomPressureInit();
+        n2Vessel1PressureInit();
+        n2Vessel2PressureInit();
+        n2FillingPressureInit();
         oxVesselWeightInit();
         oxTankWeightInit();
     }
 
+    if (Config::Sensors::ADC_2::ENABLED)
+    {
+        adc2Init();
+        oxTankTopPressureInit();
+        oxTankBottomPressureInit();
+    }
+
     if (Config::Sensors::MAX31856::ENABLED)
         tc1Init();
 
@@ -297,11 +307,11 @@ std::vector<SensorInfo> Sensors::getSensorInfos()
     if (instance)                                                \
         infos.push_back(manager->getSensorInfo(instance.get())); \
     else                                                         \
-        infos.push_back(SensorInfo { #name, 0, nullptr, false })
+        infos.push_back(SensorInfo{name, 0ns, nullptr, false})
 
-        PUSH_SENSOR_INFO(adc1, "ADC1");
-        PUSH_SENSOR_INFO(adc2, "ADC2");
-        PUSH_SENSOR_INFO(tc1, "TC1");
+        PUSH_SENSOR_INFO(adc1, "ADS131M08_1");
+        PUSH_SENSOR_INFO(adc2, "ADS131M08_2");
+        PUSH_SENSOR_INFO(tc1, "MAX31856_1");
         PUSH_SENSOR_INFO(internalAdc, "InternalADC");
         PUSH_SENSOR_INFO(oxVesselPressure, "OxVesselPressure");
         PUSH_SENSOR_INFO(oxFillingPressure, "OxFillingPressure");
diff --git a/src/RIGv2/rig-v2-entry.cpp b/src/RIGv2/rig-v2-entry.cpp
index b8ec84e95..013353999 100644
--- a/src/RIGv2/rig-v2-entry.cpp
+++ b/src/RIGv2/rig-v2-entry.cpp
@@ -37,9 +37,11 @@
 #include <events/EventData.h>
 #include <events/utils/EventSniffer.h>
 
+#include <chrono>
 #include <iomanip>
 #include <iostream>
 
+using namespace std::chrono;
 using namespace Boardcore;
 using namespace Common;
 using namespace RIGv2;
@@ -83,8 +85,6 @@ int main()
                       manager.insert<GroundModeManager>(gmm) &&
                       manager.insert<TARS1>(tars1) && manager.inject();
 
-    manager.graphviz(std::cout);
-
     if (!initResult)
     {
         std::cout << "Failed to inject dependencies" << std::endl;
@@ -208,11 +208,12 @@ int main()
     std::cout << "Sensor status:" << std::endl;
     for (auto info : sensors->getSensorInfos())
     {
-        auto statusStr = !info.isEnabled      ? "Disabled"
+        // The period being 0 means the sensor is disabled
+        auto statusStr = info.period == 0ns   ? "Disabled"
                          : info.isInitialized ? "Ok"
                                               : "Error";
 
-        std::cout << "\t" << std::setw(16) << std::left << info.id << " "
+        std::cout << "\t" << std::setw(20) << std::left << info.id << " "
                   << statusStr << std::endl;
     }
 
-- 
GitLab


From 5127bb841f9b54ac63819a6c028021d3ee6cbf1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 13 Mar 2025 11:36:49 +0100
Subject: [PATCH 02/13] [RIGv2] Reword initial registry load failure message

---
 src/RIGv2/rig-v2-entry.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/RIGv2/rig-v2-entry.cpp b/src/RIGv2/rig-v2-entry.cpp
index 013353999..6548c191f 100644
--- a/src/RIGv2/rig-v2-entry.cpp
+++ b/src/RIGv2/rig-v2-entry.cpp
@@ -115,7 +115,8 @@ int main()
     // Perform an initial registry load
     std::cout << "Loading backed registry" << std::endl;
     if (registry->load() != RegistryError::OK)
-        std::cout << "*** Failed to load backed registry ***" << std::endl;
+        std::cout << "* Warning: could not load a saved registry *"
+                  << std::endl;
 
     std::cout << "Starting Actuators" << std::endl;
     if (!actuators->start())
-- 
GitLab


From d541a1102adc723e71c63f104351d462caeb7310 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 13 Mar 2025 12:07:17 +0100
Subject: [PATCH 03/13] [ConRIG] Lower radio beep period to 5 seconds

Less annoying, still as useful as before. You're expected to read full telemetry from a PC anyway...
---
 src/ConRIG/Radio/Radio.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ConRIG/Radio/Radio.cpp b/src/ConRIG/Radio/Radio.cpp
index af3e1cf78..f6b4807cb 100644
--- a/src/ConRIG/Radio/Radio.cpp
+++ b/src/ConRIG/Radio/Radio.cpp
@@ -145,7 +145,7 @@ void Radio::loopBuzzer()
         Thread::sleep(100);
         // Doesn't matter the precision, the important thing is
         // the beep, this is because an atomic is used
-        if ((!isArmed && messagesReceived > 2) ||
+        if ((!isArmed && messagesReceived > 10) ||
             (isArmed && messagesReceived > 0))
         {
             messagesReceived = 0;
-- 
GitLab


From b36b76fc7ba7098b9c326a3a08469c6d5575fcde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 13 Mar 2025 16:49:40 +0100
Subject: [PATCH 04/13] [RIGv2][Actuators] Fix servo getter array indexes

---
 src/RIGv2/Actuators/Actuators.cpp | 14 +++++++-------
 src/RIGv2/Actuators/Actuators.h   |  2 +-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/RIGv2/Actuators/Actuators.cpp b/src/RIGv2/Actuators/Actuators.cpp
index 6f2f570b5..e511cdb17 100644
--- a/src/RIGv2/Actuators/Actuators.cpp
+++ b/src/RIGv2/Actuators/Actuators.cpp
@@ -371,19 +371,19 @@ Actuators::ServoInfo* Actuators::getServo(ServosList servo)
         case OX_DETACH_SERVO:  // OX_DET
             return &infos[2];
         case N2_FILLING_VALVE:  // N2_FIL
-            return &infos[4];
+            return &infos[3];
         case N2_RELEASE_VALVE:  // N2_REL
-            return &infos[5];
+            return &infos[4];
         case N2_DETACH_SERVO:  // N2_DET
-            return &infos[6];
+            return &infos[5];
         case NITROGEN_VALVE:  // NITR
-            return &infos[7];
+            return &infos[6];
         case OX_VENTING_VALVE:  // OX_VEN
-            return &infos[8];
+            return &infos[7];
         case N2_QUENCHING_VALVE:  // N2_QUE
-            return &infos[9];
+            return &infos[8];
         case MAIN_VALVE:  // MAIN
-            return &infos[10];
+            return &infos[9];
 
         default:
             // Oh FUCK
diff --git a/src/RIGv2/Actuators/Actuators.h b/src/RIGv2/Actuators/Actuators.h
index 0289b1a78..2877fa68e 100644
--- a/src/RIGv2/Actuators/Actuators.h
+++ b/src/RIGv2/Actuators/Actuators.h
@@ -132,7 +132,7 @@ private:
     std::atomic<bool> started{false};
 
     miosix::FastMutex infosMutex;
-    ServoInfo infos[10];
+    std::array<ServoInfo, 10> infos;
     ServoInfo n2_3wayValveInfo;
 
     long long chamberCloseTs =
-- 
GitLab


From 8140c7e16fd129791889c6503e6d395cdfdc73ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 13 Mar 2025 17:11:13 +0100
Subject: [PATCH 05/13] [RIGv2] Properly implement the N2 3-way valve

The N2 3-way valve requires special handling as it's not included in the servos list,
because of it not requiring to be atomic.
---
 src/RIGv2/Actuators/Actuators.cpp | 43 +++++++++++++++++++------------
 src/RIGv2/Actuators/Actuators.h   |  1 +
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/src/RIGv2/Actuators/Actuators.cpp b/src/RIGv2/Actuators/Actuators.cpp
index e511cdb17..6138b6901 100644
--- a/src/RIGv2/Actuators/Actuators.cpp
+++ b/src/RIGv2/Actuators/Actuators.cpp
@@ -116,14 +116,11 @@ bool Actuators::ServoInfo::setOpeningTime(uint32_t time)
 }
 
 Actuators::Actuators()
-    : infos{
-          MAKE_SERVO(OX_FIL),        MAKE_SERVO(OX_REL),
-          MAKE_DETACH_SERVO(OX_DET),
-          MAKE_SERVO(N2_FIL),        MAKE_SERVO(N2_REL),
-          MAKE_DETACH_SERVO(N2_DET), MAKE_SERVO(NITR),
-          MAKE_SERVO(OX_VEN),        MAKE_SERVO(N2_QUE),
-          MAKE_SERVO(MAIN),
-      }, n2_3wayValveInfo(MAKE_SIMPLE_SERVO(N2_3W))
+    : infos{MAKE_SERVO(OX_FIL), MAKE_SERVO(OX_REL), MAKE_DETACH_SERVO(OX_DET),
+            MAKE_SERVO(N2_FIL), MAKE_SERVO(N2_REL), MAKE_DETACH_SERVO(N2_DET),
+            MAKE_SERVO(NITR),   MAKE_SERVO(OX_VEN), MAKE_SERVO(N2_QUE),
+            MAKE_SERVO(MAIN)},
+      n2_3wayValveInfo(MAKE_SIMPLE_SERVO(N2_3W))
 {
     for (auto& servo : infos)
         servo.unsafeSetServoPosition(0.0f);
@@ -142,6 +139,8 @@ bool Actuators::start()
     for (ServoInfo& info : infos)
         info.servo->enable();
 
+    n2_3wayValveInfo.servo->enable();
+
     uint8_t result =
         scheduler.addTask([this]() { updatePositionsTask(); },
                           Config::Servos::SERVO_TIMINGS_CHECK_PERIOD);
@@ -164,6 +163,19 @@ void Actuators::igniterOff() { relays::ignition::high(); }
 
 bool Actuators::wiggleServo(ServosList servo)
 {
+    // Special handling for the 3-way valve
+    if (servo == N2_3WAY_VALVE)
+    {
+        // Toggle the valve to the current opposite state
+        auto state = get3wayValveState();
+
+        set3wayValveState(!state);
+        Thread::sleep(1000);
+        set3wayValveState(state);
+
+        return true;
+    }
+
     // Wiggle means open the servo for 1s
     return openServoWithTime(servo, 1000);
 }
@@ -288,16 +300,9 @@ bool Actuators::isCanServoOpen(ServosList servo)
         return false;
 }
 
-void Actuators::set3wayValveState(bool state)
-{
-    auto position = state ? 1.0f : 0.0f;
-    n2_3wayValveInfo.unsafeSetServoPosition(position);
-}
+void Actuators::set3wayValveState(bool state) { n2_3wayValveState = state; }
 
-bool Actuators::get3wayValveState()
-{
-    return n2_3wayValveInfo.getServoPosition() == 1.0f;
-}
+bool Actuators::get3wayValveState() { return n2_3wayValveState; }
 
 void Actuators::openChamberWithTime(uint32_t time)
 {
@@ -472,4 +477,8 @@ void Actuators::updatePositionsTask()
 
         unsafeCloseChamber();
     }
+
+    // Handle the 3-way valve
+    auto position = n2_3wayValveState ? 1.0f : 0.0f;
+    n2_3wayValveInfo.unsafeSetServoPosition(position);
 }
diff --git a/src/RIGv2/Actuators/Actuators.h b/src/RIGv2/Actuators/Actuators.h
index 2877fa68e..b6cb422d7 100644
--- a/src/RIGv2/Actuators/Actuators.h
+++ b/src/RIGv2/Actuators/Actuators.h
@@ -134,6 +134,7 @@ private:
     miosix::FastMutex infosMutex;
     std::array<ServoInfo, 10> infos;
     ServoInfo n2_3wayValveInfo;
+    std::atomic<bool> n2_3wayValveState{false};
 
     long long chamberCloseTs =
         0;  ///< Timestamp to close the chamber (0 if closed)
-- 
GitLab


From cb57951b573fa8eea9154ee7fc4ec4fe328440c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Wed, 19 Mar 2025 00:42:35 +0100
Subject: [PATCH 06/13] [ConRIG][ConRIGv2] Update button handling code to avoid
 spurious disarming

---
 src/ConRIG/Buttons/Buttons.cpp   | 155 +++++---------------
 src/ConRIG/Buttons/Buttons.h     |   9 +-
 src/ConRIG/Radio/Radio.cpp       |  28 ++--
 src/ConRIG/Radio/Radio.h         |  10 +-
 src/ConRIGv2/Buttons/Buttons.cpp | 233 ++++++-------------------------
 src/ConRIGv2/Buttons/Buttons.h   |   9 +-
 src/ConRIGv2/Radio/Radio.cpp     |  30 ++--
 src/ConRIGv2/Radio/Radio.h       |   8 +-
 8 files changed, 127 insertions(+), 355 deletions(-)

diff --git a/src/ConRIG/Buttons/Buttons.cpp b/src/ConRIG/Buttons/Buttons.cpp
index 8390a9494..c4b5a98d1 100644
--- a/src/ConRIG/Buttons/Buttons.cpp
+++ b/src/ConRIG/Buttons/Buttons.cpp
@@ -32,11 +32,10 @@ using namespace miosix;
 using namespace Boardcore;
 using namespace ConRIG;
 
-Buttons::Buttons() : state() {}
-
 bool Buttons::start()
 {
-    TaskScheduler& scheduler = getModule<BoardScheduler>()->getRadioScheduler();
+    TaskScheduler& scheduler =
+        getModule<BoardScheduler>()->getButtonsScheduler();
 
     return scheduler.addTask([this]() { periodicStatusCheck(); },
                              Config::Buttons::BUTTON_SAMPLE_PERIOD) != 0;
@@ -44,131 +43,43 @@ bool Buttons::start()
 
 mavlink_conrig_state_tc_t Buttons::getState() { return state; }
 
-void Buttons::resetState()
-{
-    // Preserve the arm switch state
-    auto armSwitch   = state.arm_switch;
-    state            = {};
-    state.arm_switch = armSwitch;
-}
-
 void Buttons::periodicStatusCheck()
 {
+#define CHECK_BUTTON(cond, btn)                           \
+    if (cond)                                             \
+    {                                                     \
+        if (guard.btn > Config::Buttons::GUARD_THRESHOLD) \
+        {                                                 \
+            guard.btn = 0;                                \
+            state.btn = true;                             \
+            LOG_DEBUG(logger, #btn " button pressed");    \
+        }                                                 \
+        else                                              \
+        {                                                 \
+            guard.btn++;                                  \
+        }                                                 \
+    }                                                     \
+    else                                                  \
+    {                                                     \
+        guard.btn = 0;                                    \
+        state.btn = false;                                \
+    }
+
     state.arm_switch = btns::arm::value();
 
-    if (!btns::ignition::value() && state.arm_switch)
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard              = 0;
-            state.ignition_btn = true;
-            LOG_DEBUG(logger, "Ignition button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2o_filling::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_filling_btn = true;
-            LOG_DEBUG(logger, "ox filling button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2o_release::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_release_btn = true;
-            LOG_DEBUG(logger, "ox release button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_release::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.n2_release_btn = true;
-            LOG_DEBUG(logger, "n2 release button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2o_venting::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_venting_btn = true;
-            LOG_DEBUG(logger, "ox venting button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_detach::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard               = 0;
-            state.n2_detach_btn = true;
-            LOG_DEBUG(logger, "n2 detach button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_filling::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.n2_filling_btn = true;
-            LOG_DEBUG(logger, "n2 filling button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::nitrogen::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard              = 0;
-            state.nitrogen_btn = true;
-            LOG_DEBUG(logger, "nitrogen button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else
-    {
-        // Reset all the states and guard
-        guard = 0;
-        resetState();
-    }
+    CHECK_BUTTON(!btns::ignition::value() && state.arm_switch, ignition_btn);
+    CHECK_BUTTON(btns::n2o_filling::value(), ox_filling_btn);
+    CHECK_BUTTON(btns::n2o_release::value(), ox_release_btn);
+    CHECK_BUTTON(btns::n2_release::value(), n2_release_btn);
+    CHECK_BUTTON(btns::n2o_venting::value(), ox_venting_btn);
+    CHECK_BUTTON(btns::n2_detach::value(), n2_detach_btn);
+    CHECK_BUTTON(btns::n2_filling::value(), n2_filling_btn);
+    CHECK_BUTTON(btns::nitrogen::value(), nitrogen_btn);
+
+#undef CHECK_BUTTON
 
     // Set the internal button state in Radio module
-    getModule<Radio>()->setButtonsState(state);
+    getModule<Radio>()->updateButtonState(state);
 }
 
 void Buttons::enableIgnition() { ui::armedLed::high(); }
diff --git a/src/ConRIG/Buttons/Buttons.h b/src/ConRIG/Buttons/Buttons.h
index ecd160f2f..2d6fff4ae 100644
--- a/src/ConRIG/Buttons/Buttons.h
+++ b/src/ConRIG/Buttons/Buttons.h
@@ -36,8 +36,6 @@ class Radio;
 class Buttons : public Boardcore::InjectableWithDeps<BoardScheduler, Radio>
 {
 public:
-    Buttons();
-
     [[nodiscard]] bool start();
 
     mavlink_conrig_state_tc_t getState();
@@ -46,14 +44,11 @@ public:
     void disableIgnition();
 
 private:
-    void resetState();
-
     void periodicStatusCheck();
 
-    mavlink_conrig_state_tc_t state;
-
+    mavlink_conrig_state_tc_t state{};
     // Counter guard to avoid spurious triggers
-    uint8_t guard = 0;
+    mavlink_conrig_state_tc_t guard{};
 
     Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("buttons");
 };
diff --git a/src/ConRIG/Radio/Radio.cpp b/src/ConRIG/Radio/Radio.cpp
index f6b4807cb..cb88b002b 100644
--- a/src/ConRIG/Radio/Radio.cpp
+++ b/src/ConRIG/Radio/Radio.cpp
@@ -80,9 +80,8 @@ void Radio::handleMessage(const mavlink_message_t& msg)
             // we assume this ack is about the last sent message
             if (id == MAVLINK_MSG_ID_CONRIG_STATE_TC)
             {
-                Lock<FastMutex> lock{buttonsMutex};
                 // Reset the internal button state
-                buttonState = {};
+                resetButtonState();
             }
 
             break;
@@ -156,11 +155,11 @@ void Radio::loopBuzzer()
     }
 }
 
-void Radio::setButtonsState(mavlink_conrig_state_tc_t state)
+void Radio::updateButtonState(const mavlink_conrig_state_tc_t& state)
 {
     Lock<FastMutex> lock{buttonsMutex};
-    // The OR operator is introduced to make sure that the receiver
-    // understood the command
+    // Merge the new state with the old one, an extra-dumb way to ensure
+    // that we don't lose any button pressess
     buttonState.ox_filling_btn |= state.ox_filling_btn;
     buttonState.ox_release_btn |= state.ox_release_btn;
     buttonState.n2_filling_btn |= state.n2_filling_btn;
@@ -170,11 +169,24 @@ void Radio::setButtonsState(mavlink_conrig_state_tc_t state)
     buttonState.nitrogen_btn |= state.nitrogen_btn;
     buttonState.ox_detach_btn |= state.ox_detach_btn;
     buttonState.n2_quenching_btn |= state.n2_quenching_btn;
-    buttonState.n2_3way_btn |= state.n2_3way_btn;
     buttonState.tars3_btn |= state.tars3_btn;
     buttonState.tars3m_btn |= state.tars3m_btn;
     buttonState.ignition_btn |= state.ignition_btn;
-    buttonState.arm_switch |= state.arm_switch;
+
+    // Don't merge lever states
+    buttonState.n2_3way_btn = state.n2_3way_btn;
+    buttonState.arm_switch  = state.arm_switch;
+}
+
+void Radio::resetButtonState()
+{
+    Lock<FastMutex> lock{buttonsMutex};
+    // Save and restore lever states
+    auto n2_3way_btn        = buttonState.n2_3way_btn;
+    auto arm_switch         = buttonState.arm_switch;
+    buttonState             = {};
+    buttonState.n2_3way_btn = n2_3way_btn;
+    buttonState.arm_switch  = arm_switch;
 }
 
 bool Radio::start()
@@ -229,5 +241,3 @@ bool Radio::start()
 }
 
 MavlinkStatus Radio::getMavlinkStatus() { return mavDriver->getStatus(); }
-
-Radio::Radio() : buttonState() {}
diff --git a/src/ConRIG/Radio/Radio.h b/src/ConRIG/Radio/Radio.h
index f9d5edb29..949df5f99 100644
--- a/src/ConRIG/Radio/Radio.h
+++ b/src/ConRIG/Radio/Radio.h
@@ -49,13 +49,11 @@ class Radio : public Boardcore::InjectableWithDeps<Buses, BoardScheduler,
                                                    Buttons, Serial>
 {
 public:
-    Radio();
-
     [[nodiscard]] bool start();
 
     Boardcore::MavlinkStatus getMavlinkStatus();
 
-    void setButtonsState(mavlink_conrig_state_tc_t state);
+    void updateButtonState(const mavlink_conrig_state_tc_t& state);
 
     bool enqueueMessage(const mavlink_message_t& msg);
 
@@ -64,6 +62,8 @@ private:
     void loopBuzzer();
     void handleMessage(const mavlink_message_t& msg);
 
+    void resetButtonState();
+
     std::unique_ptr<Boardcore::SX1278Lora> radio;
     std::unique_ptr<MavDriver> mavDriver;
 
@@ -72,10 +72,10 @@ private:
         messageQueue;
 
     miosix::FastMutex queueMutex;
-    miosix::FastMutex buttonsMutex;
 
     // Button internal state
-    mavlink_conrig_state_tc_t buttonState;
+    miosix::FastMutex buttonsMutex;
+    mavlink_conrig_state_tc_t buttonState{};
 
     std::thread buzzerLooper;
 
diff --git a/src/ConRIGv2/Buttons/Buttons.cpp b/src/ConRIGv2/Buttons/Buttons.cpp
index e7056ab79..f30478643 100644
--- a/src/ConRIGv2/Buttons/Buttons.cpp
+++ b/src/ConRIGv2/Buttons/Buttons.cpp
@@ -1,5 +1,5 @@
 /* Copyright (c) 2025 Skyward Experimental Rocketry
- * Author: Ettore Pane
+ * Authors: Ettore Pane, Niccolò Betto
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -32,15 +32,10 @@ using namespace miosix;
 using namespace Boardcore;
 using namespace ConRIGv2;
 
-Buttons::Buttons()
-{
-    resetState();
-    state.arm_switch = false;
-}
-
 bool Buttons::start()
 {
-    TaskScheduler& scheduler = getModule<BoardScheduler>()->getRadioScheduler();
+    TaskScheduler& scheduler =
+        getModule<BoardScheduler>()->getButtonsScheduler();
 
     return scheduler.addTask([this]() { periodicStatusCheck(); },
                              Config::Buttons::BUTTON_SAMPLE_PERIOD) != 0;
@@ -48,196 +43,48 @@ bool Buttons::start()
 
 mavlink_conrig_state_tc_t Buttons::getState() { return state; }
 
-void Buttons::resetState()
-{
-    // Preserve the arm switch state
-    auto armSwitch   = state.arm_switch;
-    state            = {};
-    state.arm_switch = armSwitch;
-}
-
 void Buttons::periodicStatusCheck()
 {
-    state.arm_switch = btns::arm::value();
-
-    if (!btns::ignition::value() && state.arm_switch)
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard              = 0;
-            state.ignition_btn = true;
-            LOG_DEBUG(logger, "Ignition button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::ox_filling::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_filling_btn = true;
-            LOG_DEBUG(logger, "Ox filling button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::ox_release::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_release_btn = true;
-            LOG_DEBUG(logger, "Ox release button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::ox_detach::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard               = 0;
-            state.ox_detach_btn = true;
-            LOG_DEBUG(logger, "Ox detach button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_3way::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard               = 0;
-            state.ox_detach_btn = true;
-            LOG_DEBUG(logger, "n2 3way button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_filling::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.n2_filling_btn = true;
-            LOG_DEBUG(logger, "N2 filling button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_release::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.n2_release_btn = true;
-            LOG_DEBUG(logger, "N2 release button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_detach::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard               = 0;
-            state.n2_detach_btn = true;
-            LOG_DEBUG(logger, "N2 detach button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::nitrogen::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard              = 0;
-            state.nitrogen_btn = true;
-            LOG_DEBUG(logger, "Nitrogen button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::ox_venting::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                = 0;
-            state.ox_venting_btn = true;
-            LOG_DEBUG(logger, "Ox venting button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::n2_quenching::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard                  = 0;
-            state.n2_quenching_btn = true;
-            LOG_DEBUG(logger, "N2 quenching button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::tars3::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard           = 0;
-            state.tars3_btn = true;
-            LOG_DEBUG(logger, "Tars3 button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else if (btns::tars3m::value())
-    {
-        if (guard > Config::Buttons::GUARD_THRESHOLD)
-        {
-            guard            = 0;
-            state.tars3m_btn = true;
-            LOG_DEBUG(logger, "Tars3m button pressed");
-        }
-        else
-        {
-            guard++;
-        }
-    }
-    else
-    {
-        // Reset all the states and guard
-        guard = 0;
-        resetState();
+#define CHECK_BUTTON(cond, btn)                           \
+    if (cond)                                             \
+    {                                                     \
+        if (guard.btn > Config::Buttons::GUARD_THRESHOLD) \
+        {                                                 \
+            guard.btn = 0;                                \
+            state.btn = true;                             \
+            LOG_DEBUG(logger, #btn " button pressed");    \
+        }                                                 \
+        else                                              \
+        {                                                 \
+            guard.btn++;                                  \
+        }                                                 \
+    }                                                     \
+    else                                                  \
+    {                                                     \
+        guard.btn = 0;                                    \
+        state.btn = false;                                \
     }
 
+    state.arm_switch  = btns::arm::value();
+    state.n2_3way_btn = btns::n2_3way::value();
+
+    CHECK_BUTTON(!btns::ignition::value() && state.arm_switch, ignition_btn);
+    CHECK_BUTTON(btns::ox_filling::value(), ox_filling_btn);
+    CHECK_BUTTON(btns::ox_release::value(), ox_release_btn);
+    CHECK_BUTTON(btns::ox_detach::value(), ox_detach_btn);
+    CHECK_BUTTON(btns::ox_venting::value(), ox_venting_btn);
+    CHECK_BUTTON(btns::n2_filling::value(), n2_filling_btn);
+    CHECK_BUTTON(btns::n2_release::value(), n2_release_btn);
+    CHECK_BUTTON(btns::n2_detach::value(), n2_detach_btn);
+    CHECK_BUTTON(btns::n2_quenching::value(), n2_quenching_btn);
+    CHECK_BUTTON(btns::nitrogen::value(), nitrogen_btn);
+    CHECK_BUTTON(btns::tars3::value(), tars3_btn);
+    CHECK_BUTTON(btns::tars3m::value(), tars3m_btn);
+
+#undef CHECK_BUTTON
+
     // Set the internal button state in Radio module
-    getModule<Radio>()->setButtonsState(state);
+    getModule<Radio>()->updateButtonState(state);
 }
 
 void Buttons::enableIgnition() { ui::armedLed::high(); }
diff --git a/src/ConRIGv2/Buttons/Buttons.h b/src/ConRIGv2/Buttons/Buttons.h
index 5d2c26d0e..2c4d54408 100644
--- a/src/ConRIGv2/Buttons/Buttons.h
+++ b/src/ConRIGv2/Buttons/Buttons.h
@@ -36,8 +36,6 @@ class Radio;
 class Buttons : public Boardcore::InjectableWithDeps<BoardScheduler, Radio>
 {
 public:
-    Buttons();
-
     [[nodiscard]] bool start();
 
     mavlink_conrig_state_tc_t getState();
@@ -46,14 +44,11 @@ public:
     void disableIgnition();
 
 private:
-    void resetState();
-
     void periodicStatusCheck();
 
-    mavlink_conrig_state_tc_t state;
-
+    mavlink_conrig_state_tc_t state{};
     // Counter guard to avoid spurious triggers
-    uint8_t guard = 0;
+    mavlink_conrig_state_tc_t guard{};
 
     Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("buttons");
 };
diff --git a/src/ConRIGv2/Radio/Radio.cpp b/src/ConRIGv2/Radio/Radio.cpp
index 8e7ebb843..328df566a 100644
--- a/src/ConRIGv2/Radio/Radio.cpp
+++ b/src/ConRIGv2/Radio/Radio.cpp
@@ -1,5 +1,5 @@
 /* Copyright (c) 2025 Skyward Experimental Rocketry
- * Author: Ettore Pane
+ * Authors: Ettore Pane, Niccolò Betto
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -80,9 +80,8 @@ void Radio::handleMessage(const mavlink_message_t& msg)
             // we assume this ack is about the last sent message
             if (id == MAVLINK_MSG_ID_CONRIG_STATE_TC)
             {
-                Lock<FastMutex> lock{buttonsMutex};
                 // Reset the internal button state
-                buttonState = {};
+                resetButtonState();
             }
 
             break;
@@ -164,11 +163,11 @@ void Radio::buzzerTask()
     }
 }
 
-void Radio::setButtonsState(const mavlink_conrig_state_tc_t& state)
+void Radio::updateButtonState(const mavlink_conrig_state_tc_t& state)
 {
     Lock<FastMutex> lock{buttonsMutex};
-    // The OR operator is introduced to make sure that the receiver
-    // understood the command
+    // Merge the new state with the old one, an extra-dumb way to ensure
+    // that we don't lose any button pressess
     buttonState.ox_filling_btn |= state.ox_filling_btn;
     buttonState.ox_release_btn |= state.ox_release_btn;
     buttonState.n2_filling_btn |= state.n2_filling_btn;
@@ -178,11 +177,24 @@ void Radio::setButtonsState(const mavlink_conrig_state_tc_t& state)
     buttonState.nitrogen_btn |= state.nitrogen_btn;
     buttonState.ox_detach_btn |= state.ox_detach_btn;
     buttonState.n2_quenching_btn |= state.n2_quenching_btn;
-    buttonState.n2_3way_btn |= state.n2_3way_btn;
     buttonState.tars3_btn |= state.tars3_btn;
     buttonState.tars3m_btn |= state.tars3m_btn;
     buttonState.ignition_btn |= state.ignition_btn;
-    buttonState.arm_switch |= state.arm_switch;
+
+    // Don't merge lever states
+    buttonState.n2_3way_btn = state.n2_3way_btn;
+    buttonState.arm_switch  = state.arm_switch;
+}
+
+void Radio::resetButtonState()
+{
+    Lock<FastMutex> lock{buttonsMutex};
+    // Save and restore lever states
+    auto n2_3way_btn        = buttonState.n2_3way_btn;
+    auto arm_switch         = buttonState.arm_switch;
+    buttonState             = {};
+    buttonState.n2_3way_btn = n2_3way_btn;
+    buttonState.arm_switch  = arm_switch;
 }
 
 bool Radio::start()
@@ -239,7 +251,7 @@ bool Radio::start()
 
 MavlinkStatus Radio::getMavlinkStatus() { return mavDriver->getStatus(); }
 
-Radio::Radio() : buzzer(MIOSIX_BUZZER_TIM, 523), buttonState()
+Radio::Radio() : buzzer(MIOSIX_BUZZER_TIM, 523)
 {
     buzzer.setDutyCycle(TimerUtils::Channel::MIOSIX_BUZZER_CHANNEL, 0.5);
 }
diff --git a/src/ConRIGv2/Radio/Radio.h b/src/ConRIGv2/Radio/Radio.h
index 399eb42fb..9d8c8bb47 100644
--- a/src/ConRIGv2/Radio/Radio.h
+++ b/src/ConRIGv2/Radio/Radio.h
@@ -56,7 +56,7 @@ public:
 
     Boardcore::MavlinkStatus getMavlinkStatus();
 
-    void setButtonsState(const mavlink_conrig_state_tc_t& state);
+    void updateButtonState(const mavlink_conrig_state_tc_t& state);
 
     bool enqueueMessage(const mavlink_message_t& msg);
 
@@ -65,6 +65,8 @@ private:
     void buzzerTask();
     void handleMessage(const mavlink_message_t& msg);
 
+    void resetButtonState();
+
     std::unique_ptr<Boardcore::SX1278Lora> radio;
     std::unique_ptr<MavDriver> mavDriver;
 
@@ -81,10 +83,10 @@ private:
         messageQueue;
 
     miosix::FastMutex queueMutex;
-    miosix::FastMutex buttonsMutex;
 
     // Button internal state
-    mavlink_conrig_state_tc_t buttonState;
+    miosix::FastMutex buttonsMutex;
+    mavlink_conrig_state_tc_t buttonState{};
 
     std::atomic<uint8_t> messagesReceived{0};
     std::atomic<bool> isArmed{false};
-- 
GitLab


From b3d6be5d3c2ba73c33519e2e68fdc117d112520d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Wed, 19 Mar 2025 15:29:56 +0100
Subject: [PATCH 07/13] [RIGv2] Flush messages based on bitrate rather than
 message count

We have a ridicolously low bitrate :'(
---
 src/RIGv2/Configs/RadioConfig.h |  5 +-
 src/RIGv2/Radio/Radio.cpp       | 91 +++++++++++++++++++--------------
 src/RIGv2/Radio/Radio.h         |  6 +--
 3 files changed, 60 insertions(+), 42 deletions(-)

diff --git a/src/RIGv2/Configs/RadioConfig.h b/src/RIGv2/Configs/RadioConfig.h
index af1b8643e..fb8a2a6b8 100644
--- a/src/RIGv2/Configs/RadioConfig.h
+++ b/src/RIGv2/Configs/RadioConfig.h
@@ -39,8 +39,9 @@ constexpr unsigned int MAV_MAX_LENGTH     = MAVLINK_MAX_DIALECT_PAYLOAD_SIZE;
 constexpr uint16_t MAV_SLEEP_AFTER_SEND = 0;
 constexpr size_t MAV_OUT_BUFFER_MAX_AGE = 10;
 
-constexpr unsigned int CIRCULAR_BUFFER_SIZE  = 30;
-constexpr unsigned int MAX_PACKETS_PER_FLUSH = 4;
+constexpr unsigned int CIRCULAR_BUFFER_SIZE = 30;
+// Measured empirically, used to determine how many packets to send in a flush
+constexpr unsigned int BITRATE = 4000;  // [bits/s]
 
 constexpr uint8_t MAV_SYSTEM_ID    = MAV_SYSID_RIG;
 constexpr uint8_t MAV_COMPONENT_ID = 0;
diff --git a/src/RIGv2/Radio/Radio.cpp b/src/RIGv2/Radio/Radio.cpp
index 472eb5d10..794a4abc2 100644
--- a/src/RIGv2/Radio/Radio.cpp
+++ b/src/RIGv2/Radio/Radio.cpp
@@ -22,6 +22,7 @@
 
 #include "Radio.h"
 
+#include <ConRIGv2/Configs/RadioConfig.h>
 #include <common/Events.h>
 #include <common/Radio.h>
 #include <diagnostic/CpuMeter/CpuMeter.h>
@@ -98,27 +99,44 @@ bool Radio::start()
     return true;
 }
 
-void Radio::enqueuePacket(const mavlink_message_t& msg)
+void Radio::enqueueMessage(const mavlink_message_t& msg)
 {
-    queuedPackets.put(msg);
+    queuedMessages.put(msg);
 }
 
-void Radio::flushPackets()
+void Radio::flushMessages()
 {
-    // Flush all packets of the queue
-    size_t count =
-        std::min(queuedPackets.count(), Config::Radio::MAX_PACKETS_PER_FLUSH);
-    for (size_t i = 0; i < count; i++)
+    // Flush the maximum number of packets according to the bitrate
+    constexpr auto sendSlotDuration =
+        1.0f / ConRIGv2::Config::Radio::PING_GSE_PERIOD.value();  // [s]
+    constexpr auto maxFlushSize =
+        static_cast<size_t>(Config::Radio::BITRATE / 8 * sendSlotDuration);
+
+    try
     {
-        try
-        {
-            mavDriver->enqueueMsg(queuedPackets.pop());
-        }
-        catch (...)
+        size_t bytesSent = 0;
+
+        while (!queuedMessages.isEmpty())
         {
-            // This shouldn't happen, but still try to prevent it
+            auto& message      = queuedMessages.get();
+            auto messageLength = mavlink_msg_get_send_buffer_length(&message);
+            if (bytesSent + messageLength > maxFlushSize)
+                break;
+
+            bool enqueued = mavDriver->enqueueMsg(message);
+            // If we reached the maximum queue size, stop flushing
+            if (!enqueued)
+                break;
+
+            queuedMessages.pop();
+            bytesSent += messageLength;
         }
     }
+    catch (std::range_error& e)
+    {
+        // This shouldn't happen, but still try to prevent it
+        LOG_ERR(logger, "Error while flushing packets: %s", e.what());
+    }
 }
 
 void Radio::enqueueAck(const mavlink_message_t& msg)
@@ -127,7 +145,7 @@ void Radio::enqueueAck(const mavlink_message_t& msg)
     mavlink_msg_ack_tm_pack(Config::Radio::MAV_SYSTEM_ID,
                             Config::Radio::MAV_COMPONENT_ID, &ackMsg, msg.msgid,
                             msg.seq);
-    enqueuePacket(ackMsg);
+    enqueueMessage(ackMsg);
 }
 
 void Radio::enqueueNack(const mavlink_message_t& msg, uint8_t errorId)
@@ -136,7 +154,7 @@ void Radio::enqueueNack(const mavlink_message_t& msg, uint8_t errorId)
     mavlink_msg_nack_tm_pack(Config::Radio::MAV_SYSTEM_ID,
                              Config::Radio::MAV_COMPONENT_ID, &nackMsg,
                              msg.msgid, msg.seq, errorId);
-    enqueuePacket(nackMsg);
+    enqueueMessage(nackMsg);
 }
 
 void Radio::enqueueWack(const mavlink_message_t& msg, uint8_t errorId)
@@ -145,7 +163,7 @@ void Radio::enqueueWack(const mavlink_message_t& msg, uint8_t errorId)
     mavlink_msg_wack_tm_pack(Config::Radio::MAV_SYSTEM_ID,
                              Config::Radio::MAV_COMPONENT_ID, &wackMsg,
                              msg.msgid, msg.seq, errorId);
-    enqueuePacket(wackMsg);
+    enqueueMessage(wackMsg);
 }
 
 MavlinkStatus Radio::getMavStatus()
@@ -424,7 +442,7 @@ void Radio::enqueueRegistry()
                 }
             }
 
-            enqueuePacket(msg);
+            enqueueMessage(msg);
         });
 }
 
@@ -447,7 +465,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
                 mavlink_msg_sensor_state_tm_encode(
                     Config::Radio::MAV_SYSTEM_ID,
                     Config::Radio::MAV_COMPONENT_ID, &msg, &tm);
-                enqueuePacket(msg);
+                enqueueMessage(msg);
             }
 
             return true;
@@ -477,7 +495,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             mavlink_msg_sys_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                       Config::Radio::MAV_COMPONENT_ID, &msg,
                                       &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -503,7 +521,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             mavlink_msg_logger_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                          Config::Radio::MAV_COMPONENT_ID, &msg,
                                          &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -531,7 +549,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             mavlink_msg_mavlink_stats_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                                 Config::Radio::MAV_COMPONENT_ID,
                                                 &msg, &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -621,7 +639,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             mavlink_msg_gse_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                       Config::Radio::MAV_COMPONENT_ID, &msg,
                                       &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -662,7 +680,7 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             mavlink_msg_motor_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                         Config::Radio::MAV_COMPONENT_ID, &msg,
                                         &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -706,7 +724,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_adc_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                       Config::Radio::MAV_COMPONENT_ID, &msg,
                                       &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
 
             data = getModule<Sensors>()->getADC2LastSample();
 
@@ -732,7 +750,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_adc_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                       Config::Radio::MAV_COMPONENT_ID, &msg,
                                       &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
 
             return true;
         }
@@ -751,7 +769,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
                                            &msg, &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -769,7 +787,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
                                            &msg, &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -787,7 +805,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
                                            &msg, &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -805,7 +823,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
                                            &msg, &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -823,7 +841,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_temp_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                        Config::Radio::MAV_COMPONENT_ID, &msg,
                                        &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -841,7 +859,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_load_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                        Config::Radio::MAV_COMPONENT_ID, &msg,
                                        &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -859,7 +877,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_load_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                        Config::Radio::MAV_COMPONENT_ID, &msg,
                                        &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -877,7 +895,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_msg_voltage_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                           Config::Radio::MAV_COMPONENT_ID, &msg,
                                           &tm);
-            enqueuePacket(msg);
+            enqueueMessage(msg);
             return true;
         }
 
@@ -892,14 +910,13 @@ void Radio::handleConrigState(const mavlink_message_t& msg)
 {
     // Acknowledge the state
     enqueueAck(msg);
-
-    // Flush all pending packets
-    flushPackets();
-
     // Send GSE and motor telemetry
     enqueueSystemTm(MAV_GSE_ID);
     enqueueSystemTm(MAV_MOTOR_ID);
 
+    // Flush all pending packets
+    flushMessages();
+
     mavlink_conrig_state_tc_t state;
     mavlink_msg_conrig_state_tc_decode(&msg, &state);
 
diff --git a/src/RIGv2/Radio/Radio.h b/src/RIGv2/Radio/Radio.h
index 37b61efd8..935a9dcdb 100644
--- a/src/RIGv2/Radio/Radio.h
+++ b/src/RIGv2/Radio/Radio.h
@@ -63,8 +63,8 @@ private:
     void enqueueWack(const mavlink_message_t& msg, uint8_t errorId);
     void enqueueNack(const mavlink_message_t& msg, uint8_t errorId);
 
-    void enqueuePacket(const mavlink_message_t& msg);
-    void flushPackets();
+    void enqueueMessage(const mavlink_message_t& msg);
+    void flushMessages();
 
     void handleMessage(const mavlink_message_t& msg);
     void handleCommand(const mavlink_message_t& msg);
@@ -80,7 +80,7 @@ private:
 
     Boardcore::CircularBuffer<mavlink_message_t,
                               Config::Radio::CIRCULAR_BUFFER_SIZE>
-        queuedPackets;
+        queuedMessages;
 
     std::atomic<bool> started{false};
     std::unique_ptr<Boardcore::SX1278Lora> radio;
-- 
GitLab


From 2288a64e510d80a9e6dd5305b18a4da102014bdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Wed, 19 Mar 2025 22:55:13 +0100
Subject: [PATCH 08/13] [RIGv2] Repurpose OX tank top/bottom PTs to N2 and OX
 tanks

---
 scripts/logdecoder/General/logdecoder.cpp |  4 +-
 scripts/logdecoder/RIGv2/logdecoder.cpp   |  4 +-
 src/RIGv2/CanHandler/CanHandler.cpp       |  4 +-
 src/RIGv2/Configs/SensorsConfig.h         | 32 ++++----
 src/RIGv2/Radio/Radio.cpp                 | 11 +--
 src/RIGv2/Sensors/Sensors.cpp             | 98 +++++++++++------------
 src/RIGv2/Sensors/Sensors.h               | 28 +++----
 src/RIGv2/Sensors/SensorsData.h           | 12 +--
 src/RIGv2/StateMachines/TARS1/TARS1.cpp   |  2 +-
 9 files changed, 97 insertions(+), 98 deletions(-)

diff --git a/scripts/logdecoder/General/logdecoder.cpp b/scripts/logdecoder/General/logdecoder.cpp
index c2639f17f..056abac66 100644
--- a/scripts/logdecoder/General/logdecoder.cpp
+++ b/scripts/logdecoder/General/logdecoder.cpp
@@ -115,8 +115,8 @@ void registerTypes(Deserializer& ds)
     ds.registerType<RIGv2::N2Vessel1PressureData>();
     ds.registerType<RIGv2::N2Vessel2PressureData>();
     ds.registerType<RIGv2::N2FillingPressureData>();
-    ds.registerType<RIGv2::OxTankTopPressureData>();
-    ds.registerType<RIGv2::OxTankBottomPressureData>();
+    ds.registerType<RIGv2::OxTankPressureData>();
+    ds.registerType<RIGv2::N2TankPressureData>();
     ds.registerType<RIGv2::ActuatorsData>();
     ds.registerType<RIGv2::GroundModeManagerData>();
     ds.registerType<RIGv2::TarsActionData>();
diff --git a/scripts/logdecoder/RIGv2/logdecoder.cpp b/scripts/logdecoder/RIGv2/logdecoder.cpp
index 666ae2f71..66050b858 100644
--- a/scripts/logdecoder/RIGv2/logdecoder.cpp
+++ b/scripts/logdecoder/RIGv2/logdecoder.cpp
@@ -63,8 +63,8 @@ void registerTypes(Deserializer& ds)
     ds.registerType<N2Vessel1PressureData>();
     ds.registerType<N2Vessel2PressureData>();
     ds.registerType<N2FillingPressureData>();
-    ds.registerType<OxTankTopPressureData>();
-    ds.registerType<OxTankBottomPressureData>();
+    ds.registerType<OxTankPressureData>();
+    ds.registerType<N2TankPressureData>();
     ds.registerType<ActuatorsData>();
     ds.registerType<GroundModeManagerData>();
     ds.registerType<TarsActionData>();
diff --git a/src/RIGv2/CanHandler/CanHandler.cpp b/src/RIGv2/CanHandler/CanHandler.cpp
index 42494b83b..ddfefe9bd 100644
--- a/src/RIGv2/CanHandler/CanHandler.cpp
+++ b/src/RIGv2/CanHandler/CanHandler.cpp
@@ -213,7 +213,7 @@ void CanHandler::handleSensor(const Canbus::CanMessage& msg)
         {
             CanPressureData data = pressureDataFromCanMessage(msg);
             sdLogger.log(data);
-            sensors->setCanOxTankTopPressure(data);
+            sensors->setCanOxTankPressure(data);
             break;
         }
 
@@ -221,7 +221,7 @@ void CanHandler::handleSensor(const Canbus::CanMessage& msg)
         {
             CanPressureData data = pressureDataFromCanMessage(msg);
             sdLogger.log(data);
-            sensors->setCanOxTankBottomPressure(data);
+            sensors->setCanN2TankPressure(data);
             break;
         }
 
diff --git a/src/RIGv2/Configs/SensorsConfig.h b/src/RIGv2/Configs/SensorsConfig.h
index 225da353d..6a48598b8 100644
--- a/src/RIGv2/Configs/SensorsConfig.h
+++ b/src/RIGv2/Configs/SensorsConfig.h
@@ -87,8 +87,8 @@ constexpr bool ENABLED = true;
 
 using Channel = Boardcore::ADS131M08Defs::Channel;
 
-constexpr auto OX_TANK_TOP_PT_CHANNEL    = Channel::CHANNEL_0;
-constexpr auto OX_TANK_BOTTOM_PT_CHANNEL = Channel::CHANNEL_1;
+constexpr auto OX_TANK_PT_CHANNEL = Channel::CHANNEL_0;
+constexpr auto N2_TANK_PT_CHANNEL = Channel::CHANNEL_1;
 
 constexpr float CH0_SHUNT_RESISTANCE = 29.0;  // TODO: measure
 constexpr float CH1_SHUNT_RESISTANCE = 29.0;  // TODO: measure
@@ -102,25 +102,25 @@ constexpr bool ENABLED = true;
 
 namespace Trafag
 {
-constexpr float OX_VESSEL_SHUNT_RESISTANCE      = ADC_1::CH0_SHUNT_RESISTANCE;
-constexpr float OX_FILLING_SHUNT_RESISTANCE     = ADC_1::CH1_SHUNT_RESISTANCE;
-constexpr float N2_VESSEL1_SHUNT_RESISTANCE     = ADC_1::CH2_SHUNT_RESISTANCE;
-constexpr float N2_VESSEL2_SHUNT_RESISTANCE     = ADC_1::CH3_SHUNT_RESISTANCE;
-constexpr float N2_FILLING_SHUNT_RESISTANCE     = ADC_1::CH7_SHUNT_RESISTANCE;
-constexpr float OX_TANK_TOP_SHUNT_RESISTANCE    = ADC_2::CH0_SHUNT_RESISTANCE;
-constexpr float OX_TANK_BOTTOM_SHUNT_RESISTANCE = ADC_2::CH1_SHUNT_RESISTANCE;
+constexpr float OX_VESSEL_SHUNT_RESISTANCE  = ADC_1::CH0_SHUNT_RESISTANCE;
+constexpr float OX_FILLING_SHUNT_RESISTANCE = ADC_1::CH1_SHUNT_RESISTANCE;
+constexpr float N2_VESSEL1_SHUNT_RESISTANCE = ADC_1::CH2_SHUNT_RESISTANCE;
+constexpr float N2_VESSEL2_SHUNT_RESISTANCE = ADC_1::CH3_SHUNT_RESISTANCE;
+constexpr float N2_FILLING_SHUNT_RESISTANCE = ADC_1::CH7_SHUNT_RESISTANCE;
+constexpr float OX_TANK_SHUNT_RESISTANCE    = ADC_2::CH0_SHUNT_RESISTANCE;
+constexpr float N2_TANK_SHUNT_RESISTANCE    = ADC_2::CH1_SHUNT_RESISTANCE;
 
 constexpr float MIN_CURRENT = 4;
 constexpr float MAX_CURRENT = 20;
 
 // TODO: check depending on which trafags are used
-constexpr float OX_VESSEL_MAX_PRESSURE      = 100;  // bar
-constexpr float OX_FILLING_MAX_PRESSURE     = 250;  // bar
-constexpr float N2_VESSEL1_MAX_PRESSURE     = 400;  // bar
-constexpr float N2_VESSEL2_MAX_PRESSURE     = 400;  // bar
-constexpr float N2_FILLING_MAX_PRESSURE     = 400;  // bar
-constexpr float OX_TANK_TOP_MAX_PRESSURE    = 250;  // bar
-constexpr float OX_TANK_BOTTOM_MAX_PRESSURE = 100;  // bar
+constexpr float OX_VESSEL_MAX_PRESSURE  = 100;  // bar
+constexpr float OX_FILLING_MAX_PRESSURE = 250;  // bar
+constexpr float N2_VESSEL1_MAX_PRESSURE = 400;  // bar
+constexpr float N2_VESSEL2_MAX_PRESSURE = 400;  // bar
+constexpr float N2_FILLING_MAX_PRESSURE = 400;  // bar
+constexpr float OX_TANK_MAX_PRESSURE    = 250;  // bar
+constexpr float N2_TANK_MAX_PRESSURE    = 100;  // bar
 }  // namespace Trafag
 
 namespace LoadCell
diff --git a/src/RIGv2/Radio/Radio.cpp b/src/RIGv2/Radio/Radio.cpp
index 794a4abc2..5422349cb 100644
--- a/src/RIGv2/Radio/Radio.cpp
+++ b/src/RIGv2/Radio/Radio.cpp
@@ -654,9 +654,10 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             tm.timestamp = TimestampTimer::getTimestamp();
 
             // Sensors (either CAN or local)
-            tm.ox_tank_top_pressure = sensors->getOxTankTopPressure().pressure;
-            tm.ox_tank_bot_pressure =
-                sensors->getOxTankBottomPressure().pressure;
+            tm.ox_tank_top_pressure = sensors->getN2TankPressure()
+                                          .pressure;  // TODO: rename in mavlink
+            tm.ox_tank_bot_pressure = sensors->getOxTankPressure()
+                                          .pressure;  // TODO: rename in mavlink
             tm.combustion_chamber_pressure =
                 sensors->getCombustionChamberPressure().pressure;
             tm.ox_tank_temperature =
@@ -796,7 +797,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_message_t msg;
             mavlink_pressure_tm_t tm;
 
-            PressureData data = getModule<Sensors>()->getOxTankBottomPressure();
+            PressureData data = getModule<Sensors>()->getOxTankPressure();
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
@@ -814,7 +815,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_message_t msg;
             mavlink_pressure_tm_t tm;
 
-            PressureData data = getModule<Sensors>()->getOxTankTopPressure();
+            PressureData data = getModule<Sensors>()->getN2TankPressure();
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
diff --git a/src/RIGv2/Sensors/Sensors.cpp b/src/RIGv2/Sensors/Sensors.cpp
index 5eec560c6..969505aa9 100644
--- a/src/RIGv2/Sensors/Sensors.cpp
+++ b/src/RIGv2/Sensors/Sensors.cpp
@@ -55,8 +55,8 @@ bool Sensors::start()
     if (Config::Sensors::ADC_2::ENABLED)
     {
         adc2Init();
-        oxTankTopPressureInit();
-        oxTankBottomPressureInit();
+        oxTankPressureInit();
+        n2TankPressureInit();
     }
 
     if (Config::Sensors::MAX31856::ENABLED)
@@ -122,29 +122,29 @@ PressureData Sensors::getN2FillingPressure()
                              : PressureData{};
 }
 
-PressureData Sensors::getOxTankTopPressure()
+PressureData Sensors::getOxTankPressure()
 {
     if (useCanData)
     {
-        return getCanOxTankTopPressure();
+        return getCanOxTankPressure();
     }
     else
     {
-        return oxTankTopPressure ? oxTankTopPressure->getLastSample()
-                                 : PressureData{};
+        return oxTankPressure ? oxTankPressure->getLastSample()
+                              : PressureData{};
     }
 }
 
-PressureData Sensors::getOxTankBottomPressure()
+PressureData Sensors::getN2TankPressure()
 {
     if (useCanData)
     {
-        return getCanOxTankBottomPressure();
+        return getCanN2TankPressure();
     }
     else
     {
-        return oxTankBottomPressure ? oxTankBottomPressure->getLastSample()
-                                    : PressureData{};
+        return n2TankPressure ? n2TankPressure->getLastSample()
+                              : PressureData{};
     }
 }
 
@@ -217,16 +217,16 @@ VoltageData Sensors::getMotorBatteryVoltage()
         return VoltageData{};
 }
 
-PressureData Sensors::getCanOxTankTopPressure()
+PressureData Sensors::getCanN2TankPressure()
 {
     Lock<FastMutex> lock{canMutex};
-    return canOxTankBottomPressure;
+    return canN2TankPressure;
 }
 
-PressureData Sensors::getCanOxTankBottomPressure()
+PressureData Sensors::getCanOxTankPressure()
 {
     Lock<FastMutex> lock{canMutex};
-    return canOxTankTopPressure;
+    return canOxTankPressure;
 }
 
 PressureData Sensors::getCanCombustionChamberPressure()
@@ -247,16 +247,16 @@ VoltageData Sensors::getCanMotorBatteryVoltage()
     return canMotorBatteryVoltage;
 }
 
-void Sensors::setCanOxTankTopPressure(PressureData data)
+void Sensors::setCanOxTankPressure(PressureData data)
 {
     Lock<FastMutex> lock{canMutex};
-    canOxTankBottomPressure = data;
+    canN2TankPressure = data;
 }
 
-void Sensors::setCanOxTankBottomPressure(PressureData data)
+void Sensors::setCanN2TankPressure(PressureData data)
 {
     Lock<FastMutex> lock{canMutex};
-    canOxTankTopPressure = data;
+    canOxTankPressure = data;
 }
 
 void Sensors::setCanCombustionChamberPressure(PressureData data)
@@ -318,8 +318,8 @@ std::vector<SensorInfo> Sensors::getSensorInfos()
         PUSH_SENSOR_INFO(n2Vessel1Pressure, "N2Vessel1Pressure");
         PUSH_SENSOR_INFO(n2Vessel2Pressure, "N2Vessel2Pressure");
         PUSH_SENSOR_INFO(n2FillingPressure, "N2FillingPressure");
-        PUSH_SENSOR_INFO(oxTankTopPressure, "OxTankTopPressure");
-        PUSH_SENSOR_INFO(oxTankBottomPressure, "OxTankBotPressure");
+        PUSH_SENSOR_INFO(oxTankPressure, "OxTankPressure");
+        PUSH_SENSOR_INFO(n2TankPressure, "N2TankPressure");
         PUSH_SENSOR_INFO(oxVesselWeight, "OxVesselWeight");
         PUSH_SENSOR_INFO(oxTankWeight, "OxTankWeight");
 
@@ -437,14 +437,13 @@ void Sensors::adc2Init()
         channel.enabled = false;
 
     // Configure all required channels
-    config.channelsConfig[(int)Config::Sensors::ADC_2::OX_TANK_TOP_PT_CHANNEL] =
-        {.enabled = true,
-         .pga     = ADS131M08Defs::PGA::PGA_1,
-         .offset  = 0,
-         .gain    = 1.0};
+    config.channelsConfig[(int)Config::Sensors::ADC_2::OX_TANK_PT_CHANNEL] = {
+        .enabled = true,
+        .pga     = ADS131M08Defs::PGA::PGA_1,
+        .offset  = 0,
+        .gain    = 1.0};
 
-    config.channelsConfig[(
-        int)Config::Sensors::ADC_2::OX_TANK_BOTTOM_PT_CHANNEL] = {
+    config.channelsConfig[(int)Config::Sensors::ADC_2::N2_TANK_PT_CHANNEL] = {
         .enabled = true,
         .pga     = ADS131M08Defs::PGA::PGA_1,
         .offset  = 0,
@@ -569,45 +568,44 @@ void Sensors::n2FillingPressureCallback()
     sdLogger.log(N2FillingPressureData{getN2FillingPressure()});
 }
 
-void Sensors::oxTankTopPressureInit()
+void Sensors::oxTankPressureInit()
 {
-    oxTankTopPressure = std::make_unique<TrafagPressureSensor>(
+    oxTankPressure = std::make_unique<TrafagPressureSensor>(
         [this]()
         {
             auto sample = getADC2LastSample();
             return sample.getVoltage(
-                Config::Sensors::ADC_2::OX_TANK_TOP_PT_CHANNEL);
+                Config::Sensors::ADC_2::OX_TANK_PT_CHANNEL);
         },
-        Config::Sensors::Trafag::OX_TANK_TOP_SHUNT_RESISTANCE,
-        Config::Sensors::Trafag::OX_TANK_TOP_MAX_PRESSURE,
+        Config::Sensors::Trafag::OX_TANK_SHUNT_RESISTANCE,
+        Config::Sensors::Trafag::OX_TANK_MAX_PRESSURE,
         Config::Sensors::Trafag::MIN_CURRENT,
         Config::Sensors::Trafag::MAX_CURRENT);
 }
 
-void Sensors::oxTankTopPressureCallback()
+void Sensors::oxTankPressureCallback()
 {
-    sdLogger.log(OxTankTopPressureData{oxTankTopPressure->getLastSample()});
+    sdLogger.log(OxTankPressureData{oxTankPressure->getLastSample()});
 }
 
-void Sensors::oxTankBottomPressureInit()
+void Sensors::n2TankPressureInit()
 {
-    oxTankBottomPressure = std::make_unique<TrafagPressureSensor>(
+    n2TankPressure = std::make_unique<TrafagPressureSensor>(
         [this]()
         {
             auto sample = getADC2LastSample();
             return sample.getVoltage(
-                Config::Sensors::ADC_2::OX_TANK_BOTTOM_PT_CHANNEL);
+                Config::Sensors::ADC_2::N2_TANK_PT_CHANNEL);
         },
-        Config::Sensors::Trafag::OX_TANK_BOTTOM_SHUNT_RESISTANCE,
-        Config::Sensors::Trafag::OX_TANK_BOTTOM_MAX_PRESSURE,
+        Config::Sensors::Trafag::N2_TANK_SHUNT_RESISTANCE,
+        Config::Sensors::Trafag::N2_TANK_MAX_PRESSURE,
         Config::Sensors::Trafag::MIN_CURRENT,
         Config::Sensors::Trafag::MAX_CURRENT);
 }
 
-void Sensors::oxTankBottomPressureCallback()
+void Sensors::n2TankPressureCallback()
 {
-    sdLogger.log(
-        OxTankBottomPressureData{oxTankBottomPressure->getLastSample()});
+    sdLogger.log(N2TankPressureData{n2TankPressure->getLastSample()});
 }
 
 void Sensors::oxVesselWeightInit()
@@ -720,18 +718,18 @@ bool Sensors::sensorManagerInit()
         map.emplace(std::make_pair(n2FillingPressure.get(), info));
     }
 
-    if (oxTankTopPressure)
+    if (oxTankPressure)
     {
-        SensorInfo info("OxTankTopPressure", Config::Sensors::ADS131M08::PERIOD,
-                        [this]() { oxTankTopPressureCallback(); });
-        map.emplace(std::make_pair(oxTankTopPressure.get(), info));
+        SensorInfo info("OxTankPressure", Config::Sensors::ADS131M08::PERIOD,
+                        [this]() { oxTankPressureCallback(); });
+        map.emplace(std::make_pair(oxTankPressure.get(), info));
     }
 
-    if (oxTankBottomPressure)
+    if (n2TankPressure)
     {
-        SensorInfo info("OxTankBotPressure", Config::Sensors::ADS131M08::PERIOD,
-                        [this]() { oxTankBottomPressureCallback(); });
-        map.emplace(std::make_pair(oxTankBottomPressure.get(), info));
+        SensorInfo info("N2TankPressure", Config::Sensors::ADS131M08::PERIOD,
+                        [this]() { n2TankPressureCallback(); });
+        map.emplace(std::make_pair(n2TankPressure.get(), info));
     }
 
     if (oxVesselWeight)
diff --git a/src/RIGv2/Sensors/Sensors.h b/src/RIGv2/Sensors/Sensors.h
index 06a5ceb1f..e38a2de50 100644
--- a/src/RIGv2/Sensors/Sensors.h
+++ b/src/RIGv2/Sensors/Sensors.h
@@ -64,8 +64,8 @@ public:
     Boardcore::PressureData getN2Vessel1Pressure();
     Boardcore::PressureData getN2Vessel2Pressure();
     Boardcore::PressureData getN2FillingPressure();
-    Boardcore::PressureData getOxTankTopPressure();
-    Boardcore::PressureData getOxTankBottomPressure();
+    Boardcore::PressureData getOxTankPressure();
+    Boardcore::PressureData getN2TankPressure();
     Boardcore::PressureData getCombustionChamberPressure();
 
     Boardcore::TemperatureData getOxTankTemperature();
@@ -77,16 +77,16 @@ public:
     Boardcore::VoltageData getBatteryVoltage();
     Boardcore::VoltageData getMotorBatteryVoltage();
 
-    Boardcore::PressureData getCanOxTankTopPressure();
-    Boardcore::PressureData getCanOxTankBottomPressure();
+    Boardcore::PressureData getCanOxTankPressure();
+    Boardcore::PressureData getCanN2TankPressure();
     Boardcore::PressureData getCanCombustionChamberPressure();
     Boardcore::TemperatureData getCanTankTemperature();
     Boardcore::VoltageData getCanMotorBatteryVoltage();
 
     std::vector<Boardcore::SensorInfo> getSensorInfos();
 
-    void setCanOxTankTopPressure(Boardcore::PressureData data);
-    void setCanOxTankBottomPressure(Boardcore::PressureData data);
+    void setCanOxTankPressure(Boardcore::PressureData data);
+    void setCanN2TankPressure(Boardcore::PressureData data);
     void setCanCombustionChamberPressure(Boardcore::PressureData data);
     void setCanOxTankTemperature(Boardcore::TemperatureData data);
     void setCanMotorBatteryVoltage(Boardcore::VoltageData data);
@@ -108,11 +108,11 @@ private:
     void n2FillingPressureInit();
     void n2FillingPressureCallback();
 
-    void oxTankTopPressureInit();
-    void oxTankTopPressureCallback();
+    void oxTankPressureInit();
+    void oxTankPressureCallback();
 
-    void oxTankBottomPressureInit();
-    void oxTankBottomPressureCallback();
+    void n2TankPressureInit();
+    void n2TankPressureCallback();
 
     void oxVesselWeightInit();
     void oxVesselWeightCallback();
@@ -142,8 +142,8 @@ private:
     std::atomic<bool> useCanData{false};
     miosix::FastMutex canMutex;
 
-    Boardcore::PressureData canOxTankTopPressure;
-    Boardcore::PressureData canOxTankBottomPressure;
+    Boardcore::PressureData canOxTankPressure;
+    Boardcore::PressureData canN2TankPressure;
     Boardcore::PressureData canCombustionChamberPressure;
     // TODO: N2 tank pressure from CAN
     Boardcore::TemperatureData canOxTankTemperature;
@@ -155,8 +155,8 @@ private:
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2Vessel1Pressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2Vessel2Pressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2FillingPressure;
-    std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankTopPressure;
-    std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankBottomPressure;
+    std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankPressure;
+    std::unique_ptr<Boardcore::TrafagPressureSensor> n2TankPressure;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> oxVesselWeight;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> oxTankWeight;
 
diff --git a/src/RIGv2/Sensors/SensorsData.h b/src/RIGv2/Sensors/SensorsData.h
index c598c0a2a..71ae7b241 100644
--- a/src/RIGv2/Sensors/SensorsData.h
+++ b/src/RIGv2/Sensors/SensorsData.h
@@ -129,24 +129,24 @@ struct N2FillingPressureData : Boardcore::PressureData
     N2FillingPressureData() {}
 };
 
-struct OxTankTopPressureData : Boardcore::PressureData
+struct OxTankPressureData : Boardcore::PressureData
 {
-    explicit OxTankTopPressureData(const Boardcore::PressureData& data)
+    explicit OxTankPressureData(const Boardcore::PressureData& data)
         : Boardcore::PressureData(data)
     {
     }
 
-    OxTankTopPressureData() {}
+    OxTankPressureData() {}
 };
 
-struct OxTankBottomPressureData : Boardcore::PressureData
+struct N2TankPressureData : Boardcore::PressureData
 {
-    explicit OxTankBottomPressureData(const Boardcore::PressureData& data)
+    explicit N2TankPressureData(const Boardcore::PressureData& data)
         : Boardcore::PressureData(data)
     {
     }
 
-    OxTankBottomPressureData() {}
+    N2TankPressureData() {}
 };
 
 }  // namespace RIGv2
diff --git a/src/RIGv2/StateMachines/TARS1/TARS1.cpp b/src/RIGv2/StateMachines/TARS1/TARS1.cpp
index 2d1e27c00..bc092337b 100644
--- a/src/RIGv2/StateMachines/TARS1/TARS1.cpp
+++ b/src/RIGv2/StateMachines/TARS1/TARS1.cpp
@@ -257,7 +257,7 @@ void TARS1::sample()
 {
     Sensors* sensors = getModule<Sensors>();
 
-    pressureFilter.add(sensors->getOxTankBottomPressure().pressure);
+    pressureFilter.add(sensors->getOxTankPressure().pressure);
     massFilter.add(sensors->getOxTankWeight().load);
     medianSamples++;
 
-- 
GitLab


From fc692052d942a430f450b29db3273b888ac4b63a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Thu, 20 Mar 2025 12:14:56 +0100
Subject: [PATCH 09/13] [RIGv2] Update trafag sensor configuration

* Re-measured shunt resistance for new and old ADC channels
* Updated trafag ranges for the next cold flow test
---
 src/RIGv2/Configs/SensorsConfig.h | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/src/RIGv2/Configs/SensorsConfig.h b/src/RIGv2/Configs/SensorsConfig.h
index 6a48598b8..7544c895a 100644
--- a/src/RIGv2/Configs/SensorsConfig.h
+++ b/src/RIGv2/Configs/SensorsConfig.h
@@ -74,11 +74,11 @@ constexpr auto OX_VESSEL_LC_CHANNEL   = Channel::CHANNEL_5;
 constexpr auto OX_TANK_LC_CHANNEL     = Channel::CHANNEL_6;
 constexpr auto N2_FILLING_PT_CHANNEL  = Channel::CHANNEL_7;
 
-constexpr float CH0_SHUNT_RESISTANCE = 29.4048;  // TODO: check
-constexpr float CH1_SHUNT_RESISTANCE = 29.5830;  // TODO: check
-constexpr float CH2_SHUNT_RESISTANCE = 29.4973;  // TODO: check
-constexpr float CH3_SHUNT_RESISTANCE = 29.8849;  // TODO: check
-constexpr float CH7_SHUNT_RESISTANCE = 29.0;     // TODO: measure
+constexpr float CH0_SHUNT_RESISTANCE = 29.283f;
+constexpr float CH1_SHUNT_RESISTANCE = 29.233f;
+constexpr float CH2_SHUNT_RESISTANCE = 29.268f;
+constexpr float CH3_SHUNT_RESISTANCE = 29.645f;
+constexpr float CH7_SHUNT_RESISTANCE = 29.708f;
 }  // namespace ADC_1
 
 namespace ADC_2
@@ -90,8 +90,8 @@ using Channel = Boardcore::ADS131M08Defs::Channel;
 constexpr auto OX_TANK_PT_CHANNEL = Channel::CHANNEL_0;
 constexpr auto N2_TANK_PT_CHANNEL = Channel::CHANNEL_1;
 
-constexpr float CH0_SHUNT_RESISTANCE = 29.0;  // TODO: measure
-constexpr float CH1_SHUNT_RESISTANCE = 29.0;  // TODO: measure
+constexpr float CH0_SHUNT_RESISTANCE = 29.685f;
+constexpr float CH1_SHUNT_RESISTANCE = 29.625f;
 }  // namespace ADC_2
 
 namespace MAX31856
@@ -113,14 +113,13 @@ constexpr float N2_TANK_SHUNT_RESISTANCE    = ADC_2::CH1_SHUNT_RESISTANCE;
 constexpr float MIN_CURRENT = 4;
 constexpr float MAX_CURRENT = 20;
 
-// TODO: check depending on which trafags are used
 constexpr float OX_VESSEL_MAX_PRESSURE  = 100;  // bar
-constexpr float OX_FILLING_MAX_PRESSURE = 250;  // bar
-constexpr float N2_VESSEL1_MAX_PRESSURE = 400;  // bar
-constexpr float N2_VESSEL2_MAX_PRESSURE = 400;  // bar
-constexpr float N2_FILLING_MAX_PRESSURE = 400;  // bar
-constexpr float OX_TANK_MAX_PRESSURE    = 250;  // bar
-constexpr float N2_TANK_MAX_PRESSURE    = 100;  // bar
+constexpr float OX_FILLING_MAX_PRESSURE = 100;  // bar
+constexpr float N2_VESSEL1_MAX_PRESSURE = 100;  // bar
+constexpr float N2_VESSEL2_MAX_PRESSURE = 100;  // bar
+constexpr float N2_FILLING_MAX_PRESSURE = 100;  // bar
+constexpr float OX_TANK_MAX_PRESSURE    = 100;  // bar
+constexpr float N2_TANK_MAX_PRESSURE    = 250;  // bar
 }  // namespace Trafag
 
 namespace LoadCell
-- 
GitLab


From db32e307a0e39d1cb26115d536891e1693338b54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Sat, 22 Mar 2025 11:33:27 +0100
Subject: [PATCH 10/13] [RIGv2] Add ADC testing entrypoint

`rig-v-adc-test` prints ADC values for all channels to serial output, mainly used for shunt resistance testing. The voltage printed is averaged over time with a moving average.
---
 CMakeLists.txt                |   4 +
 src/RIGv2/rig-v2-adc-test.cpp | 275 ++++++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)
 create mode 100644 src/RIGv2/rig-v2-adc-test.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d44bbc9de..a1510b8c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,6 +72,10 @@ add_executable(rig-v2-entry src/RIGv2/rig-v2-entry.cpp ${RIG_V2_COMPUTER})
 target_include_directories(rig-v2-entry PRIVATE ${OBSW_INCLUDE_DIRS})
 sbs_target(rig-v2-entry stm32f767zi_rig_v2)
 
+add_executable(rig-v2-adc-test src/RIGv2/rig-v2-adc-test.cpp ${RIG_V2_COMPUTER})
+target_include_directories(rig-v2-adc-test PRIVATE ${OBSW_INCLUDE_DIRS})
+sbs_target(rig-v2-adc-test stm32f767zi_rig_v2)
+
 add_executable(con_rig-entry src/ConRIG/con_rig-entry.cpp ${CON_RIG_COMPUTER})
 target_include_directories(con_rig-entry PRIVATE ${OBSW_INCLUDE_DIRS})
 sbs_target(con_rig-entry stm32f429zi_con_rig)
diff --git a/src/RIGv2/rig-v2-adc-test.cpp b/src/RIGv2/rig-v2-adc-test.cpp
new file mode 100644
index 000000000..5dda0ffe7
--- /dev/null
+++ b/src/RIGv2/rig-v2-adc-test.cpp
@@ -0,0 +1,275 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Authors: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <RIGv2/Actuators/Actuators.h>
+#include <RIGv2/BoardScheduler.h>
+#include <RIGv2/Buses.h>
+#include <RIGv2/CanHandler/CanHandler.h>
+#include <RIGv2/Radio/Radio.h>
+#include <RIGv2/Registry/Registry.h>
+#include <RIGv2/Sensors/Sensors.h>
+#include <RIGv2/StateMachines/GroundModeManager/GroundModeManager.h>
+#include <RIGv2/StateMachines/TARS1/TARS1.h>
+#include <common/Events.h>
+#include <diagnostic/CpuMeter/CpuMeter.h>
+#include <diagnostic/StackLogger.h>
+#include <drivers/timer/TimestampTimer.h>
+#include <events/EventBroker.h>
+#include <events/EventData.h>
+#include <events/utils/EventSniffer.h>
+
+#include <chrono>
+#include <iomanip>
+#include <iostream>
+#include <thread>
+
+using namespace std::chrono;
+using namespace Boardcore;
+using namespace Common;
+using namespace RIGv2;
+using namespace miosix;
+
+int main()
+{
+    DependencyManager manager;
+
+    Buses* buses              = new Buses();
+    BoardScheduler* scheduler = new BoardScheduler();
+
+    Sensors* sensors       = new Sensors();
+    Actuators* actuators   = new Actuators();
+    Registry* registry     = new Registry();
+    CanHandler* canHandler = new CanHandler();
+    GroundModeManager* gmm = new GroundModeManager();
+    TARS1* tars1           = new TARS1();
+    Radio* radio           = new Radio();
+
+    Logger& sdLogger    = Logger::getInstance();
+    EventBroker& broker = EventBroker::getInstance();
+
+    // Setup event sniffer
+    EventSniffer sniffer(broker,
+                         [&](uint8_t event, uint8_t topic)
+                         {
+                             EventData data{TimestampTimer::getTimestamp(),
+                                            event, topic};
+                             sdLogger.log(data);
+                         });
+
+    // Insert modules
+    bool initResult = manager.insert<Buses>(buses) &&
+                      manager.insert<BoardScheduler>(scheduler) &&
+                      manager.insert<Actuators>(actuators) &&
+                      manager.insert<Sensors>(sensors) &&
+                      manager.insert<Radio>(radio) &&
+                      manager.insert<CanHandler>(canHandler) &&
+                      manager.insert<Registry>(registry) &&
+                      manager.insert<GroundModeManager>(gmm) &&
+                      manager.insert<TARS1>(tars1) && manager.inject();
+
+    if (!initResult)
+    {
+        std::cout << "Failed to inject dependencies" << std::endl;
+        return 0;
+    }
+
+    // Status led indicators
+    // led1: Sensors ok
+    // led2: Radio ok
+    // led3: CanBus ok
+    // led4: Everything ok
+
+    // Start modules
+    std::cout << "Starting EventBroker" << std::endl;
+    if (!broker.start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start EventBroker ***" << std::endl;
+    }
+
+    std::cout << "Starting Registry" << std::endl;
+    if (!registry->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start Registry ***" << std::endl;
+    }
+
+    // Perform an initial registry load
+    std::cout << "Loading backed registry" << std::endl;
+    if (registry->load() != RegistryError::OK)
+        std::cout << "* Warning: could not load a saved registry *"
+                  << std::endl;
+
+    std::cout << "Starting Actuators" << std::endl;
+    if (!actuators->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start Actuators ***" << std::endl;
+    }
+
+    std::cout << "Starting Sensors" << std::endl;
+    if (!sensors->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start Sensors ***" << std::endl;
+    }
+    else
+    {
+        led1On();
+    }
+
+    std::cout << "Starting Radio" << std::endl;
+    if (!radio->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start Radio ***" << std::endl;
+    }
+    else
+    {
+        led2On();
+    }
+
+    std::cout << "Starting CanHandler" << std::endl;
+    if (!canHandler->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start CanHandler ***" << std::endl;
+    }
+    else
+    {
+        led3On();
+    }
+
+    std::cout << "Starting GroundModeManager" << std::endl;
+    if (!gmm->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start GroundModeManager ***" << std::endl;
+    }
+
+    std::cout << "Starting TARS1" << std::endl;
+    if (!tars1->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start TARS1 ***" << std::endl;
+    }
+
+    std::cout << "Starting BoardScheduler" << std::endl;
+    if (!scheduler->start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start BoardScheduler ***" << std::endl;
+    }
+
+    // Start logging when system boots
+    std::cout << "Starting Logger" << std::endl;
+    if (!sdLogger.start())
+    {
+        initResult = false;
+        std::cout << "*** Failed to start Logger ***" << std::endl;
+    }
+    else
+    {
+        sdLogger.resetStats();
+        std::cout << "Logger Ok!\n"
+                  << "\tLog number: " << sdLogger.getStats().logNumber
+                  << std::endl;
+    }
+
+    if (initResult)
+    {
+        broker.post(FMM_INIT_OK, TOPIC_MOTOR);
+        std::cout << "All good!" << std::endl;
+        led4On();
+    }
+    else
+    {
+        broker.post(FMM_INIT_ERROR, TOPIC_MOTOR);
+        std::cout << "*** Init failure ***" << std::endl;
+    }
+
+    std::cout << "Sensor status:" << std::endl;
+    for (auto info : sensors->getSensorInfos())
+    {
+        // The period being 0 means the sensor is disabled
+        auto statusStr = info.period == 0ns   ? "Disabled"
+                         : info.isInitialized ? "Ok"
+                                              : "Error";
+
+        std::cout << "\t" << std::setw(20) << std::left << info.id << " "
+                  << statusStr << std::endl;
+    }
+
+    ADS131M08Data avg{};
+    size_t count = 0;
+
+    std::atomic<bool> reset{false};
+
+    std::thread inputHandler = std::thread(
+        [&]()
+        {
+            while (true)
+            {
+                char command{};
+                std::cin >> command;
+
+                if (command == 'r')
+                    reset = true;
+            }
+        });
+
+    while (true)
+    {
+        Thread::sleep(10);
+
+        // Choose the ADC to sample here
+        auto sample = sensors->getADC1LastSample();
+
+        if (reset == true)
+        {
+            avg   = {};
+            count = 0;
+            reset = false;
+            std::cout << "*** Resetting moving average ***\n";
+        }
+
+        // Perform moving average
+        count++;
+        for (int i = 0; i < 8; i++)
+            avg.voltage[i] += (sample.voltage[i] - avg.voltage[i]) / count;
+
+        if (count % 100 != 0)
+            continue;
+
+        std::cout << std::setw(7) << count;
+        for (int i = 0; i < 8; i++)
+        {
+            auto millivolts = avg.voltage[i] * 1000.0f;
+
+            std::cout << "| CH " << i << ": " << std::setw(10) << std::fixed
+                      << millivolts << "mV ";
+        }
+        std::cout << '\n';
+    }
+
+    return 0;
+}
-- 
GitLab


From 358f67f53bdc8eae9e5541f43be1de9c8772ec95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Sun, 23 Mar 2025 00:19:05 +0100
Subject: [PATCH 11/13] [ConRIG][ConRIGv2] Play audio feedback quicker after
 startup and disarming

---
 src/ConRIG/Configs/RadioConfig.h   |  6 ++++++
 src/ConRIG/Radio/Radio.cpp         | 17 +++++++++++++----
 src/ConRIG/Radio/Radio.h           |  3 ++-
 src/ConRIGv2/Configs/RadioConfig.h |  6 ++++++
 src/ConRIGv2/Radio/Radio.cpp       | 19 +++++++++++++------
 src/ConRIGv2/Radio/Radio.h         |  3 ++-
 6 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/src/ConRIG/Configs/RadioConfig.h b/src/ConRIG/Configs/RadioConfig.h
index 735ae3f51..af7f66cde 100644
--- a/src/ConRIG/Configs/RadioConfig.h
+++ b/src/ConRIG/Configs/RadioConfig.h
@@ -50,6 +50,12 @@ constexpr uint8_t MAV_COMPONENT_ID = 96;
 // Periodic telemetries frequency
 constexpr Hertz PING_GSE_PERIOD = 2_hz;
 
+// Audio feedback message threshold
+constexpr auto AUDIO_FEEDBACK_THRESHOLD = 10;
+// Value to reset the message counter to, to avoid long pauses without audio
+// feedback after startup or disarming
+constexpr auto AUDIO_FEEDBACK_RESET_VALUE = AUDIO_FEEDBACK_THRESHOLD * 4 / 5;
+
 }  // namespace Radio
 }  // namespace Config
 }  // namespace ConRIG
diff --git a/src/ConRIG/Radio/Radio.cpp b/src/ConRIG/Radio/Radio.cpp
index cb88b002b..f9e218372 100644
--- a/src/ConRIG/Radio/Radio.cpp
+++ b/src/ConRIG/Radio/Radio.cpp
@@ -63,10 +63,18 @@ void Radio::handleMessage(const mavlink_message_t& msg)
         case MAVLINK_MSG_ID_GSE_TM:
         {
             int armingState = mavlink_msg_gse_tm_get_arming_state(&msg);
-            messagesReceived += 1;
+            bool wasArmed   = isArmed;
+            bool isNowArmed = armingState == 1;
+            isArmed         = isNowArmed;
+
+            // Reset the message counter to a value higher than zero to avoid
+            // long pauses without audio feedback after disarming
+            if (wasArmed && !isNowArmed)
+                messagesReceived = Config::Radio::AUDIO_FEEDBACK_RESET_VALUE;
+            else
+                messagesReceived += 1;
 
-            isArmed = armingState == 1;
-            if (armingState == 1)
+            if (isNowArmed)
                 getModule<Buttons>()->enableIgnition();
             else
                 getModule<Buttons>()->disableIgnition();
@@ -144,7 +152,8 @@ void Radio::loopBuzzer()
         Thread::sleep(100);
         // Doesn't matter the precision, the important thing is
         // the beep, this is because an atomic is used
-        if ((!isArmed && messagesReceived > 10) ||
+        if ((!isArmed &&
+             messagesReceived > Config::Radio::AUDIO_FEEDBACK_THRESHOLD) ||
             (isArmed && messagesReceived > 0))
         {
             messagesReceived = 0;
diff --git a/src/ConRIG/Radio/Radio.h b/src/ConRIG/Radio/Radio.h
index 949df5f99..29197d280 100644
--- a/src/ConRIG/Radio/Radio.h
+++ b/src/ConRIG/Radio/Radio.h
@@ -79,7 +79,8 @@ private:
 
     std::thread buzzerLooper;
 
-    std::atomic<uint8_t> messagesReceived{0};
+    std::atomic<uint8_t> messagesReceived{
+        Config::Radio::AUDIO_FEEDBACK_RESET_VALUE};
     std::atomic<bool> isArmed{false};
 
     Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("radio");
diff --git a/src/ConRIGv2/Configs/RadioConfig.h b/src/ConRIGv2/Configs/RadioConfig.h
index 8f2695e67..b6065aa5e 100644
--- a/src/ConRIGv2/Configs/RadioConfig.h
+++ b/src/ConRIGv2/Configs/RadioConfig.h
@@ -50,6 +50,12 @@ constexpr uint8_t MAV_COMPONENT_ID = 96;
 // Periodic telemetries frequency
 constexpr Hertz PING_GSE_PERIOD = 2_hz;
 
+// Audio feedback message threshold
+constexpr auto AUDIO_FEEDBACK_THRESHOLD = 10;
+// Value to reset the message counter to, to avoid long pauses without audio
+// feedback after startup or disarming
+constexpr auto AUDIO_FEEDBACK_RESET_VALUE = AUDIO_FEEDBACK_THRESHOLD * 4 / 5;
+
 }  // namespace Radio
 }  // namespace Config
 }  // namespace ConRIGv2
diff --git a/src/ConRIGv2/Radio/Radio.cpp b/src/ConRIGv2/Radio/Radio.cpp
index 328df566a..3091b2a7c 100644
--- a/src/ConRIGv2/Radio/Radio.cpp
+++ b/src/ConRIGv2/Radio/Radio.cpp
@@ -63,10 +63,18 @@ void Radio::handleMessage(const mavlink_message_t& msg)
         case MAVLINK_MSG_ID_GSE_TM:
         {
             int armingState = mavlink_msg_gse_tm_get_arming_state(&msg);
-            messagesReceived += 1;
+            bool wasArmed   = isArmed;
+            bool isNowArmed = armingState == 1;
+            isArmed         = isNowArmed;
+
+            // Reset the message counter to a value higher than zero to avoid
+            // long pauses without audio feedback after disarming
+            if (wasArmed && !isNowArmed)
+                messagesReceived = Config::Radio::AUDIO_FEEDBACK_RESET_VALUE;
+            else
+                messagesReceived += 1;
 
-            isArmed = armingState == 1;
-            if (armingState == 1)
+            if (isNowArmed)
                 getModule<Buttons>()->enableIgnition();
             else
                 getModule<Buttons>()->disableIgnition();
@@ -149,9 +157,8 @@ void Radio::buzzerOff()
 
 void Radio::buzzerTask()
 {
-    constexpr int beepPeriod = 5;  // seconds
-
-    if ((!isArmed && messagesReceived > beepPeriod * 2) ||
+    if ((!isArmed &&
+         messagesReceived > Config::Radio::AUDIO_FEEDBACK_THRESHOLD) ||
         (isArmed && messagesReceived > 0))
     {
         messagesReceived = 0;
diff --git a/src/ConRIGv2/Radio/Radio.h b/src/ConRIGv2/Radio/Radio.h
index 9d8c8bb47..71120d3fb 100644
--- a/src/ConRIGv2/Radio/Radio.h
+++ b/src/ConRIGv2/Radio/Radio.h
@@ -88,7 +88,8 @@ private:
     miosix::FastMutex buttonsMutex;
     mavlink_conrig_state_tc_t buttonState{};
 
-    std::atomic<uint8_t> messagesReceived{0};
+    std::atomic<uint8_t> messagesReceived{
+        Config::Radio::AUDIO_FEEDBACK_RESET_VALUE};
     std::atomic<bool> isArmed{false};
 
     Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("radio");
-- 
GitLab


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 12/13] [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


From 52e88602acaa82af8dfc8b31b0a9a9f666594d6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Betto?= <niccolo.betto@skywarder.eu>
Date: Tue, 8 Apr 2025 00:17:19 +0200
Subject: [PATCH 13/13] [RIGv2] Cleanup OX tank pressures

Apparently there still are top and bottom pressures for the OX tank...
---
 src/RIGv2/CanHandler/CanHandler.cpp     |  4 +-
 src/RIGv2/Radio/Radio.cpp               | 23 ++++++------
 src/RIGv2/Sensors/Sensors.cpp           | 50 +++++++++++++++----------
 src/RIGv2/Sensors/Sensors.h             | 17 +++++----
 src/RIGv2/StateMachines/TARS1/TARS1.cpp |  2 +-
 5 files changed, 56 insertions(+), 40 deletions(-)

diff --git a/src/RIGv2/CanHandler/CanHandler.cpp b/src/RIGv2/CanHandler/CanHandler.cpp
index ddfefe9bd..42494b83b 100644
--- a/src/RIGv2/CanHandler/CanHandler.cpp
+++ b/src/RIGv2/CanHandler/CanHandler.cpp
@@ -213,7 +213,7 @@ void CanHandler::handleSensor(const Canbus::CanMessage& msg)
         {
             CanPressureData data = pressureDataFromCanMessage(msg);
             sdLogger.log(data);
-            sensors->setCanOxTankPressure(data);
+            sensors->setCanOxTankTopPressure(data);
             break;
         }
 
@@ -221,7 +221,7 @@ void CanHandler::handleSensor(const Canbus::CanMessage& msg)
         {
             CanPressureData data = pressureDataFromCanMessage(msg);
             sdLogger.log(data);
-            sensors->setCanN2TankPressure(data);
+            sensors->setCanOxTankBottomPressure(data);
             break;
         }
 
diff --git a/src/RIGv2/Radio/Radio.cpp b/src/RIGv2/Radio/Radio.cpp
index 944fab614..26bce81fe 100644
--- a/src/RIGv2/Radio/Radio.cpp
+++ b/src/RIGv2/Radio/Radio.cpp
@@ -654,10 +654,11 @@ bool Radio::enqueueSystemTm(uint8_t tmId)
             tm.timestamp = TimestampTimer::getTimestamp();
 
             // Sensors (either CAN or local)
-            tm.ox_tank_top_pressure = sensors->getN2TankPressure()
-                                          .pressure;  // TODO: rename in mavlink
-            tm.ox_tank_bot_pressure = sensors->getOxTankPressure()
-                                          .pressure;  // TODO: rename in mavlink
+            tm.n2_tank_pressure = sensors->getN2TankPressure().pressure;
+            tm.ox_tank_bot_pressure =
+                sensors->getOxTankBottomPressure().pressure;
+            tm.ox_tank_top_pressure =
+                sensors->getCanOxTankTopPressure().pressure;
             tm.combustion_chamber_pressure =
                 sensors->getCombustionChamberPressure().pressure;
             tm.ox_tank_temperature =
@@ -765,7 +766,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
-            strcpy(tm.sensor_name, "VesselPressure");
+            strcpy(tm.sensor_name, "OxVesselPressure");
 
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
@@ -783,7 +784,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
-            strcpy(tm.sensor_name, "FillingPressure");
+            strcpy(tm.sensor_name, "OxFillingPressure");
 
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
@@ -797,11 +798,11 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_message_t msg;
             mavlink_pressure_tm_t tm;
 
-            PressureData data = getModule<Sensors>()->getOxTankPressure();
+            PressureData data = getModule<Sensors>()->getOxTankBottomPressure();
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
-            strcpy(tm.sensor_name, "BottomTankPressure");
+            strcpy(tm.sensor_name, "OxTankBotPressure");
 
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
@@ -815,11 +816,11 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
             mavlink_message_t msg;
             mavlink_pressure_tm_t tm;
 
-            PressureData data = getModule<Sensors>()->getN2TankPressure();
+            PressureData data = getModule<Sensors>()->getCanOxTankTopPressure();
 
             tm.timestamp = data.pressureTimestamp;
             tm.pressure  = data.pressure;
-            strcpy(tm.sensor_name, "TopTankPressure");
+            strcpy(tm.sensor_name, "OxTankTopPressure");
 
             mavlink_msg_pressure_tm_encode(Config::Radio::MAV_SYSTEM_ID,
                                            Config::Radio::MAV_COMPONENT_ID,
@@ -855,7 +856,7 @@ bool Radio::enqueueSensorTm(uint8_t tmId)
 
             tm.timestamp = data.loadTimestamp;
             tm.load      = data.load;
-            strcpy(tm.sensor_name, "VesselWeight");
+            strcpy(tm.sensor_name, "OxVesselWeight");
 
             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 614a961aa..89e22b649 100644
--- a/src/RIGv2/Sensors/Sensors.cpp
+++ b/src/RIGv2/Sensors/Sensors.cpp
@@ -56,7 +56,7 @@ bool Sensors::start()
     if (Config::Sensors::ADC_2::ENABLED)
     {
         adc2Init();
-        oxTankPressureInit();
+        oxTankBottomPressureInit();
         n2TankPressureInit();
     }
 
@@ -123,16 +123,16 @@ PressureData Sensors::getN2FillingPressure()
                              : PressureData{};
 }
 
-PressureData Sensors::getOxTankPressure()
+PressureData Sensors::getOxTankBottomPressure()
 {
     if (useCanData)
     {
-        return getCanOxTankPressure();
+        return getCanOxTankBottomPressure();
     }
     else
     {
-        return oxTankPressure ? oxTankPressure->getLastSample()
-                              : PressureData{};
+        return oxTankBottomPressure ? oxTankBottomPressure->getLastSample()
+                                    : PressureData{};
     }
 }
 
@@ -223,10 +223,16 @@ PressureData Sensors::getCanN2TankPressure()
     return canN2TankPressure;
 }
 
-PressureData Sensors::getCanOxTankPressure()
+PressureData Sensors::getCanOxTankBottomPressure()
+{
+    Lock<FastMutex> lock{canMutex};
+    return canOxTankBottomPressure;
+}
+
+PressureData Sensors::getCanOxTankTopPressure()
 {
     Lock<FastMutex> lock{canMutex};
-    return canOxTankPressure;
+    return canOxTankTopPressure;
 }
 
 PressureData Sensors::getCanCombustionChamberPressure()
@@ -247,16 +253,22 @@ VoltageData Sensors::getCanMotorBatteryVoltage()
     return canMotorBatteryVoltage;
 }
 
-void Sensors::setCanOxTankPressure(PressureData data)
+void Sensors::setCanOxTankBottomPressure(PressureData data)
 {
     Lock<FastMutex> lock{canMutex};
-    canN2TankPressure = data;
+    canOxTankBottomPressure = data;
+}
+
+void Sensors::setCanOxTankTopPressure(PressureData data)
+{
+    Lock<FastMutex> lock{canMutex};
+    canOxTankTopPressure = data;
 }
 
 void Sensors::setCanN2TankPressure(PressureData data)
 {
     Lock<FastMutex> lock{canMutex};
-    canOxTankPressure = data;
+    canN2TankPressure = data;
 }
 
 void Sensors::setCanCombustionChamberPressure(PressureData data)
@@ -320,7 +332,7 @@ std::vector<SensorInfo> Sensors::getSensorInfos()
         PUSH_SENSOR_INFO(n2Vessel1Pressure, "N2Vessel1Pressure");
         PUSH_SENSOR_INFO(n2Vessel2Pressure, "N2Vessel2Pressure");
         PUSH_SENSOR_INFO(n2FillingPressure, "N2FillingPressure");
-        PUSH_SENSOR_INFO(oxTankPressure, "OxTankPressure");
+        PUSH_SENSOR_INFO(oxTankBottomPressure, "OxTankBotPressure");
         PUSH_SENSOR_INFO(n2TankPressure, "N2TankPressure");
         PUSH_SENSOR_INFO(oxVesselWeight, "OxVesselWeight");
         PUSH_SENSOR_INFO(rocketWeight, "RocketWeight");
@@ -571,9 +583,9 @@ void Sensors::n2FillingPressureCallback()
     sdLogger.log(N2FillingPressureData{getN2FillingPressure()});
 }
 
-void Sensors::oxTankPressureInit()
+void Sensors::oxTankBottomPressureInit()
 {
-    oxTankPressure = std::make_unique<TrafagPressureSensor>(
+    oxTankBottomPressure = std::make_unique<TrafagPressureSensor>(
         [this]()
         {
             auto sample = getADC2LastSample();
@@ -586,9 +598,9 @@ void Sensors::oxTankPressureInit()
         Config::Sensors::Trafag::MAX_CURRENT);
 }
 
-void Sensors::oxTankPressureCallback()
+void Sensors::oxTankBottomPressureCallback()
 {
-    sdLogger.log(OxTankPressureData{oxTankPressure->getLastSample()});
+    sdLogger.log(OxTankPressureData{oxTankBottomPressure->getLastSample()});
 }
 
 void Sensors::n2TankPressureInit()
@@ -739,11 +751,11 @@ bool Sensors::sensorManagerInit()
         map.emplace(std::make_pair(n2FillingPressure.get(), info));
     }
 
-    if (oxTankPressure)
+    if (oxTankBottomPressure)
     {
-        SensorInfo info("OxTankPressure", Config::Sensors::ADS131M08::PERIOD,
-                        [this]() { oxTankPressureCallback(); });
-        map.emplace(std::make_pair(oxTankPressure.get(), info));
+        SensorInfo info("OxTankBotPressure", Config::Sensors::ADS131M08::PERIOD,
+                        [this]() { oxTankBottomPressureCallback(); });
+        map.emplace(std::make_pair(oxTankBottomPressure.get(), info));
     }
 
     if (n2TankPressure)
diff --git a/src/RIGv2/Sensors/Sensors.h b/src/RIGv2/Sensors/Sensors.h
index f7f9bffe5..1c3a2dba8 100644
--- a/src/RIGv2/Sensors/Sensors.h
+++ b/src/RIGv2/Sensors/Sensors.h
@@ -64,7 +64,7 @@ public:
     Boardcore::PressureData getN2Vessel1Pressure();
     Boardcore::PressureData getN2Vessel2Pressure();
     Boardcore::PressureData getN2FillingPressure();
-    Boardcore::PressureData getOxTankPressure();
+    Boardcore::PressureData getOxTankBottomPressure();
     Boardcore::PressureData getN2TankPressure();
     Boardcore::PressureData getCombustionChamberPressure();
 
@@ -78,7 +78,8 @@ public:
     Boardcore::VoltageData getBatteryVoltage();
     Boardcore::VoltageData getMotorBatteryVoltage();
 
-    Boardcore::PressureData getCanOxTankPressure();
+    Boardcore::PressureData getCanOxTankBottomPressure();
+    Boardcore::PressureData getCanOxTankTopPressure();
     Boardcore::PressureData getCanN2TankPressure();
     Boardcore::PressureData getCanCombustionChamberPressure();
     Boardcore::TemperatureData getCanTankTemperature();
@@ -86,7 +87,8 @@ public:
 
     std::vector<Boardcore::SensorInfo> getSensorInfos();
 
-    void setCanOxTankPressure(Boardcore::PressureData data);
+    void setCanOxTankBottomPressure(Boardcore::PressureData data);
+    void setCanOxTankTopPressure(Boardcore::PressureData data);
     void setCanN2TankPressure(Boardcore::PressureData data);
     void setCanCombustionChamberPressure(Boardcore::PressureData data);
     void setCanOxTankTemperature(Boardcore::TemperatureData data);
@@ -109,8 +111,8 @@ private:
     void n2FillingPressureInit();
     void n2FillingPressureCallback();
 
-    void oxTankPressureInit();
-    void oxTankPressureCallback();
+    void oxTankBottomPressureInit();
+    void oxTankBottomPressureCallback();
 
     void n2TankPressureInit();
     void n2TankPressureCallback();
@@ -146,7 +148,8 @@ private:
     std::atomic<bool> useCanData{false};
     miosix::FastMutex canMutex;
 
-    Boardcore::PressureData canOxTankPressure;
+    Boardcore::PressureData canOxTankBottomPressure;
+    Boardcore::PressureData canOxTankTopPressure;
     Boardcore::PressureData canN2TankPressure;
     Boardcore::PressureData canCombustionChamberPressure;
     // TODO: N2 tank pressure from CAN
@@ -159,7 +162,7 @@ private:
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2Vessel1Pressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2Vessel2Pressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2FillingPressure;
-    std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankPressure;
+    std::unique_ptr<Boardcore::TrafagPressureSensor> oxTankBottomPressure;
     std::unique_ptr<Boardcore::TrafagPressureSensor> n2TankPressure;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> oxVesselWeight;
     std::unique_ptr<Boardcore::TwoPointAnalogLoadCell> rocketWeight;
diff --git a/src/RIGv2/StateMachines/TARS1/TARS1.cpp b/src/RIGv2/StateMachines/TARS1/TARS1.cpp
index bc092337b..2d1e27c00 100644
--- a/src/RIGv2/StateMachines/TARS1/TARS1.cpp
+++ b/src/RIGv2/StateMachines/TARS1/TARS1.cpp
@@ -257,7 +257,7 @@ void TARS1::sample()
 {
     Sensors* sensors = getModule<Sensors>();
 
-    pressureFilter.add(sensors->getOxTankPressure().pressure);
+    pressureFilter.add(sensors->getOxTankBottomPressure().pressure);
     massFilter.add(sensors->getOxTankWeight().load);
     medianSamples++;
 
-- 
GitLab