diff --git a/src/Parafoil/BoardScheduler.h b/src/Parafoil/BoardScheduler.h
index 2843c6cc61052baba21be2d54e5d9b68efad96d8..cd331b343cb1718e8df0ba101324af21c60e2f67 100644
--- a/src/Parafoil/BoardScheduler.h
+++ b/src/Parafoil/BoardScheduler.h
@@ -54,6 +54,7 @@ public:
 
     Boardcore::TaskScheduler& nasController() { return critical; }
     Boardcore::TaskScheduler& sensors() { return high; }
+    Boardcore::TaskScheduler& pinHandler() { return high; }
 
     static Priority::PriorityLevel flightModeManagerPriority()
     {
diff --git a/src/Parafoil/Configs/PinHandlerConfig.h b/src/Parafoil/Configs/PinHandlerConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..237fb032ee65c42906a5aea6007d2151217d986c
--- /dev/null
+++ b/src/Parafoil/Configs/PinHandlerConfig.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Davide Basso
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <utils/PinObserver/PinObserver.h>
+
+#include <chrono>
+
+namespace Parafoil
+{
+namespace Config
+{
+namespace PinHandler
+{
+
+/* linter-off */ using namespace std::chrono_literals;
+
+namespace PinObserver
+{
+constexpr auto PERIOD = 20ms;
+}
+
+namespace Expulsion
+{
+constexpr auto DETECTION_THRESHOLD   = 20;
+constexpr auto TRIGGERING_TRANSITION = Boardcore::PinTransition::FALLING_EDGE;
+}  // namespace Expulsion
+
+}  // namespace PinHandler
+}  // namespace Config
+}  // namespace Parafoil
diff --git a/src/Parafoil/PinHandler/PinData.h b/src/Parafoil/PinHandler/PinData.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a2acf0aaa7af7503b7056ae6dc7c8f23d4b6bfd
--- /dev/null
+++ b/src/Parafoil/PinHandler/PinData.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Davide Basso
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <iostream>
+
+namespace Parafoil
+{
+
+struct PinChangeData
+{
+    uint64_t timestamp    = 0;
+    uint8_t pinId         = 0;
+    bool lastState        = false;
+    uint32_t changesCount = 0;
+
+    static std::string header()
+    {
+        return "timestamp,pinId,lastState,changesCount\n";
+    }
+
+    void print(std::ostream& os) const
+    {
+        os << timestamp << "," << static_cast<int>(pinId) << ","
+           << static_cast<int>(lastState) << "," << changesCount << "\n";
+    }
+};
+
+}  // namespace Parafoil
diff --git a/src/Parafoil/PinHandler/PinHandler.cpp b/src/Parafoil/PinHandler/PinHandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7721678388882326e458eed21d95672a54874d5
--- /dev/null
+++ b/src/Parafoil/PinHandler/PinHandler.cpp
@@ -0,0 +1,107 @@
+
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Davide Basso
+ *
+ * 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 "PinHandler.h"
+
+#include <Parafoil/BoardScheduler.h>
+#include <Parafoil/Configs/PinHandlerConfig.h>
+#include <common/Events.h>
+#include <drivers/timer/TimestampTimer.h>
+#include <events/EventBroker.h>
+#include <interfaces-impl/hwmapping.h>
+
+#include "PinData.h"
+
+using namespace Boardcore;
+using namespace Common;
+namespace config = Parafoil::Config::PinHandler;
+namespace hwmap  = miosix::inputs;
+
+namespace Parafoil
+{
+
+const decltype(PinHandler::PIN_LIST) PinHandler::PIN_LIST = {
+    PinList::NOSECONE_PIN,
+};
+
+bool PinHandler::start()
+{
+    using namespace std::chrono;
+
+    auto& scheduler = getModule<BoardScheduler>()->pinHandler();
+
+    pinObserver = std::make_unique<PinObserver>(
+        scheduler, milliseconds{config::PinObserver::PERIOD}.count());
+
+    bool expulsionPinDetachResult = pinObserver->registerPinCallback(
+        hwmap::expulsion::getPin(),
+        [this](auto t) { onExpulsionPinTransition(t); },
+        config::Expulsion::DETECTION_THRESHOLD);
+
+    if (!expulsionPinDetachResult)
+    {
+        LOG_ERR(logger,
+                "Failed to register pin callback for the detach ramp pin");
+        return false;
+    }
+
+    started = true;
+    return true;
+}
+
+bool PinHandler::isStarted() { return started; }
+
+PinData PinHandler::getPinData(PinList pin)
+{
+    switch (pin)
+    {
+        case PinList::NOSECONE_PIN:
+            return pinObserver->getPinData(hwmap::expulsion::getPin());
+        default:
+            return PinData{};
+    }
+}
+
+void PinHandler::logPin(PinList pin)
+{
+    auto pinData       = getPinData(pin);
+    auto pinChangeData = PinChangeData{
+        .timestamp    = TimestampTimer::getTimestamp(),
+        .pinId        = static_cast<uint8_t>(pin),
+        .lastState    = pinData.lastState,
+        .changesCount = pinData.changesCount,
+    };
+    Logger::getInstance().log(pinChangeData);
+}
+
+void PinHandler::onExpulsionPinTransition(PinTransition transition)
+{
+    logPin(PinList::NOSECONE_PIN);
+    LOG_INFO(logger, "Expulsion Pin transition detected: {}",
+             static_cast<int>(transition));
+
+    if (transition == config::Expulsion::TRIGGERING_TRANSITION)
+        EventBroker::getInstance().post(FLIGHT_NC_DETACHED, TOPIC_FLIGHT);
+}
+
+}  // namespace Parafoil
diff --git a/src/Parafoil/PinHandler/PinHandler.h b/src/Parafoil/PinHandler/PinHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f8be18ae3571948d2fb06f1baf5a8de39f9085a
--- /dev/null
+++ b/src/Parafoil/PinHandler/PinHandler.h
@@ -0,0 +1,71 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Davide Basso
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <common/MavlinkOrion.h>
+#include <diagnostic/PrintLogger.h>
+#include <utils/DependencyManager/DependencyManager.h>
+#include <utils/PinObserver/PinObserver.h>
+
+namespace Parafoil
+{
+class BoardScheduler;
+
+enum class PinList : uint8_t
+{
+    NOSECONE_PIN = 0,
+};
+
+/**
+ * @brief This class contains the handlers for the detach pins on the payload.
+ *
+ * It uses Boardcore's PinObserver to bind these functions to the GPIO pins.
+ * The handlers post an event on the EventBroker.
+ */
+class PinHandler : public Boardcore::InjectableWithDeps<BoardScheduler>
+{
+public:
+    static const std::array<PinList, 1> PIN_LIST;
+
+    [[nodiscard]] bool start();
+
+    bool isStarted();
+
+    /**
+     * @brief Returns information about the specified pin.
+     */
+    Boardcore::PinData getPinData(PinList pin);
+
+private:
+    void logPin(PinList pin);
+
+    void onExpulsionPinTransition(Boardcore::PinTransition transition);
+
+    std::unique_ptr<Boardcore::PinObserver> pinObserver;
+
+    std::atomic<bool> started{false};
+
+    Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("PinHandler");
+};
+
+}  // namespace Parafoil
diff --git a/src/Parafoil/parafoil-entry.cpp b/src/Parafoil/parafoil-entry.cpp
index d5c9d51b4c158da9a95be27a912f1d02c8eb9420..0b5451b3f21aa99ced8bdbfd34373ff5ecf9679b 100644
--- a/src/Parafoil/parafoil-entry.cpp
+++ b/src/Parafoil/parafoil-entry.cpp
@@ -22,6 +22,7 @@
 
 #include <Parafoil/BoardScheduler.h>
 #include <Parafoil/Buses.h>
+#include <Parafoil/PinHandler/PinHandler.h>
 #include <Parafoil/Sensors/Sensors.h>
 #include <Parafoil/StateMachines/FlightModeManager/FlightModeManager.h>
 #include <common/Events.h>
@@ -78,8 +79,7 @@ using namespace Common;
 
 int main()
 {
-    std::cout << "Parafoil Entrypoint "
-              << "(" << BUILD_TYPE << ")"
+    std::cout << "Parafoil Entrypoint " << "(" << BUILD_TYPE << ")"
               << " by Skyward Experimental Rocketry" << std::endl;
 
     auto logger = Logging::getLogger("Parafoil");
@@ -101,7 +101,8 @@ int main()
     // Sensors
     auto sensors = new Sensors();
     initResult &= depman.insert(sensors);
-    // TODO: PinHandler
+    auto pinHandler = new PinHandler();
+    initResult &= depman.insert(pinHandler);
 
     // TODO: Radio
 
@@ -159,4 +160,4 @@ int main()
     }
 
     return 0;
-}
\ No newline at end of file
+}