diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake
index 6597cfa5ed967307049e5009367794ab1b8893a9..70a1ffc46859af365c3729a00f37301f15c92be0 100644
--- a/cmake/dependencies.cmake
+++ b/cmake/dependencies.cmake
@@ -146,6 +146,7 @@ set(GROUNDSTATION_AUTOMATED
     src/boards/Groundstation/Automated/Follower/Follower.cpp
     src/boards/Groundstation/Automated/Ports/Ethernet.cpp
     src/boards/Groundstation/Automated/Hub.cpp
+    src/boards/Groundstation/Automated/Leds/Leds.cpp
 )
 
 set(ANTENNAS
diff --git a/src/boards/Groundstation/Automated/Leds/Leds.cpp b/src/boards/Groundstation/Automated/Leds/Leds.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa4ba87a588af45d7e204621f9b2b3cce0532db1
--- /dev/null
+++ b/src/boards/Groundstation/Automated/Leds/Leds.cpp
@@ -0,0 +1,87 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Federico Lolli
+ *
+ * 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 "Leds.h"
+
+#include <miosix.h>
+
+using namespace miosix;
+using namespace Boardcore;
+
+namespace Antennas
+{
+
+bool Leds::start()
+{
+    // turn off all leds
+    ledOff();
+
+    if (!ActiveObject::start())
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void Leds::run()
+{
+    while (!shouldStop())
+    {
+        // we avoid using mutex to avoid waiting for the release of it
+        // data races here are not a problem
+        if (blinking_red)
+        {
+            userLed4::high();
+            Thread::sleep(100);
+            userLed4::low();
+            Thread::sleep(100);
+        }
+        else if (yellow_blink)
+        {
+            led2On();
+            Thread::sleep(50);
+            led2Off();
+            Thread::sleep(50);
+        }
+        else if (orange_blinking)
+        {
+            led3On();
+            Thread::sleep(50);
+            led3Off();
+            Thread::sleep(50);
+        }
+    }
+}
+
+void Leds::errorLoop()
+{
+    while (true)
+    {
+        userLed4::high();
+        Thread::sleep(100);
+        userLed4::low();
+        Thread::sleep(100);
+    }
+}
+
+}  // namespace Antennas
diff --git a/src/boards/Groundstation/Automated/Leds/Leds.h b/src/boards/Groundstation/Automated/Leds/Leds.h
new file mode 100644
index 0000000000000000000000000000000000000000..105736a43b74bbeb99fff1d520ccc975b556f3d5
--- /dev/null
+++ b/src/boards/Groundstation/Automated/Leds/Leds.h
@@ -0,0 +1,126 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Federico Lolli
+ *
+ * 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 <ActiveObject.h>
+#include <miosix.h>
+
+#include <utils/ModuleManager/ModuleManager.hpp>
+
+namespace Antennas
+{
+
+/**
+ * @brief Utility to handle blinking leds with non-blocking sleep
+ * (useful for state machines states that need to blink leds without blocking)
+ */
+class Leds : public Boardcore::Module, protected Boardcore::ActiveObject
+{
+public:
+    Leds() {}
+
+    ~Leds() { ActiveObject::stop(); }
+
+    /**
+     * @brief Start the blinking LED thread
+     */
+    bool start();
+
+    /**
+     * @brief start blinking red led
+     */
+    void start_blinking_red() { blinking_red = true; }
+
+    /**
+     * @brief stop blinking red led
+     */
+    void stop_blinking_red() { blinking_red = false; }
+
+    /**
+     * @brief turn on green led
+     */
+    void turn_on_green() { led1On(); }
+
+    /**
+     * @brief start blinking yellow led
+     */
+    void start_blinking_yellow() { yellow_blink = true; }
+
+    /**
+     * @brief stop blinking yellow led
+     */
+    void stop_blinking_yellow()
+    {
+        yellow_blink = false;
+        Thread::sleep(101);  // to avoid data races with led2On/Off
+    }
+
+    /**
+     * @brief turn on yellow led
+     */
+    void turn_on_yellow() { led2On(); }
+
+    /**
+     * @brief turn off yellow led
+     */
+    void turn_off_yellow() { led2Off(); }
+
+    /**
+     * @brief start blinking orange led
+     */
+    void start_blinking_orange() { orange_blinking = true; }
+
+    /**
+     * @brief stop blinking orange led
+     */
+    void stop_blinking_orange()
+    {
+        orange_blinking = false;
+        Thread::sleep(101);  // to avoid data races with led3On/Off
+    }
+
+    /**
+     * @brief turn on orange led
+     */
+    void turn_on_orange() { led3On(); }
+
+    /**
+     * @brief turn off orange led
+     */
+    void turn_off_orange() { led3Off(); }
+
+    /**
+     * @brief Blink the red led in a loop, blocking the thread.
+     */
+    static void errorLoop();
+
+protected:
+    void run() override;
+
+private:
+    std::atomic_bool blinking_red{false};
+    std::atomic_bool yellow_blink{false};
+    std::atomic_bool orange_blinking{false};
+};
+
+}  // namespace Antennas