diff --git a/libs/mavlink-skyward-lib b/libs/mavlink-skyward-lib
index 4874d08b4a6340d6a9da8da9a33f96b8f01d789b..1374b7d63113a5bcf178e7ea4ac87c1524f81609 160000
--- a/libs/mavlink-skyward-lib
+++ b/libs/mavlink-skyward-lib
@@ -1 +1 @@
-Subproject commit 4874d08b4a6340d6a9da8da9a33f96b8f01d789b
+Subproject commit 1374b7d63113a5bcf178e7ea4ac87c1524f81609
diff --git a/src/shared/utils/PinObserver/PinObserver.cpp b/src/shared/utils/PinObserver/PinObserver.cpp
index 14430cda3df132bbfdcbf58565715f3b88067834..820158a145510ad54b17a727a255ed543429f9bc 100644
--- a/src/shared/utils/PinObserver/PinObserver.cpp
+++ b/src/shared/utils/PinObserver/PinObserver.cpp
@@ -22,17 +22,19 @@
 
 #include "PinObserver.h"
 
+#include <drivers/timer/TimestampTimer.h>
+
 #include <functional>
 
 namespace Boardcore
 {
 
 bool PinObserver::registerPinCallback(miosix::GpioPin pin, PinCallback callback,
-                                      unsigned int detectionThreshold)
+                                      uint32_t detectionThreshold)
 {
     // Try to insert the callback
-    auto result =
-        callbacks.insert({pin, {callback, detectionThreshold, pin.value(), 0}});
+    auto result = callbacks.insert(
+        {pin, {callback, detectionThreshold, 0, 0, pin.value() == 1, 0}});
 
     // Check if the insertion took place
     if (result.second)
@@ -54,6 +56,13 @@ bool PinObserver::start() { return scheduler.start(); }
 
 void PinObserver::stop() { scheduler.stop(); }
 
+PinData PinObserver::getPinData(miosix::GpioPin pin) { return callbacks[pin]; }
+
+void PinObserver::resetPinChangesCount(miosix::GpioPin pin)
+{
+    callbacks[pin].changesCount = 0;
+}
+
 PinObserver::PinObserver() { scheduler.start(); }
 
 void PinObserver::periodicPinValueCheck(miosix::GpioPin pin)
@@ -62,36 +71,37 @@ void PinObserver::periodicPinValueCheck(miosix::GpioPin pin)
     if (callbacks.find(pin) == callbacks.end())
         return;
 
+    auto &pinData = callbacks[pin];
+
     // Retrieve the pin information
-    const PinCallback &callback           = std::get<0>(callbacks[pin]);
-    const unsigned int detectionThreshold = std::get<1>(callbacks[pin]);
-    bool &previousState                   = std::get<2>(callbacks[pin]);
-    unsigned int &detectedCount           = std::get<3>(callbacks[pin]);
+    uint32_t &count = pinData.periodCount;
 
     // Read the current pin status
     const bool newState = pin.value();
 
     // Are we in a transition?
-    if (previousState != newState)
+    if (pinData.lastState != newState)
     {
-        detectedCount = 0;  // Yes, reset the counter
+        count = 0;               // Yes, reset the counter
+        pinData.changesCount++;  // And register the change
     }
     else
     {
-        detectedCount++;  // No, continue to increment
+        count++;  // No, continue to increment
 
         // If the count reaches the threshold, then trigger the event
-        if (detectedCount > detectionThreshold)
+        if (count > pinData.threshold)
         {
             if (newState)
-                callback(PinTransition::RISING_EDGE);
+                pinData.callback(PinTransition::RISING_EDGE);
             else
-                callback(PinTransition::FALLING_EDGE);
+                pinData.callback(PinTransition::FALLING_EDGE);
         }
     }
 
     // Save the current pin status
-    previousState = newState;
+    pinData.lastStateTimestamp = TimestampTimer::getTimestamp();
+    pinData.lastState          = newState;
 }
 
 }  // namespace Boardcore
diff --git a/src/shared/utils/PinObserver/PinObserver.h b/src/shared/utils/PinObserver/PinObserver.h
index 07090622a702af94f2dcbc04fdd1e3fe05065f62..692d514d40f2176c3f32af747599aade0279ba00 100644
--- a/src/shared/utils/PinObserver/PinObserver.h
+++ b/src/shared/utils/PinObserver/PinObserver.h
@@ -40,6 +40,19 @@ enum class PinTransition
     RISING_EDGE    ///< The pin goes from low to high.
 };
 
+/**
+ * @brief Pin informations.
+ */
+struct PinData
+{
+    std::function<void(PinTransition)> callback;  ///< The callback function.
+    uint32_t threshold;           ///< Number of periods to trigger an event.
+    uint32_t periodCount;         ///< Number of periods the value was the same.
+    uint64_t lastStateTimestamp;  ///< Timestamp of the last measurement.
+    bool lastState;               ///< The last measured pin state.
+    uint32_t changesCount;        ///< Incremental count of the pin changes.
+};
+
 /**
  * Class used to call a callback after a pin performs a specific transition
  * (RISING or FALLING edge) and stays in the new state for a specific amount of
@@ -71,7 +84,7 @@ public:
      * @return False if another callback was already registered for the pin.
      */
     bool registerPinCallback(miosix::GpioPin pin, PinCallback callback,
-                             unsigned int detectionThreshold = 1);
+                             uint32_t detectionThreshold = 1);
 
     /**
      * @brief Unregisters the callback associated with the specified pin, if
@@ -97,6 +110,16 @@ public:
      */
     void stop();
 
+    /**
+     * @brief Returns the information for the specified pin.
+     */
+    PinData getPinData(miosix::GpioPin pin);
+
+    /**
+     * @brief Resets the changes counter for the specified pin.
+     */
+    void resetPinChangesCount(miosix::GpioPin pin);
+
 private:
     /**
      * @brief Construct a new PinObserver object.
@@ -115,19 +138,8 @@ private:
 
     TaskScheduler scheduler;
 
-    /**
-     * @brief Map of all the callbacks registered in the PinObserver.
-
-     * The type stored is a tuple containing:
-     * - The button callback function;
-     * - Detection threshold: number of periods to trigger an event
-     * - The last pin status;
-     * - Number of periods the pin values stayed the same;
-     */
-    std::map<miosix::GpioPin,
-             std::tuple<PinCallback, unsigned int, bool, unsigned int>,
-             GpioPinCompare>
-        callbacks;
+    /// Map of all the callbacks registered in the PinObserver.
+    std::map<miosix::GpioPin, PinData, GpioPinCompare> callbacks;
 };
 
 }  // namespace Boardcore