Question

I'm currently stuck on a problem, which involves a program using a task scheduler and a task using a delay.

A task is running the following code:

// Some function
delay(_speedVar);
// Some function
delay(_speedVar);
// End of task.

Where as I have another task, just polling for information from the UART, so set the value of _speedVar.

// Uart task
if(Serial.available())
{
  _speedVar = Serial.read();
}
// End of task

My problem is, that if speedVar is set to a high value, let's say 10 seconds, the task doing some function and having a delay of (_speedVar), needs to be interrupted somehow, and started over with the new _speedVar value.

There's actually no flexibility in the Task Scheduler I'm using. It only allows me to create and destroy tasks. I'm yet to find one that have more functions and that works probably, so I'm stuck with this one for now

Only idea to a solution, would be the use of an interrupt, but I'm unsure how to get this implemented correctly when using a task scheduler.

All programming is done in C++ using Arduino's Sketch tool. Programming unit is an Arduino Uno.

Was it helpful?

Solution

Assuming that the scheduler is cooperative and these fragments of code you have posted are somehow called in some "big-loop", then, most non-trivial tasks would typically be implemented as state-machines. Given:

class cElapsedTime
{
    cElapsedTime()
    {
       zero() ; 
    }

    void zero()
    {
        timestamp = millis() ;
    }

    bool time()
    {
        return millis() - m_timestamp ;
    }
} ;

enum
{
    STATE_A,
    STATE_B
}  state = STATE_A;

cElapsedTime control_task_delay ;

Then toggle between two states to execute different code blocks after each delay period. By continuously comparing the elapsed time with the current value of _speedVar, the delay can be changed at any time. If _speedVar changed from 10 seconds to 5, and elapsed time is 7 seconds, the delayed code will be executed immediatly; if the time is extended, so will the delay:

if( control_task_delay.time() >= _speedVar )
{
    switch( state )
    {
        case STATE_A :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_B ;              // Next state
        break ;

        case STATE_B :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_A ;              // Next state
        break ;
    }
}

It is not clear in your code fragment that the first // Some function is not identical to the second; perhaps // Some other function would have clarified? However if they were in fact identical then the code would be simply:

if( control_task_delay.time() >= _speedVar )
{
    // Some function

    control_task_delay.zero()      // Restart delay
}

You can see that it is the same principle you have applied to your UART polling task - using a non-blocking test. That said, there is perhaps no need for separate tasks in any case; you could have:

if( Serial.available() )
{
    _speedVar = Serial.read();
}

if( control_task_delay.time() >= _speedVar )
{
    switch( state )
    {
        case STATE_A :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_B ;              // Next state
        break ;

        case STATE_B :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_A ;              // Next state
        break ;
    }
}

It is not clear in your code fragment that the first // Some function is not identical to the second; perhaps // Some other function would have clarified? However if they were in fact identical then the code would be simply:

if( control_task_delay.time() >= _speedVar )
{
    // Some function

    control_task_delay.zero()      // Restart delay
}

if( control_task_delay.time() >= _speedVar )
{
    switch( state )
    {
        case STATE_A :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_B ;              // Next state
        break ;

        case STATE_B :
            // Some function

            control_task_delay.zero()      // Restart delay
            state = STATE_A ;              // Next state
        break ;
    }
}

It is hard to see what the "scheduler" is achieving in this scenario.

OTHER TIPS

A Cooperative task scheduler's tasks cannot include delays or blocking IO operations. Instead you need to calculate ticks to match the time you need (On arduino I guess you can use http://arduino.cc/en/Reference/millis )

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top