8000 Merge pull request #5 from Makuna/FeatureUpdate · useful-esp8266-lib/Task@de9bbf1 · GitHub
[go: up one dir, main page]

Skip to content

Commit de9bbf1

Browse files
committed
Merge pull request Makuna#5 from Makuna/FeatureUpdate
feature work
2 parents 128f21b + 7d105ce commit de9bbf1

File tree

6 files changed

+110
-189
lines changed

6 files changed

+110
-189
lines changed

README.md

Lines changed: 12 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,26 @@
11
# Task
22

3+
[![Donate](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6AA97KE54UJR4)
4+
35
Arduino Nonpreemptive multitasking library
46

5-
For the latest Arduino IDE, use the library manager to find and install "Task by Makuna" library.
7+
NOTE: Avoid the use of Delay in all high level code as the tasks timing should be used to replace it.
68

7-
For older versions, you can just clone this into your Arduino\Library folder.
9+
For bugs, make sure there isn't an active issue and then create one.
810

9-
For a good starting point at understanding the direction of this library, please read https://learn.adafruit.com/multi-tasking-the-arduino-part-1?view=all.
10-
This library was not based on that work though, but they share common goals.
11+
For quick questions jump on Gitter and ask away.
12+
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/Task?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
1113

12-
NOTE: Avoid the use of Delay in all high level code as the tasks timing should be used to replace it.
14+
## Documentation
15+
[See Wiki](https://github.com/Makuna/Task/wiki)
1316

14-
## Installing This Library
17+
## Installing This Library (you just want to use it)
1518
Open the Library Manager and search for "Task by Makuna" and install
1619

17-
## Installing This Library From GitHub
20+
## Installing This Library From GitHub (you want to contribute)
1821
Create a directory in your Arduino\Library folder named "Task"
1922
Clone (Git) this project into that folder.
2023
It should now show up in the import list.
2124

22-
## TaskTime
23-
### Conversion macros
24-
The resolution of the task interval is based on millis() or micros(). The default is millis(). To allow the code to easily switch, callers should use the macros to wrap constants.
25-
26-
```
27-
uint32_t taskTime = MsToTaskTime(400); // 400 ms
28-
uint32_t timeMilliseconds = TaskTimeToMs(taskTime);
29-
uint32_t timeMicroseconds = TaskTimeToUs(taskTime);
30-
taskTime = UsToTaskTime(400000) // 4000000us, 400ms also
31-
```
32-
This is important for passing in time interval when the task is created, and when handling the deltaTime parameter in the Update method.
33-
34-
```
35-
FunctionTask taskTurnLedOn(OnUpdateTaskLedOn, MsToTaskTime(400)); 400ms
36-
37-
void OnUpdateTaskLedOn(uint32_t deltaTime)
38-
{
39-
uint32_t deltaTimeMs = TaskTimeToMs(deltaTime);
40-
}
41-
```
42-
### Getting the current Update Time
43-
If you call millis() or micros(), you will get the time as it is right then. If you want relative time from update to update, you can get this from the TaskManager. This value will change only on the update interval, and should only be used within an update call.
44-
```
45-
uint32_t updateTaskTime = taskManager.CurrentTaskTime();
46-
```
47-
48-
### Using higher resolution time
49-
To switch the library to use a higher resolution interval (microseconds), you need to edit the Task.h file in the library/Task folder and uncomment the following line.
50-
51-
```
52-
//#define TASK_MICRO_RESOLUTION
53-
```
54-
If you have used the macros mentioned above, your project should compile and run, but now at a higher resoltion.
55-
By doing this, the longest time a task interval can be is just over 70 minutes.
56-
TaskTime values will now be microseconds, but the time interval may still be larger as some Arduinos will give values that increment by 2, 4, or even 8.
57-
58-
## Samples
59-
### BlinkUsingTaskFunctions
60-
This demonstrates the use of the FunctionTask feature of Task library. It will use two FunctionTasks to to blink a LED repeatedly, by alternating which task is active and flpping the state of the LED pin.
61-
In this example, tasks are declared at the top and are associated with a function that will be run when the task gets called to update.
62-
63-
```
64-
FunctionTask taskTurnLedOn(OnUpdateTaskLedOn, MsToTaskTime(400)); // turn on the led in 400ms
65-
FunctionTask taskTurnLedOff(OnUpdateTaskLedOff, MsToTaskTime(600)); // turn off the led in 600ms
66-
67-
...
68-
69-
void OnUpdateTaskLedOn(uint32_t deltaTime)
70-
{
71-
digitalWrite(ledPin, HIGH); // turn the LED on (HIGH is the voltage level)
72-
taskManager.StopTask(&taskTurnLedOn); // stop trying to turn the LED On
73-
taskManager.StartTask(&taskTurnLedOff); // start the task to turn the LED off
74-
}
75-
76-
77-
void OnUpdateTaskLedOff(uint32_t deltaTime)
78-
{
79-
digitalWrite(ledPin, LOW); // turn the LED off by making the voltage LOW
80-
taskManager.StopTask(&taskTurnLedOff); // stop trying to turn the LED Off
81-
taskManager.StartTask(&taskTurnLedOn); // start the task to turn the LED On
82-
}
83-
```
84-
Then one of the tasks is started in the setup function.
85-
86-
```
87-
void setup()
88-
{
89-
pinMode(ledPin, OUTPUT);
90-
91-
taskManager.StartTask(&taskTurnLedOn); // start with turning it on
92-
}
93-
```
94-
The tasks will continously toggle their running state handing off to the other to turn off and on the the led.
95-
96-
### BlinkUsingTaskMacros
97-
This demonstrates the use of the Task macros feature of Task library. It will use a custom tasks defined using the helper macros to to blink a LED repeatedly.
98-
This is intended for intermediate level coders where more control is needed. This exposes to the developer the functions that are called when the task is started and stopped along with updated.
99-
The custom task is defined in the taskBlinkLed.h tab.
100-
101-
### BlinkUsingCustomTask
102-
This demonstrates the use of the custom Task object feature of Task library. It will use a custom task to blink a LED repeatedly.
103-
This is intended for advanced level coders where the most control is required and knowledge of C++ is understood.
104-
105-
### ButtonTask
106-
This demonstrates the use of the custom Task object feature of Task library.
107-
It will instance two custom ButtonTasks to monitor two different pins and call back when they change state; with debouce and auto repeat support.
108-
109-
This requires two momentary buttons attached to any io pins and ground. One button will turn on the on board led when it is pressed down, the other button turn off the on board led when it is released. Both will send usefull information to the serial monitor.
110-
The custom task is defined in the ButtonTask.h tab.
111-
112-
### ButtonInterrupt
113-
This demonstrates the use of the Sleep feature of the Task library.
114-
It will instance two custom ButtonTasks to monitor two different pins and call back when they change state; with debouce and auto repeat support.
115-
An external interrupt is tied to the buttons to wake the Arduino up on any button press.
116-
There are two tasks implementing a LED Blink showing a "heartbeat" that can only run when awake.
117-
There is a task that will put the Arduino into a deep sleep 15 seconds after any button press.
118-
119-
This requires two momentary buttons attached any io pins and ground.
120-
This requires a diode per button be attached between the button pin and a single external interrupt pin. The cathode (black band) end of the diode is attached to the button pin; the anode to the interrupt pin.
121-
122-
### MessageTask
123-
This demonstrates the use of the message passing feature of Task library.
124-
It will instance two custom ButtonTasks to monitor two different pins and they will send messages when they change state. It will also have tasks that provide a heartbeat message.
125-
126-
This requires two momentary buttons attached between pins 4 & 5 and ground, you can change the pins to any digital pin
127-
128-
### RotaryEncoder
129-
This demonstrates creating a task to manage the details of rotary encoder. The task will track a value and increment and decrement it when the encoder is rotated. It will also provide a callback so the application can respond. Further, it provides a debounced button callback for the encoder press feature.
130-
131-
This requires a common rotary encoder be connected to available pins.
132-
133-
## Sleep Modes (advanced feature)
134-
If you want to have your project to deep sleep and use less power, you can call the EnterSleep method and pass in a sleep modes as defined in Arduino header sleep.h. The default is SLEEP_MODE_PWR_DOWN if you dont provide one.
135-
The processor will be placed into the given sleep mode until it is woke up. Different sleep modes have different actions that can cause it to wake. But external interrupts will wake up the Arduino for all sleep modes.
136-
137-
```
138-
Serial.println("sleep");
139-
Serial.flush(); // flush is important, we are about to sleep the complete Arduino
140-
141-
taskManager.EnterSleep(); // this will not return until something wakes the Arduino
142-
143-
Serial.println("AWAKE");
144-
Serial.flush();
145-
```
146-
147-
## WatchDog Timer is enabled
148-
This library will turn on the watchdog timer and by default set it too 500ms. If any single function takes longer than 500ms, the Arduino will reset and start over.
149-
This is usefull where a bug in the code may cause an intermittant hang. But it requires that the developer make sure to use the Tasks to keep a single function to a small atomic piece of work.
150-
The length of the WatchDog Timer can be changed by passing in one of the flags defined in wdt.h for the supported timer lengths to the loop method.
151-
152-
```
153-
void loop()
154-
{
155-
taskManager.Loop(WDTO_1S); // use one second watch dog timer
156-
}
157-
```
158-
159-
## Multiple Tasks are no problem
160-
While the samples show simple examples, the limit to the number of tasks is based on memory and the time spent in the active update calls.
161-
You can have one task blinking an LED, while another task samples a analog in and sets PWM output. Just keep the work inside each update call to the minimum needed for that time period and set the time cycle on the task to an appropriet value.
25+
## Documentation
26+
[See Wiki](https://github.com/Makuna/Task/wiki)

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
"url": "https://github.com/Makuna/Task.git"
99
},
1010
"frameworks": "arduino",
11-
"platforms": "*",
11+
"platforms": "*"
1212
}
1313

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Task by Makuna
2-
version=1.1
2+
version=1.1.1
33
author=Michael C. Miller (makuna@live.com)
44
maintainer=Michael C. Miller (makuna@live.com)
55
sentence=A library that makes creating complex mulitple task projects easy.

src/Task.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ class Task
6161
{
6262
}
6363

64+
void setTimeInterval(uint32_t timeInterval)
65+
{
66+
_timeInterval = timeInterval;
67+
if (_taskState == TaskState_Running)
68+
{
69+
_remainingTime = timeInterval;
70+
}
71+
}
72+
73+
uint32_t getTimeInterval()
74+
{
75+
return _timeInterval;
76+
}
6477

6578
protected:
6679
virtual bool OnStart() { return true; };

src/TaskManager.cpp

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@ See GNU Lesser General Public License at <http://www.gnu.org/licenses/>.
1313
--------------------------------------------------------------------*/
1414

1515
#include <Arduino.h>
16+
1617
#include "Task.h"
1718
#include "TaskManager.h"
1819

19-
#if defined(ESP8266)
20-
#else
20+
#if defined(ARDUINO_ARCH_ESP8266)
21+
extern "C"
22+
{
23+
#include <user_interface.h>
24+
}
25+
#elif defined(__arm__)
26+
27+
#elif defined(ARDUINO_ARCH_AVR)
2128
#include <avr/po F438 wer.h>
2229
#endif
2330

@@ -27,10 +34,7 @@ TaskManager::TaskManager() :
2734
_pFirstTask( NULL ),
2835
_pLastTask( NULL )
2936
{
30-
#if defined(ESP8266)
31-
//Esp.wdtFeed();
32-
//Esp.wdtDisable();
33-
#else
37+
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_AVR) && !defined(__arm__)
3438
wdt_reset();
3539
wdt_disable();
3640
#endif
@@ -71,12 +75,7 @@ void TaskManager::StopTask(Task* pTask)
7175
pTask->Stop();
7276
}
7377

74-
#if defined(ESP8266)
75-
//void TaskManager::Loop(uint16_t watchdogTimeOutMs)
76-
void TaskManager::Loop()
77-
#else
7878
void TaskManager::Loop(uint8_t watchdogTimeOutFlag)
79-
#endif
8079
{
8180
uint32_t currentTick = GetTaskTime();
8281
uint32_t deltaTime = currentTick - _lastTick;
@@ -87,17 +86,7 @@ void TaskManager::Loop(uint8_t watchdogTimeOutFlag)
8786
uint32_t nextWakeTime = ProcessTasks(deltaTime);
8887

8988
RemoveStoppedTasks();
90-
91-
#if defined(ESP8266)
92-
// Esp8266
93-
94-
#if defined(USE_WDT)
95-
//Esp.wdtFeed();
96-
//Esp.wdtEnable(watchdogTimeOutMs);
97-
#endif
98-
99-
#else
100-
// Arduino Normal
89+
10190
// if the next task has more time available than the next
10291
// millisecond interupt, then sleep
10392
if (nextWakeTime > TaskTimePerMs)
@@ -106,6 +95,20 @@ void TaskManager::Loop(uint8_t watchdogTimeOutFlag)
10695
// due to Millis() using timer interupt at 1 ms,
10796
// the cpu will be woke up by that every millisecond
10897

98+
#if defined(ARDUINO_ARCH_ESP8266)
99+
// the esp8266 really doesn't have an idle mode
100+
#if defined(USE_WDT)
101+
// use watchdog timer for failsafe mode,
102+
// total task update time should be less than watchdogTimeOutFlag
103+
wdt_disable();
104+
wdt_enable(watchdogTimeOutFlag);
105+
#endif
106+
107+
#elif defined(__arm__)
108+
// Arm support for sleep/idle not implemented yet
109+
110+
#elif defined(ARDUINO_ARCH_AVR)
111+
109112
#if defined(USE_WDT)
110113
// use watchdog timer for failsafe mode,
111114
// total task update time should be less than watchdogTimeOutFlag
@@ -126,24 +129,57 @@ void TaskManager::Loop(uint8_t watchdogTimeOutFlag)
126129
sei();
127130
sleep_cpu(); // will sleep in this call
128131
sleep_disable();
132+
#endif // Arduino Normal
129133
}
130134
#if defined(USE_WDT)
131135
else
132136
{
137+
#if !defined(__arm__) // no arm support for watchdog
133138
wdt_reset(); // keep the dog happy
139+
#endif
134140
}
135141
#endif
136-
#endif // Esp
142+
137143
}
138144
}
139145

140-
#if defined(ESP8266)
141-
#else
146+
#if defined(ARDUINO_ARCH_ESP8266)
147+
#define RTC_MEM_SLEEP_ADDR 65 // 64 is being overwritten right now
142148

143-
void TaskManager::EnterSleep(uint8_t sleepMode)
149+
void TaskManager::EnterSleep(uint32_t microSeconds,
150+
void* state,
151+
uint16_t sizeofState,
152+
WakeMode mode)
144153
{
154+
if (state != NULL && sizeofState > 0)
155+
{
156+
system_rtc_mem_write(RTC_MEM_SLEEP_ADDR, state, sizeofState);
157+
}
158+
ESP.deepSleep(microSeconds, mode);
159+
}
160+
161+
bool TaskManager::RestartedFromSleep(void* state, uint16_t sizeofState)
162+
{
163+
rst_info* resetInfo = ESP.getResetInfoPtr();
164+
bool wasSleeping = (resetInfo && REASON_DEEP_SLEEP_AWAKE == resetInfo->reason);
165+
if (wasSleeping)
166+
{
167+
if (state != NULL && sizeofState > 0)
168+
{
169+
system_rtc_mem_read(RTC_MEM_SLEEP_ADDR, state, sizeofState);
170+
}
171+
}
172+
return wasSleeping;
173+
}
145174

175+
#elif defined(__arm__)
176+
// Arm support for sleep not implemented yet
146177

178+
179+
#elif defined(ARDUINO_ARCH_AVR)
180+
181+
void TaskManager::EnterSleep(uint8_t sleepMode)
182+
{
147183
#if defined(USE_WDT)
148184
// disable watchdog so it doesn't wake us up
149185
wdt_reset();
@@ -170,9 +206,8 @@ void TaskManager::EnterSleep(uint8_t sleepMode)
170206
wdt_reset();
171207
wdt_enable(WDTO_500MS);
172208
#endif
173-
174209
}
175-
#endif // Esp
210+
#endif
176211

177212
uint32_t TaskManager::ProcessTasks(uint32_t deltaTime)
178213
{
@@ -192,17 +227,16 @@ uint32_t TaskManager::ProcessTasks(uint32_t deltaTime)
192227
uint32_t taskDeltaTime = pIterate->_timeInterval - pIterate->_remainingTime;
193228
taskDeltaTime += deltaTime;
194229

195-
pIterate->OnUpdate(taskDeltaTime);
196-
197230
// add the initial time so we don't loose any remainders
198231
pIterate->_remainingTime += pIterate->_timeInterval;
199-
200232
// if we are still less than delta time, things are running slow
201233
// so push to the next update frame
202234
if (pIterate->_remainingTime <= deltaTime)
203235
{
204236
pIterate->_remainingTime = deltaTime + TaskTimeAccuracy;
205237
}
238+
239+
pIterate->OnUpdate(taskDeltaTime);
206240
}
207241

208242
uint32_t newRemainingTime = pIterate->_remainingTime - deltaTime;

0 commit comments

Comments
 (0)
0