(Yet another) balancing robot

I am somewhat curious about the RTOS-like scheduler. Can you provide the relevant code so I can take a look?

Sure. It's not actually that powerful -- but it was sufficient for this robot. There's not even preemption.

Anyway, the relevant code follows. First, the Task class:

typedef void (*TaskCallback)(TaskManager &);

class Task {
private:
  long m_countdown, m_period;
  TaskCallback m_callback;

  friend class TaskManager;

  long decrementCountdownBy(long by) {
    return m_countdown -= by;
  }
 
  void inline resetCountdown(void) {
    m_countdown = m_period;
  }

  void inline run(TaskManager &tm) {
    m_callback(tm);
  }
 
public:
  Task(TaskCallback callback, long period) : 
  m_callback(callback), m_countdown(period), m_period(period) {
 
  }
};

Each task will be an instance of this class. Like so, for a blinking LED example with 1000ms interval:

void task1(TaskManager &tm)
{
    static ledStatus = false;
    digitalWrite(13, ledStatus^=1);
}

Task tasks[] = { Task(task1, 1000); };

You'll also need the scheduler itself; relevant parts of the code follows:

class TaskManager {
private:
  Task *m_tasks;
  unsigned int m_nTasks;
  unsigned long m_lastTime;
 
  void sleep(void) {
    set_sleep_mode(SLEEP_MODE_IDLE);
    sleep_enable();
    sleep_mode();
    sleep_disable();
  }
public:
  TaskManager(Task *tasks, int n_tasks) : 
  m_tasks(tasks), m_nTasks(n_tasks), m_lastTime(0L) {
 
  }

  void inline loop() {
    Task *task;
    unsigned int n_task;
    unsigned long elapsedTime = millis() - m_lastTime;
 
    for (n_task = m_nTasks; n_task > 0; n_task--) {
      task = &m_tasks[n_task];
 
      if (task->decrementCountdownBy(elapsedTime) <= 0) {
        task->run(*this);
        task->resetCountdown();
      }
    }
 
    m_lastTime = millis();
    sleep();
  }
};

So, if you call the loop() method of the task manager, all tasks will be executed roughly at the frequency you told them to execute:

TaskManger tm(tasks, 1);

void loop()
{
  tm.loop(); 
}

As there is no preemption, you should be aware that a task won't be stopped in middle-air. Also, there is no guarantee that the task execution periods will be respected. It is crude, but sufficient for most things people use Arduinos for :slight_smile: