3

I am in the final stages of development of a simple embedded system. The device performs PID coefficient estimation and then instantiates a PID controller with the estimated coefficients.

The architecture of the program is cooperative multitasking. The file main.c defines a series of void task_...(void) functions and calls them one after the other upon each timer tick.

I would like to perform the operation void task_pid_tune(void) for as long as it takes. Then, I want to perform the operation pid_configure(coefficients) once. From then on, I want to perform the operation pid_run() instead of the previous two.

Currently all 4 tasks (pid_tune() is not implemented yet) run in an extremely simple way

while( wait_for_timer_tick() )
{
    task1();
    task2();
    task3();
    task4();
 }

I would prefer to keep it that way, instead of writing logic inside this function. I am writing in C99. I am fine with static and global variables, as well as public getters.

Please advise how shall I implement communication between void task_pid_tune(void) and void task_pid_run(void). Please keep in mind that the latter will be called much more often than the former, hence performance is important in that case.


Clarification.

No task is allowed to be blocking. In other words, all scheduled tasks must return before the next timer tick.

Consequently, the required execution order is:

    task1();
    task2();
    task3();
    task4();
    task_pid_tune();
    // this loops until pid tuning is ready
    // that is, pid_tune() samples some signal once per system tick
    // and at some point, it gets happy and provides estimated pid coefficients

    task1();
    task2();
    task3();
    task4();
    task_pid_configure();  // this runs only one 

    task1();
    task2();
    task3();
    task4();
    task_pid_run();
    // This loops forever.
2
  • If void task_pid_tune(void) is a blocking call, can't you just wait until it returns, then call pid_configure(coefficients), wait until it returns, and then drop into your loop? Jan 11, 2016 at 21:40
  • I don't get it. If you want them to run in order, just call them in order. If you want them to run concurrently, have them run concurrently. You can't do both at the same time [sic] Jan 11, 2016 at 21:45

1 Answer 1

2

An easy and readable way to switch between the PID tasks is to use a function pointer, like this:

void (*pid_task)() = &task_pid_tune;

int main() {
  //... startup code

  while( wait_for_timer_tick() )
  {
    task1();
    task2();
    task3();
    task4();
    pid_task();
  }
}

void task_pid_run()
{
  //... run the PID
}

void task_pid_configure()
{
  //... perform configuration

  pid_task = &task_pid_run;
}

void task_pid_tune()
{
  //... perform PID tuning

  if (tuning done)
    pid_task = &task_pid_configure;
}

Here the pid_tune and pid_configure tasks determine when a new task should replace them and which task that should be. The main execution loop just executes whichever PID task is currently assigned to the function pointer for execution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.