Giter Site home page Giter Site logo

arkhipenko / taskscheduler Goto Github PK

View Code? Open in Web Editor NEW
1.2K 75.0 218.0 2.36 MB

Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers

Home Page: http://playground.arduino.cc/Code/TaskScheduler

License: BSD 3-Clause "New" or "Revised" License

C++ 96.69% C 3.31%
arduino esp8266 attiny multitasking cooperative library teensy esp32 nrf52 stm32

taskscheduler's Introduction

Task Scheduler

Cooperative multitasking for Arduino, ESPx, STM32 and other microcontrollers

Version 3.7.0: 2022-10-10 Latest updates

arduino-library-badgexscode

Get expedited support or integration consultation for TaskScheduler from xs:code

xscode

OVERVIEW:

A lightweight implementation of cooperative multitasking (task scheduling). An easier alternative to preemptive programming and frameworks like FreeRTOS.

Why cooperative?

You mostly do not need to worry about pitfalls of concurrent processing (races, deadlocks, livelocks, resource sharing, etc.). The fact of cooperative processing takes care of such issues by design.

“Everybody who learns concurrency and thinks they understand it, ends up finding mysterious races they thought weren’t possible, and discovers that they didn’t actually understand it yet after all.” Herb Sutter, chair of the ISO C++ standards committee, Microsoft.

Main features:

  1. Periodic task execution, with dynamic execution period in milliseconds (default) or microseconds (if explicitly enabled) – frequency of execution
  2. Number of iterations (limited or infinite number of iterations)
  3. Execution of tasks in predefined sequence
  4. Dynamic change of task execution parameters (frequency, number of iterations, callback methods)
  5. Power saving via entering IDLE sleep mode when tasks are not scheduled to run
  6. Support for event-driven task invocation via Status Request object
  7. Support for task IDs and Control Points for error handling and watchdog timer
  8. Support for Local Task Storage pointer (allowing use of same callback code for multiple tasks)
  9. Support for layered task prioritization
  10. Support for std::functions (tested on ESPx and STM32 only)
  11. Overall task timeout
  12. Static and dynamic callback method binding
  13. CPU load / idle statistics for time critical applications
  14. Scheduling options with priority for original schedule (with and without catchup) and interval
  15. Ability to pause/resume and enable/disable scheduling
  16. Thread-safe scheduling while running under preemptive scheduler (i. e., FreeRTOS)
  17. Optional self-destruction of dynamically created tasks upon disable

Scheduling overhead: between 15 and 18 microseconds per scheduling pass (Arduino UNO rev 3 @ 16MHz clock, single scheduler w/o prioritization)

TaskScheduler was tested on the following platforms:

  • Arduino Uno R3
  • Arduino Nano
  • Arduino Micro
  • ATtiny85
  • ESP8266
  • ESP32
  • Teensy (tested on Teensy 3.5)
  • nRF52 (tested on nRF52832)
  • nRF52 Adafruit Core (tested on nRF52840 with v3.6.2 workround)
  • STM32 (tested on Mini USB STM32F103RCBT6 ARM Cortex-M3 leaflabs Leaf maple mini module F)
  • MSP430 and MSP432 boards
  • Raspberry Pi (requires external Arduino.h and millis() implementation)

Don't just take my word for it - try it for yourself on Wokwi


TaskScheduler process diagram

Changelog is located here.

For detailed functionality overview please refer to TaskScheduler documentation in the 'extras' folder or in the Wiki page.

User Feedback:

"I've used https://github.com/arkhipenko/TaskScheduler with great success. Running LED patterns, monitoring button presses, reading data from an accelerometer, auto advancing to the next pattern, reading data from Serial. All at the same time." - here

"There are libraries that do this automatically on Arduino too, allowing you to schedule [cooperative] multitasking and sleep the uC between tasks. E.g. https://github.com/arkhipenko/TaskScheduler is really good, I've used it before. You basically queue up a list of task callbacks and a schedule in your setup() and then do a call to tasks.execute() in loop(), which pops off the next task that is due in a queue or sleeps otherwise. It's simple, but much more straightforward than manually using if millis() - last > delta1... else sleep() and not as rigid as using the timer ISRs (which really serve a different purpose)." - here

"I took the controller with me on a business trip and spend the night getting the basic code framework out. It is going to run on top of Arkhipenko’s TaskScheduler. (https://github.com/arkhipenko/TaskScheduler) This should help me isolate any issues between the different control systems while managing the different task’s timing requirements." - here

"it's really cool and useful, for whenver you want your MCU to do more than 1 task" - here

"I encourage you to use it in the Arduino environment, it allows you to save a lot of time (and code lines) wherever you need to schedule, i.e. run many tasks that should to perform at different frequencies and when we want to have the greatest control over the performance of these tasks and we want good diagnostic of errors." - here

"arkhipenko/TaskScheduler is still my choice for now, especially when I get my pull request in, so we can have that idle 1 ms sleep feature for free." - here

"The difference with milis is basically that you don’t have to be using logics to manage the executions, but the module itself does it. This will allow us to make code more readable and easier to maintain. In addition, we must take into account the extra functions it provides, such as saving energy when not in use, or changing settings dynamically." - here

Check out what TaskScheduler can do:

Around the world:

My projects:

taskscheduler's People

Contributors

arkhipenko avatar blackedder avatar jimf42 avatar tarzan115 avatar thijstriemstra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

taskscheduler's Issues

Is there any way to use stateful callbacks?

Judging from the source code, the callback is fixed as a single (function) pointer. As such, even C++11 lambda functions would not help.

Do you have any plans (and vision) on how to implement them? My analysis concluded, that the simplest and most efficient way to do it is to store the following struct

struct {
   void (* fptr)(void *);
   void* arg;
}

instead of just function pointer. Overload the operator() for such struct; and if the *arg==0, call the fptr without parameters.

What do you think?

interrupt

Hello,
Is it possible ( advisable) to have a interrupt attached in "loop" for a sensor measurement or will this cause problems with the task scheduler?

issue with MightyCore

Hi
I have problem with Optiboot -- https://github.com/MCUdude/MightyCore -- ATmega644P

In file included from /Users/omegapro/Documents/Arduino/libraries/libraries/LCDMenuLib2/src/LCDMenuLib2.h:142:0,
from /Users/omegapro/Google Drive/Elettronica/ASKO/Software/prova menu/LCDML_031_i2c_display_20x4/LCDML_031_i2c_display_20x4.ino:6:
/Users/omegapro/Documents/Arduino/libraries/libraries/LCDMenuLib2/src/LCDMenuLib2_macros.h:101:88: error: invalid conversion from 'void ()()' to 'LCDML_FuncPtr_pu8 {aka void ()(unsigned char)}' [-fpermissive]
LCDMenuLib2_menu parent ## _ ## child(id, param, settings, callback, condition );
^

                                                                                   ^

/Users/omegapro/Documents/Arduino/libraries/libraries/LCDMenuLib2/src/LCDMenuLib2_macros.h:107:9: note: in expansion of macro 'LCDML_addAdvanced'
LCDML_addAdvanced(id, parent, child, NULL, content, callback, 0, _LCDML_TYPE_default)
^
/Users/omegapro/Google Drive/Elettronica/ASKO/Software/prova menu/LCDML_031_i2c_display_20x4/LCDML_031_i2c_display_20x4.ino:77:3: note: in expansion of macro 'LCDML_add'
LCDML_add (8 , LCDML_0_1 , 5 , "Imp. Caldaia" , temp_caldaia);
^
In file included from /Users/omegapro/Documents/Arduino/libraries/libraries/LCDMenuLib2/src/LCDMenuLib2.h:121:0,
from /Users/omegapro/Google Drive/Elettronica/ASKO/Software/prova menu/LCDML_031_i2c_display_20x4/LCDML_031_i2c_display_20x4.ino:6:
/Users/omegapro/Documents/Arduino/libraries/libraries/LCDMenuLib2/src/LCDMenuLib2_menu.h:73:13: error: initializing argument 4 of 'LCDMenuLib2_menu::LCDMenuLib2_menu(uint8_t, uint8_t, uint8_t, LCDML_FuncPtr_pu8, LCDML_FuncPtr_rb)' [-fpermissive]
LCDMenuLib2_menu(uint8_t p_id, uint8_t p_param, uint8_t p_configuration, LCDML_FuncPtr_pu8 p_callback_function, LCDML_FuncPtr_rb p_condition_function);
^

THANKS in advance for your help !!!!
Cristian

Exception during destruction of Task

I'm using the testing branch (3fc2676) with _TASK_STD_FUNCTION defined in an ESP8266 project and running into an exception that I'm having trouble understanding—I'm hoping I'm missing something obvious. I have a class that has a std::unique_ptr<Task> and when my class is being destroyed, I get an exception that decodes as:


Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address
Decoding 15 results
0x4020494a: Task::disable() at /Users/ilg/Documents/code/esp8266-wemos-test/esp8266-wemos-test/./Library/TaskScheduler/src/TaskScheduler.h line 608
0x4020c06c: Print::write(unsigned char const*, unsigned int) at /Users/ilg/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/Print.cpp line 64
0x402049bc: Task::~Task() at /Users/ilg/Documents/code/esp8266-wemos-test/esp8266-wemos-test/main.cpp line 62
0x40204a28: std::default_delete ::operator()(Task*) const at /Users/ilg/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/bits/unique_ptr.h line 67
0x402374c4: ip_output_if at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/ipv4/ip.c line 631
0x40204a4d: ~unique_ptr at /Users/ilg/Library/Arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/1.20.0-26-gb404fb9-2/xtensa-lx106-elf/include/c++/4.8.2/bits/unique_ptr.h line 185

[followed by my class's destructor, etc.]

In particular, I'm confused by the Print::write() call in there, since Task::~Task() is

Task::~Task() {
    disable();
    if (iScheduler)
        iScheduler->deleteTask(*this);
}

and line 608 of Task::disable() is bool previousEnabled = iStatus.enabled; in

bool Task::disable() {
	bool previousEnabled = iStatus.enabled;
	iStatus.enabled = false;
	iStatus.inonenable = false; 
	if (previousEnabled && iOnDisable) {
		Task *current = iScheduler->iCurrent;
		iScheduler->iCurrent = this;
		iOnDisable();
		iScheduler->iCurrent = current;
	}
#ifdef _TASK_STATUS_REQUEST
	iMyStatusRequest.signalComplete();
#endif
	return (previousEnabled);
}

If more context is necessary, I'll see if I can work up a reasonably-sized example to reproduce the issue. Thanks.

Multiple definition error when including taskscheduler (from a separate header file.)

I tried setting up a simple project (using platformio) and get the following compilation error (I am pretty sure this used to work without a problem.)

ndexing .pioenvs/esp32dev/libd60/libTaskScheduler_ID721.a
Archiving .pioenvs/esp32dev/libFrameworkArduino.a
Indexing .pioenvs/esp32dev/libFrameworkArduino.a
Linking .pioenvs/esp32dev/firmware.elf
.pioenvs/esp32dev/src/main.ino.o: In function `Task::isEnabled()':
/home/edwin/TmpSync/tmpPain/.piolibdeps/TaskScheduler_ID721/src/TaskScheduler.h:308: multiple definition of
 `Task::isEnabled()'
.pioenvs/esp32dev/src/foo1.o:/home/edwin/TmpSync/tmpPain/.piolibdeps/TaskScheduler_ID721/src/TaskScheduler.
h:308: first defined here
.pioenvs/esp32dev/src/main.ino.o: In function `Task::getInterval()':
main.ino.cpp:(.text._ZN4Task11getIntervalEv+0x0): multiple definition of `Task::getInterval()'
.pioenvs/esp32dev/src/foo1.o:foo1.cpp:(.text._ZN4Task11getIntervalEv+0x0): first defined here
.pioenvs/esp32dev/src/main.ino.o: In function `Task::getIterations()':
main.ino.cpp:(.text._ZN4Task13getIterationsEv+0x0): multiple definition of `Task::getIterations()'
.pioenvs/esp32dev/src/foo1.o:foo1.cpp:(.text._ZN4Task13getIterationsEv+0x0): first defined here
.pioenvs/esp32dev/src/main.ino.o: In function `Task::getRunCounter()':
main.ino.cpp:(.text._ZN4Task13getRunCounterEv+0x0): multiple definition of `Task::getRunCounter()'
.pioenvs/esp32dev/src/foo1.o:foo1.cpp:(.text._ZN4Task13getRunCounterEv+0x0): first defined here
.pioenvs/esp32dev/src/main.ino.o: In function `Task::setCallback(void (*)())':
main.ino.cpp:(.text._ZN4Task11setCallbackEPFvvE+0x0): multiple definition of `Task::setCallback(void (*)())
'
...

While debuggin this I found that it happens even with just four files:

src/foo.h

#ifndef FOO1_H
#define FOO1_H

#include "TaskScheduler.h"

int sum(int a, int b);

#endif

src/foo.cpp

#include "foo1.h"

int sum(int a, int b) {
    return a + b;
}

src/main.ino

#include "foo1.h"

void setup() {
  Serial.begin(115200);
}

void loop() {
    sum(100, 100);
}

platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps = TaskScheduler

Compilation Error with PlatformIO for ESP8266

Hi,

I can't compile an empty PlatformIO project for ESP-8266 if TaskScheduler is importet.

Here is my platormio.ini File

[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino

lib_deps =
    TaskScheduler

I got the following Error message:

Processing esp12e (platform: espressif8266; board: esp12e; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LibraryManager: Installing id=721
Downloading...
Unpacking  [########################------------]   67%
Unpacking...
Error: Traceback (most recent call last):
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\__main__.py", line 120, in main
    cli(None, None, None)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 700, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 680, in main
    rv = self.invoke(ctx)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 1027, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 873, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 508, in invoke
    return callback(*args, **kwargs)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\decorators.py", line 16, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\commands\run.py", line 107, in cli
    result = (envname, ep.process())
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\commands\run.py", line 205, in process
    result = self._run()
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\commands\run.py", line 300, in _run
    self.verbose)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\commands\run.py", line 323, in _autoinstall_libdeps
    ctx.invoke(cmd_lib_install, libraries=[lib], silent=not verbose)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\core.py", line 508, in invoke
    return callback(*args, **kwargs)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\click\decorators.py", line 26, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\commands\lib.py", line 103, in lib_install
    library, silent=silent, interactive=interactive, force=force)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\managers\lib.py", line 354, in install
    force=force)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\managers\package.py", line 720, in install
    pkg_dir = self._install_from_piorepo(name, requirements)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\managers\lib.py", line 213, in _install_from_piorepo
    if app.get_setting("enable_ssl") else dl_data['url'], requirements)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\managers\package.py", line 444, in _install_from_url
    self.unpack(dlpath, tmp_dir)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\managers\package.py", line 224, in unpack
    return fu.unpack(dest_dir, with_progress=False)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\unpacker.py", line 112, in unpack
    self._unpacker.extract_item(item, dest_dir)
  File "c:\users\yannik\.platformio\penv\lib\site-packages\platformio\unpacker.py", line 38, in extract_item
    self._afo.extract(item, dest_dir)
  File "C:\Users\Yannik\.platformio\python27\Lib\tarfile.py", line 2118, in extract
    self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  File "C:\Users\Yannik\.platformio\python27\Lib\tarfile.py", line 2194, in _extract_member
    self.makefile(tarinfo, targetpath)
  File "C:\Users\Yannik\.platformio\python27\Lib\tarfile.py", line 2234, in makefile
    with bltn_open(targetpath, "wb") as target:
IOError: [Errno 2] No such file or directory: 'D:\\Eigene Dateien (cloud)\\GitLab\\LTC-Led-Track-Controller\\Software\\LTC-Led-Track-Controller\\.piolibdeps\\_tmp_installing-y9ze9y-package\\.\\examples\\Scheduler_example20_StatusRequest_LTS_WDT_Timeout_Object\\Scheduler_example20_StatusRequest_LTS_WDT_Timeout_Object.ino'

============================================================

An unexpected error occurred. Further steps:

* Verify that you have the latest version of PlatformIO using
  `pip install -U platformio` command

* Try to find answer in FAQ Troubleshooting section
  http://docs.platformio.org/page/faq.html

* Report this problem to the developers
  https://github.com/platformio/platformio-core/issues

============================================================

Any ideas what is causing the problem and how to solve it?

I reinstalled PlatformIO multiple times, tried Atom and VSCode, but everytime the same problem.

Thanks in advance.

Finer time resolution

I initially used your library to do multitasking on Arduino for my robot and 3D printer. I found that the time resolution (in milli-seconds) is not fine enough for my applications. I ended up copying your library and replacing all the millis() with micros().

It would be nice if TaskScheduler class could be updated to support finer time resolution.

What is the best way to use TaskScheduler with POWER_DOWN on idle (instead of the IDLE mode)?

If you power down Arduino instead of putting it to sleep, you can wake it with a watchdog timer. I know, that you use a watchdog timer for checking for scheduler overruns, but only optionally.

I also know, that when Arduino is powered down, it doesn't update millis() and PWMs are down too. But it can still respond to external interrupts and I2C interrupts, so it is sufficient for my projects.

Do you have any ideas on how to use powerdown mode instead of idle with your library? I can help you implement this.

Run counter as an index into array within callback.

G'day mate, I have an issue using run counter as an index into an 8-byte array inside a callback. If the callback invokes another callback, run counter=1,3,5,7... instead of 1,2,3,4,...(see attached sketch). My workaround is to increment a global index variable and set iterations x 2 (8x2). But is there a a more elegant way to achieve this?

testtask.ino.txt

Blocking tasks request

Hi!
Can I do a program executing one task after another? For example, create a task to execute for a particular time and other tasks are waiting?

Callback running every interval but not task that calls callback

If I create a task that has a callback function A and A is set to run ever 5 seconds.. and A calls callback function B through setCallback. Why is it that B ends up being called every 5 seconds but A only runs once and never gets called again? I must be doing something wrong..

Rename tag 'show'

Hi,

There is a version tag called 'show', which I think was supposed to be '1.6.0'?

nick.

Xtensa compiler (esp8266): Declaration of constructor does not match implementation

Compiling TaskScheduler.h using the xtensa-lx106-elf-g++ compiler (esp8266) fails. Apparently, it can not match the declaration of the constructor with its implementation because of mixing boolean and bool for parameter aEnable.

public:
   Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler*  aScheduler=NULL, boolean aEnable=false, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);

needs to become

public:
   Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, bool aEnable=false, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);

std::function support

For one of my projects I preferred to use std::functions instead of function pointers. I have made the needed changes to the source code here. If you are interested in adding support std::function to TaskScheduler, I'd be happy to clean it up and submit a PR. The needed changes are fairly straightforward.

Reset a task start time

Hi, is it possible to reset a task start time while the task is active?
This is my scenario:
I want a task to control the backlight on an lcd so the display turns off when there is no user activity for say 30 seconds.
I would like to start a task for this (no problem) but if there is some activity from a user then I want to reset the task execution start time back to the beginning to delay the task. I guess I can do this with disable/enable but is there another cleaner way?

setInterval() Bug

over night I have been thinking about that.
We implemented the fix it by placing: if (iEnabled) enable(); into Task::setIterations().
I am not sure if that is completely right and if it should not be like:

void Task::setIterations(long aIterations) { 
    if (iEnabled && iIterations == 0) enable();
    iSetIterations = iIterations = aIterations; 
}

You have to decide if that makes sense . My motivation was:

  1. if iterations is not 0 there was no problem, so there was no need to do it.
  2. but more importantly: enable() resets the iPreviousMillis value. But in the case, that the Task is still running, this would destroy the current interval.
    I have a Task running. Its Interval is set to 1o.ooo ms. Every 1o seconds the callback is run.
    Four seconds after the callback was run, I call Task::setIterations() this will reset the Value of iPreviousMillis in a way that the task is due to run immediately. But it should wait another six seconds.

I placed it before the reset of the Variables so that I have the untouched iIterations to compare. I think that is OK too.

You wrote that you have placed the fix into Task::set() too. I Think that was not necessary, before I knew what the Problem was and before there was Task::restart() I used full Task::set() as workaround for Task::setIterations(), because there it worked without any Problems. Although now, looking at the code I cannot understand why.

PS.: great Library, Thank You.

License slightly cumbersome

This project currently uses an older version of the BSD license (AFAICS). It is fairly liberal, but contains two clauses that are a bit cumbersome for our project:

  1. "Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms", which means the full license text must be present in the binary, taking up flash space (it does not actually require displaying the text anywhere, but that would of course make sense).
  2. "and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed by Anatoli Arkhipenko", which means we should be mentioning your name pretty much everywhere.

I suspect that neither of these are actually your intention? If they are indeed not, perhaps the 3-clause BSD license would be a better fit: https://opensource.org/licenses/BSD-3-Clause It still requires keeping the license and copyright in source versions, but only requires them to be present in any documentation accompanying the binary version.

I would be grateful if you could consider this request swiftly, since we are planning to make a release of our software soon.

Scheduler seems to crash/hang

Hello,

Thanks for your cool library! But ... :-) I'm running into an weird issue where the scheduler seems to stay stuck during running of one particular task. At that point all tasks stop and no work is done. I would like to ask your assistance in troubleshooting. Extra flags/options/debug statements I could include to pinpoint the issue.

My code can be found here:
https://github.com/costyn/Glow-Fur-for-Pro-Mini-with-MPU6050

So at a certain point, only if Task taskGetDMPData is enabled, runner.execute() will not return in void loop(). I have included a heartbeat in loop() to confirm this. I have tried re-enabling tasks in loop() but that didn't make a difference.

I have tried to see if there is a pattern in the number of iterations at which it crashes, but I have not been able to spot a pattern.

The code for the MPU6050 works fine without the scheduler. It's only if I run the data retrieval from the gyro with the scheduler that it stops.

I also checked for memory issues; heap/stack crashes, but the SRAM usage stays constant during running.

Pulling pin 3 to GND triggers an interrupt with some println's, and these still work after the scheduler crashes. So I know the AVR is still not crashed.

Any tips welcome! Thanks!

Kind regards,

Costyn.

Rename enable() and enableDelayed()

The TaskScheduler is well-designed in allowing both immediate execution of tasks via enable() or delayed execution via enableDelayed(). The documentation for enable() says that it "enables the task, and schedules it for immediate execution (without delay) at this or next scheduling pass depending on when the task was enabled." That's likely to cause confusion and bugs, however, for a few reasons:

  1. running tasks immediately upon enable() means that the may execute at incorrect times. For example, a task may be set to run once per second, but if the enable() is called more than once in a second, the task will run more than once per second. This semantics means that the default behavior can lead to bugs. Programmers have additional burden to code this correctly.

  2. "Enable" commonly means to make possible, not to do. So the function name is misleading.

  3. For the same reason, enable is a function that should be idempotent. Intuitively, if you enable something that is already enabled, nothing should happen.

  4. It doesn't scale. Suppose we have a thousand Tasks all with different timings. Suppose further that enabling them all via with enableDelayed() works: they all run correctly at their appointed times. But with the current semantics, using enable() and all of them would make them all run immediately, likely leading to conflicts or overload.

Therefore enable() should use the delay, and enableImmediate() should be created to run immediately. Or to minimize disruption for existing users, deprecate enable(), leaving enableImmediate() and enableDelayed() to maximize explicitness and clarity.

Document approximate memory requirements

It would be really nice to know the approximate memory (program and RAM) requirements for this library with the various compile parameters enabled. Any chance of getting that into the documentation (WiKi)?

Add a default constructor to the Task class

Hi,

It might be a good idea to add an explicit default constructor to the Task class.

Line 128 of TaskSchedulerDeclarations.h, add:
INLINE Task() {};

This would allow to compile libraries such as painlessMesh (which declare a bunch of Tasks without initializing them) together with option _TASK_STATUS_REQUEST.

Another question: why not use the classical header (.h) and code (.cpp) file structure instead of two .h files with different names?

Get upcoming task

It would be a good idea to be able to find the upcoming task that will be executed given the current task

OLED turn off after some time

Thank you for this great scheduler.. I've been able to do pretty much everything I've needed except one weird task.

I'm trying to set up a timeout on an OLED screen connected to the arduino. There is a button that can turn it off or on, but I'd like to implement a timeout after let's say 60 seconds to save the screen.

I've set up all the tasks, and tried to use the t1.delay(60000); method but it didn't do anything, eg:

void displayWake() {

u8x8.setPowerSave(false); //screen is on
sleepTimerTask.setCallback(&displaySleep); //method sets power save to true
sleepTimerTask.delay(60000); //delay before the function above is executed

}
where the sleep timer is: Task sleepTimerTask(TASK_SECOND, TASK_ONCE, &displaySleep);

Thanks again for your help
T

<avr/wdt.h>

Hello, first at all congratulations and thank you for your hard work !
i have a problem to compile the 7th example who use #include <avr/wdt.h>
it say : "No such file or directory"
can you tell me, please, how can i do to make it work ?

Stable State for an task

Hello,
it is possible to set a task in a stable state when the status is changed to disable ?

For example: a pump control task

first iteration:
// init something

loop:
// ....

stable stop/disable state:
// pump stop

HELP: Flash for chip ID 7e06e0e6 is not supported

Hey mate,

Love the library and how much more comprehensive it is than all the other options out there. Nice work!

Am currently working on an Arduino implementation of a CubeSat, and will be putting the little guy on a balloon launch this Saturday (a couple of days from now) and would love to be able to use your library.

It complies fine, but when uploading the following error message pops up

"Flash for chip ID 7e06e0e6 is not supported"

I'm using a 3rd party Arduino Due copy - http://www.geeetech.com/wiki/index.php/Iduino_DUE_Pro -

Any help would be much much appreciated.

Thanks,
Jordan

Code that worked with 2.4.0 doesn't work with 2.5.0

Hello, thanks for making this, it has been a lot of help for a couple projects im working on with the esp8266. Recently with the update to 2.5 code that has been working stopped compiling, I think this is due to the new multi tab compatibility but i'm not sure, any help would be gladly accepted.

The error is below.

`
In file included from Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskScheduler.h:125:0,

             from defcon-badge\defcon-badge.ino:20:

Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskSchedulerDeclarations.h:94:3: error: conflicting declaration 'typedef struct __task_status __task_status'

} __task_status;

^

In file included from Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessMesh.h:6:0,

             from defcon-badge\defcon-badge.ino:14:

Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessScheduler.h:221:3: error: '__task_status' has a previous declaration as 'typedef struct __task_status __task_status'

} __task_status;

^

In file included from Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskScheduler.h:125:0,

             from defcon-badge\defcon-badge.ino:20:

Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskSchedulerDeclarations.h:99:7: error: redefinition of 'class Task'

class Task {

   ^

In file included from Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessMesh.h:6:0,

             from defcon-badge\defcon-badge.ino:14:

Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessScheduler.h:230:7: error: previous definition of 'class Task'

class Task {

   ^

In file included from Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskScheduler.h:125:0,

             from defcon-badge\defcon-badge.ino:20:

Arduino-B\portable\sketchbook\libraries\TaskScheduler\src/TaskSchedulerDeclarations.h:187:7: error: redefinition of 'class Scheduler'

class Scheduler {

   ^

In file included from Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessMesh.h:6:0,

             from defcon-badge\defcon-badge.ino:14:

Arduino-B\portable\sketchbook\libraries\painlessMesh-master-1bab045503bff21f5e7b43ea120912e227835346\src/painlessScheduler.h:319:7: error: previous definition of 'class Scheduler'

class Scheduler {

   ^

`

Also for ESP8266?

Hello,
is this only for Avr arduino or can it be used with ESP8266.

Please ingnore this. I found it in the libraries for the ESP8266

best regards

Real Time

Hi Anatoli,
How are you?
Well, just another simple question.
Can your library be considered of Real Time?
Thanks,
Luis

Power save/idle mode not working longer term?

Firstly well done putting TaskScheduler together, looks powerful.

I tried your example 1 and added definition for task sleep on idle to confirm lower power consumption was possible.

It appears to be switching between normal power and power save initially but after task 2 ran a few times after task 3 was disabled it appears to never switch to idle and power is never reduced. I even increased task 2 to 5 seconds which should have made this even clearer.

I also tried example 18 but this does seem to work.

Perhaps the bug is related to finite duration tasks, task disable or deleteTask?

Arduino Mega AT2560

Hi,
Thanks for your work.
I'm trying to run some examples in a Arduino Mega AT2560 with a Linux computer.
They compile well, upload well but in the Serial Monitor window I get a lot of strange characters.
Can you give me please an idea about what this could be?
Thanks in advance,
Luis

porting to ESP32?

what about porting to ESP32?

beside all defines is needed to remove the dependecy to
#include "user_interface.h"

Compiling Error

Hello,
I'm having problems running your example Code. I'm getting the following compiling error.

in file included from sketch_oct21b.ino:1:0:
/home/mirko/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:198:1: error: prototype for 'Task::Task(long unsigned int, long int, void (*)(), Scheduler*, bool, bool (*)(), void (*)())' does not match any in class 'Task'
 Task::Task( unsigned long aInterval, long aIterations, void (*aCallback)(), Scheduler* aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)() ) {
 ^
/home/mirko/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:133:7: error: candidates are: constexpr Task::Task(Task&&)
 class Task {
       ^
/home/mirko/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:133:7: error:                 constexpr Task::Task(const Task&)
/home/mirko/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:136:2: error:                 Task::Task(long unsigned int, long int, void (*)(), Scheduler*, boolean, bool (*)(), void (*)())
  Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, boolean aEnable=false, bool (*aOnEnable)()=NULL, void (*aOnDisable)()=NULL);

Using the TaskScheduler inside another library

Hi,

I'm trying to turn my working script into a library, making it much easier to reuse for other - very similar - projects. The TaskScheduler works perfectly from my original sketch, but I can't get it to compile when moving into a separate library object. See also my post on the Arduino forum for code example.

Compiler says:
error: '((HydroMonitorMaster*)this)->HydroMonitorMaster::tReadSensors' does not have class type tReadSensors.enable();

Probably more of a generic programming issue than a TaskScheduler issue, I haven't been able to find a solution for this.

Is running?

is there a method or so to know if any specific task is running?

or in the worst case what would happen if do I try to disable and delete any in-existent task?

Best regards

Warning, Category

Not really a big issue, but getting this warning "WARNING: Category 'Schedulers' in Library TaskScheduler is not valid. Setting to 'Uncategorized'"
Any idea how to fix that, or is there something I need to modify in the arduino settings to make that category valid?

Real sensor delay

I'm looking at example 5, and I have a question about how do I get the real sensor delay instead a simulated one like in this example?

inline specifier dissapeared in 2.5.0, causing compile error

Hi!
Why did you remove inline specifiers of methods in v2.5.0? They came in v2.2.0 simply dissapear after v2.3.0.
I am using Task class in my template class which is producing linking errors.
Each derived class giving me multiple definition error for each method of your library.
However I'd like to use features from v2.5.0, so i cant go back to v2.3.0.
Is there any chance to restore them?

Marci

Cannot use <TaskScheduler.h> in several .h-files in one Project - Preprocessor-Statement issue?

I'm running into problems using this library in several headerfiles in my Project and I wonder if this is a problem with the preprocessor-statement because I'm not having this issue with other libraries like <vector.h> or else.

I could make it work using <TaskScheduler.h> in my Project.ino and <TaskSchedulerDeclarations.h> in my other Header-Files that need to work with Tasks and so on.

This is the minimal source-code that reproduces the error: https://gitlab.com/narjesmieke/project
My problem, the error as well as my current workaround is described in the following Stackoverflow-Post: https://stackoverflow.com/questions/50291528/preprocessing-for-taskscheduler-library-doesnt-work-multiple-definition-error

Question on Time Critical

Great library! Makes my code so modular. But i have a question on Time Critical. I am running Scheduler_example09_TimeCritical and I have modified it by removing the random delay. But i still get start delayed showing up as 1 at random intervals, it is mostly 0, and never more than one. Would that be considered jitter? i am using a ESP8266.

TaskScheduler seems not compatible with multiple object source files (aka tabs in IDE)

My project will be rather big and I need to have it splitted between many .cpp files. The source code for your library is included in one big header file, declarations together with definitions. What should I do, to stop linker from complaining about

/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: multiple definition of `StatusRequest::signal(int)'
./.ino.cpp.o:/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: first defined here
./file2.cpp.o: In function `StatusRequest::signal(int)':
/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: multiple definition of `StatusRequest::signalComplete(int)'
./.ino.cpp.o:/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: first defined here
./file2.cpp.o: In function `StatusRequest::signal(int)':
/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: multiple definition of `Task::reset()'
./.ino.cpp.o:/home/Adama-docs/Adam/MyDocs/Programowanie/Arduino/libraries/TaskScheduler/src/TaskScheduler.h:387: first defined here
./file2.cpp.o: In function `StatusRequest::signal(int)':

To reproduce:

  1. Open new sketch, and put there
#include "header.hpp"

void setup()
{
    Serial.begin(9600);
    Serial.println(myfunc());
    Serial.println(globalx);
}

void loop() {}

  1. Add a new tab header.hpp with
#pragma once

#include <stdint.h>
#include <TaskScheduler.h>
extern uint8_t globalx;


uint8_t myfunc();

  1. Add a new tab file2.cpp with
#include "header.hpp"

uint8_t globalx = 42;

uint8_t myfunc()
{
    return 23;
}

  1. Try to compile and get the errors.

If you remove the line #include <TaskScheduler.h> from the header.hpp, everything compiles, but without your library.

I guess you'd need to split the library into proper decraration header and the definition (.cpp) file. Do you have plans for that?

Task schedule inconsistent at start

Hi Anatoli,

Nice work on the task scheduler! I tested the first example and while it worked very well, the tasks did not follow the actual schedule until the fourth iteration. Attached the monitor result and example code which I modified to display interation count. Any clues? Could it be something odd with serial.println rather than the task itself?

regards,
Alex
Scheduler_example.txt
monitor.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.