diff --git a/src/shared/scheduler/TaskScheduler.cpp b/src/shared/scheduler/TaskScheduler.cpp
index dbdca6f524614045290e30122cc24ff40209d901..5b41ac35ce8f8ddb57bf53bd63113eb1116e9ca1 100644
--- a/src/shared/scheduler/TaskScheduler.cpp
+++ b/src/shared/scheduler/TaskScheduler.cpp
@@ -63,14 +63,14 @@ size_t TaskScheduler::addTask(function_t function, uint32_t period,
     // Find a suitable id for the new task
     for (; id < TASKS_SIZE; id++)
     {
-        if ((*tasks)[id].valid == false)
+        if ((*tasks)[id].empty())
         {
             break;
         }
     }
 
     // Check if in the corresponding id there's already a task
-    if ((*tasks)[id].valid)
+    if ((*tasks)[id].enabled)
     {
         // Unlock the mutex for expensive operation
         Unlock<FastMutex> unlock(mutex);
@@ -94,6 +94,44 @@ size_t TaskScheduler::addTask(function_t function, uint32_t period,
     return id;
 }
 
+void TaskScheduler::enableTask(size_t id)
+{
+    if (id > TASKS_SIZE)
+    {
+        LOG_ERR(logger, "Tried to enable an out-of-range task, id = {}", id);
+        return;
+    }
+
+    Lock<FastMutex> lock(mutex);
+    Task& task = (*tasks)[id];
+
+    // Check that the task function is not empty
+    // Attempting to run an empty function will throw a bad_function_call
+    // exception
+    if (task.empty())
+    {
+        // Unlock the mutex to release the scheduler resources before logging
+        Unlock<FastMutex> unlock(mutex);
+        LOG_WARN(logger, "Tried to enable an empty task, id = {}", id);
+        return;
+    }
+
+    task.enabled = true;
+    agenda.emplace(id, getTick() + task.period * Constants::TICKS_PER_MS);
+}
+
+void TaskScheduler::disableTask(size_t id)
+{
+    if (id > TASKS_SIZE)
+    {
+        LOG_ERR(logger, "Tried to disable an out-of-range task, id = {}", id);
+        return;
+    }
+
+    Lock<FastMutex> lock(mutex);
+    (*tasks)[id].enabled = false;
+}
+
 bool TaskScheduler::start()
 {
     // This check is necessary to prevent task normalization if the scheduler is
@@ -126,7 +164,7 @@ vector<TaskStatsResult> TaskScheduler::getTaskStats()
     for (size_t id = 1; id < TASKS_SIZE; id++)
     {
         const Task& task = (*tasks)[id];
-        if (task.valid)
+        if (task.enabled)
         {
             result.push_back(fromTaskIdPairToStatsResult(task, id));
         }
@@ -189,7 +227,7 @@ void TaskScheduler::run()
             agenda.pop();
 
             // Execute the task function
-            if (nextTask.valid)
+            if (nextTask.enabled)
             {
                 {
                     Unlock<FastMutex> unlock(lock);
@@ -249,7 +287,7 @@ void TaskScheduler::enqueue(Event event, int64_t startTick)
         case Policy::ONE_SHOT:
             // If the task is one shot we won't push it to the agenda and we'll
             // remove it from the tasks map.
-            task.valid = false;
+            task.enabled = false;
             return;
         case Policy::SKIP:
             // Updated the missed events count
@@ -276,14 +314,14 @@ void TaskScheduler::enqueue(Event event, int64_t startTick)
 }
 
 TaskScheduler::Task::Task()
-    : function(nullptr), period(0), valid(false), policy(Policy::SKIP),
+    : function(nullptr), period(0), enabled(false), policy(Policy::SKIP),
       lastCall(-1), activationStats(), periodStats(), workloadStats(),
       missedEvents(0), failedEvents(0)
 {
 }
 
 TaskScheduler::Task::Task(function_t function, uint32_t period, Policy policy)
-    : function(function), period(period), valid(true), policy(policy),
+    : function(function), period(period), enabled(true), policy(policy),
       lastCall(-1), activationStats(), periodStats(), workloadStats(),
       missedEvents(0), failedEvents(0)
 {
diff --git a/src/shared/scheduler/TaskScheduler.h b/src/shared/scheduler/TaskScheduler.h
index 0130a6dee19950536a4cd86e8475d882bdae25e8..b4a27593903d4661ef5740d3a66efd955aad22c3 100644
--- a/src/shared/scheduler/TaskScheduler.h
+++ b/src/shared/scheduler/TaskScheduler.h
@@ -29,6 +29,7 @@
 #include <utils/Stats/Stats.h>
 
 #include <cstdint>
+#include <functional>
 #include <list>
 #include <map>
 #include <queue>
@@ -119,6 +120,16 @@ public:
                    Policy policy     = Policy::SKIP,
                    int64_t startTick = miosix::getTick());
 
+    /**
+     * @brief Enables the task with the given id.
+     */
+    void enableTask(size_t id);
+
+    /**
+     * @brief Disables the task with the given id, preventing it from executing.
+     */
+    void disableTask(size_t id);
+
     bool start() override;
 
     void stop() override;
@@ -136,7 +147,7 @@ private:
     {
         function_t function;
         uint32_t period;  // [ms]
-        bool valid;
+        bool enabled;     ///< Whether the task should be executed.
         Policy policy;
         int64_t lastCall;  ///< Last activation tick for statistics computation.
         Stats activationStats;  ///< Stats about activation tick error.
@@ -168,6 +179,11 @@ private:
         // copying std::function
         Task(Task&& other)            = default;
         Task& operator=(Task&& other) = default;
+
+        /**
+         * @brief Checks if this task is empty.
+         */
+        bool empty() const { return !function; }
     };
 
     struct Event