Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Taskscheduler Ignores timing when enabled via functions, possible bug. #137

Closed
dr-mrsthemonarch opened this issue Mar 8, 2022 · 6 comments

Comments

@dr-mrsthemonarch
Copy link

With a minimal example code:

#include <array>
#include <Arduino.h>
#include <TaskScheduler.h>
std::array<std::array<float, 3> , 2> vals = {0}; //imagine this is full of sensor data
String stringRead;
int cs32 = 0;
int cs14 = 1;

void cs14Print();
void cs32Print();
void thingOff();


//Tasks
Task sensor14(500, TASK_FOREVER, &cs14Print); // print every 5ms, gives the most stable print from realtimeserial
Task sensor32(300, TASK_FOREVER, &cs32Print);
Task example(2000, 5, &thingOff); // example so i don't forget method

Scheduler runner;


void cs14Print() {
  taskPrint(cs14);
};

void cs32Print() {
  taskPrint(cs32);
};


void thingOff() {
  if (example.isLastIteration()) {
    sensor14.disable();
    runner.deleteTask(sensor14);
    Serial.println("System removed");
  }
};


void schedularOnOff(int sensorSelect) {
  if (sensorSelect < 5) {
    switch (sensorSelect) {
      case 1:
        sensor14.enable();
        break;
      case 2:
        sensor14.disable();
        //runner.deleteTask(sensor14);
        break;
      case 3:
        sensor32.enable();
        break;
      case 4:
        sensor32.disable();
        //runner.deleteTask(sensor32);
        break;
    }
  }
};
void taskPrint(int pin) {
  Serial.print(vals[pin][0]);
  Serial.print(',');
  Serial.print(vals[pin][1]);
  Serial.print(',');
  Serial.println(vals[pin][2]);
};

void setup() {
  // serial to display data
  Serial.begin(115200);
  delay(100);
  runner.init();
  runner.addTask(sensor14);
  runner.addTask(sensor32);
  delay(1000);
}

void loop() {
  runner.execute();

  if (Serial.available() > 0) {
    stringRead = Serial.readStringUntil('\n');
  }
  schedularOnOff(stringRead.toInt());
}

Within serial, using four inputs, 1, 2, 3, 4 each of the two tasks will be activated, or disabled respectively. I have not used .deleteTask() in my code because I will expect to turn different tasks on and off regularly and they can 'run in the background' until I turn them back on again.

As soon as either 1, or 3 are sent through serial, the tasks immediately print the values of the val array as fast as possible, instead of the 500ms that are programmed. Should one turn off task one with 2, then turn on task two, with 3, then send the input 2 again, the taskscheduler then sends data at a reduced frequency, but not at the correct one.

Is this a bug or my bad programming? Is it not possible to activate and deactivate tasks through functions?

@arkhipenko
Copy link
Owner

arkhipenko commented Mar 9, 2022 via email

@arkhipenko
Copy link
Owner

Also, if you want the task to start with a delay, use enableDelayed() method!

@dr-mrsthemonarch
Copy link
Author

dr-mrsthemonarch commented Mar 10, 2022

Hallo! Thank you so much for having a look so fast, yes you're right the example task isn't activated, I forgot to remove that code, it does infact have nothing to do with error. I have removed the delay(1000) and reuploaded. I am using the arduino ide 1.8.15, and the newest taskscheduler library and esp32 boards.

Using this code:

#include <array>
#include <Arduino.h>
#include <TaskScheduler.h>
std::array<std::array<float, 3> , 2> vals = {0}; //imagine this is full of sensor data
String stringRead;
int cs32 = 0;
int cs14 = 1;

void cs14Print();
void cs32Print();
void thingOff();


//Tasks
Task sensor14(500, TASK_FOREVER, &cs14Print); // print every 5ms, gives the most stable print from realtimeserial
Task sensor32(300, TASK_FOREVER, &cs32Print);

Scheduler runner;


void cs14Print() {
  taskPrint(cs14);
};

void cs32Print() {
  taskPrint(cs32);
};


void schedularOnOff(int sensorSelect) {
  if (sensorSelect < 5) {
    switch (sensorSelect) {
      case 1:
        sensor14.enable();
        break;
      case 2:
        sensor14.disable();
        //runner.deleteTask(sensor14);
        break;
      case 3:
        sensor32.enable();
        break;
      case 4:
        sensor32.disable();
        //runner.deleteTask(sensor32);
        break;
    }
  }
};
void taskPrint(int pin) {
  Serial.print(vals[pin][0]);
  Serial.print(',');
  Serial.print(vals[pin][1]);
  Serial.print(',');
  Serial.println(vals[pin][2]);
};

void setup() {
  // serial to display data
  Serial.begin(115200);
  delay(100);
  runner.init();
  runner.addTask(sensor14);
  runner.addTask(sensor32);
  sensor14.enable();
  
}

void loop() {
  runner.execute();

  if (Serial.available() > 0) {
    stringRead = Serial.readStringUntil('\n');
  }
  schedularOnOff(stringRead.toInt());
}

Where sensor14 is enabled, the scheduler does print every 500ms as expected, however if I sent a serial input to disable the task with the value "2" then send the input "1" to reenable, the scheduler is ignored and does not follow the 500 timing anymore, this then infact blocks all serial input and the entire board is blocked indefinitely from any responses.

I really appreciate looking at this! Is there any other info I can provide? I feel like the error must be some improper implementation on my side with my functions, but I don't know.

@dr-mrsthemonarch
Copy link
Author

I have also looked at the scheduling options, modifying the code:

#define _TASK_SCHEDULING_OPTIONS
#include <TaskScheduler.h>

and

void schedularOnOff(int sensorSelect) {
  if (sensorSelect < 5) {
    switch (sensorSelect) {
      case 1:
        sensor14.setSchedulingOption(TASK_SCHEDULE_NC);
        sensor14.enable();
        runner.addTask(sensor14);
        
        break;
      case 2:
        sensor14.disable();
        runner.deleteTask(sensor14);
        break;
      case 3:
        sensor32.enable();
        break;
      case 4:
        sensor32.disable();
        runner.deleteTask(sensor32);
        break;
    }
  }
};

and

void setup() {
  // serial to display data
  Serial.begin(115200);
//  delay(100);
  runner.init();
  sensor14.setSchedulingOption(TASK_SCHEDULE_NC);
  runner.addTask(sensor14);
  runner.addTask(sensor32);
  sensor14.enable();
  
}

Unfortunately does not seem to have an effect.

@arkhipenko
Copy link
Owner

arkhipenko commented Mar 10, 2022

The mistake is:

void loop() {
  runner.execute();

  if (Serial.available() > 0) {
    stringRead = Serial.readStringUntil('\n');
  }

// since stringRead is never cleared you are constantly enabling (1) or disabling (2)
  schedularOnOff(stringRead.toInt());
}

this works:

void loop() {
  runner.execute();

  if (Serial.available() > 0) {
    stringRead = Serial.readStringUntil('\n');
    schedularOnOff(stringRead.toInt());
  }
}

@arkhipenko
Copy link
Owner

arkhipenko commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants