Skip to content

Commit 1a4e504

Browse files
authored
Merge pull request #36 from zjedi/master
fixed spelling, grammar, section organisation, markup, added links to…
2 parents 2259d16 + 44d0c57 commit 1a4e504

1 file changed

Lines changed: 116 additions & 113 deletions

File tree

README.md

Lines changed: 116 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,70 @@
11
![ArduinoThread Logo](https://raw.githubusercontent.com/ivanseidel/ArduinoThread/master/extras/ArduinoThread.png)
22

3-
Arduino does not support "REAL" parallel tasks (aka Threads), but we can make use of this Library to
4-
improve our code, and easily schedule tasks with fixed (or variable) time between runs.
5-
6-
This Library helps to maintain organized and to facilitate the use of multiple tasks. We can
7-
use Timers Interrupts, and make it really powerfull, running "pseudo-background" tasks under the rug.
8-
9-
For example, I personaly use it for all my projects, and put all sensor aquisition and
10-
filtering inside it, leaving the main loop, just for logic and "cool" part.
11-
12-
#### ArduinoThreads is a library for managing the periodic execution of multiple tasks.
13-
14-
Blinking an LED is often the very first thing an Arduino user learns. And this demonstrates that periodically performing one single task, like toggling the LED state, is really easy. However, one may quickly discover that managing multiple periodic tasks is not so simple if the tasks have different execution periods.
15-
16-
ArduinoThreads is designed to simplify programs that need to perform multiple periodic tasks. The user defines a Thread object for each of those tasks, then lets the library manage their scheduled execution.
17-
18-
It should be noted that these are not “threads” in the real computer-science meaning of the term: tasks are implemented as functions that are periodically run to completion. On the one hand, this means that the only way a task can “yield” the CPU is by returning to the caller, and it is thus inadvisable to delay() or do long waits inside a task. On the other hand, this makes ArduinoThreads memory friendly, as no stack needs to be allocated per task.
3+
## ArduinoThreads Motivation
4+
Arduino does not support isolated parallel tasks ([Threads](https://en.wikipedia.org/wiki/Thread_(computing))),
5+
but we can make the main `loop` switch function execution conditionally and
6+
thus simulate threading with [Protothread](https://en.wikipedia.org/wiki/Protothread) mechanism.
7+
This library implements it and helps you to:
8+
9+
- schedule, manage and simplify parallel, periodic tasks
10+
- define fixed or variable time between runs
11+
- organize the code in any type of project
12+
- put all sensor readings in a thread
13+
- keep the main loop clean
14+
- hide the complexity of thread management
15+
- run "pseudo-background" tasks using Timer interrupts
16+
17+
Blinking an LED is often the very first thing an Arduino user learns.
18+
And this demonstrates that periodically performing one single task, like toggling the LED state, is really easy.
19+
However, one may quickly discover that managing multiple periodic tasks is not so simple
20+
if the tasks have different schedule.
21+
22+
The user defines a Thread object for each of those tasks, then lets the library manage their scheduled execution.
23+
24+
It should be noted that these are not “threads” in the real computer-science meaning of the term:
25+
tasks are implemented as functions that are run periodically.
26+
On the one hand, this means that the only way a task can *yield* the CPU is by returning to the caller,
27+
and it is thus inadvisable to `delay()` or do long waits inside any task.
28+
On the other hand, this makes ArduinoThreads memory friendly, as no stack need to be allocated per task.
1929

2030
## Installation
2131

22-
1. "Download":https://github.com/ivanseidel/ArduinoThread/archive/master.zip the Master branch from gitHub.
23-
2. Unzip and modify the Folder name to "ArduinoThread" (Remove the '-master')
32+
1. Download [the Master branch](https://github.com/ivanseidel/ArduinoThread/archive/master.zip) from gitHub.
33+
2. Unzip and modify the Folder name to "ArduinoThread" (Remove the '-master' suffix)
2434
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
25-
4. Restart Arduino IDE
35+
4. Restart the Arduino IDE
2636

27-
**If you are here, because another Library requires this class, just don't waste time reading bellow. Install and ready.**
37+
**If you are here just because another library requires a class from ArduinoThread, then you are done now
38+
.**
2839

2940

3041
## Getting Started
3142

32-
There are many examples showing many ways to use it. Here, we will explain Class itself,
33-
what it does and "how" it does.
43+
There are many examples showing many ways to use it. We will explain Class itself,
44+
what it does and how it does.
3445

35-
There are basicaly, three Classes included in this Library:
36-
`Thread`, `ThreadController` and `StaticThreadController` (both controllers inherit from Thread).
46+
There are three main classes included in the library:
47+
`Thread`, `ThreadController` and `StaticThreadController` (both controllers inherit from `Thread`).
3748

38-
- `Thread class`: This is the basic class, witch contains methods to set and run callbacks,
39-
check if the Thread should be runned, and also creates a unique ThreadID on the instantiation.
49+
- `Thread`: Basic class, witch contains methods to set and run callbacks,
50+
check if the Thread should be run, and also creates a unique ThreadID on the instantiation.
4051

41-
- `ThreadController class`: Responsable for "holding" multiple Threads. Can also be called
42-
as "a group of Threads", and is used to perform run in every Thread ONLY when needed.
52+
- `ThreadController`: Responsible for managing multiple Threads. Can also be thought of
53+
as "a group of Threads", and is used to perform `run` in every Thread ONLY when needed.
4354

44-
- `StaticThreadController class`: Slighly faster and smaller version of `ThreadController`.
55+
- `StaticThreadController`: Slightly faster and smaller version of the `ThreadController`.
4556
It works similar to `ThreadController`, but once constructed it can't add or remove threads to run.
4657

47-
* The instantiation of a Thread class is very simple:
58+
#### Create Thread instance:
4859

4960
```c++
5061
Thread myThread = Thread();
5162
// or, if initializing a pointer
5263
Thread* myThread = new Thread();
5364
```
5465

55-
56-
* Setting up a thread is essential. You can configure many things:
66+
#### Setup thread behaviour
67+
You can configure many things:
5768

5869
```c++
5970
myThread.enabled = true; // Default enabled value is true
@@ -68,28 +79,26 @@ myThread.ThreadName = "myThread tag";
6879
myThread.onRun(callback_function); // callback_function is the name of the function
6980
```
7081

71-
Ok, creating Threads are not so hard. But what do we do with them now?
72-
73-
* First, let's see how Threads should work, to understand what a `ThreadController` is and does
82+
#### Running threads manually
83+
Ok, creating threads isn't too hard, but what do we do with them?
7484

7585
```c++
76-
// First check if our Thread "should" be runned
86+
// First check if our Thread should be run
7787
if(myThread.shouldRun()){
78-
// Yes, the Thread should be runned, let's run it
88+
// Yes, the Thread should run, let's run it
7989
myThread.run();
8090
}
8191
```
8292

83-
Now that you got the idea, let's think a little bit: What if i have 3, 5, 100 Threads. Do I need to check EACH one?!?
84-
85-
* The answer is: NO. Create a `ThreadController` or `StaticThreadController`,
86-
and put all your boring-complex Threads inside it!
93+
#### Running threads via a controller
94+
If you had 3, 5 or 100 threads, managing them manually could become tedious.
95+
That's when `ThreadController` or `StaticThreadController` comes into play and saves you the repetitive thread management parts of code.
8796

8897
```c++
89-
// Instantiate a new ThreadController
98+
// Instantiate new ThreadController
9099
ThreadController controller = ThreadController();
91-
// Now, put a bunch of Threads inside it, FEED it!
92-
controller.add(&myThread); // Notice the & before the thread, IF it's not instantied as a pointer.
100+
// Now, put bunch of Threads inside it, FEED it!
101+
controller.add(&myThread); // Notice the '&' sign before the thread, IF it's not instantied as a pointer.
93102
controller.add(&hisThread);
94103
controller.add(&sensorReadings);
95104
...
@@ -102,58 +111,56 @@ StaticThreadController<3> controller (&myThread, &hisThread, &sensorReadings);
102111
...
103112
```
104113
105-
* You have created, configured, grouped it. What is missing? Yes, whe should RUN it!
114+
You have created, configured, grouped it. What is missing? Yes, whe should RUN it!
115+
The following will run all the threads that NEED to run.
106116
107117
```c++
108118
// call run on a Thread, a ThreadController or a StaticThreadController to run it
109119
controller.run();
110120
```
111121

112-
This will run all the Threads that NEED to be runned.
113-
114-
Congratulations, you have learned the basics of `ArduinoThread`. If you want some TIPS, see bellow.
122+
Congratulations, you have learned the basics of the `ArduinoThread` library. If you want to learn more, see bellow.
115123

124+
### Tips and Warnings
116125

117-
### TIPs and Warnings
126+
* `ThreadController` is not of a dynamic size (like a `LinkedList`). The maximum number of threads that it can manage
127+
is defined in `ThreadController.h` (default is 15)
118128

119-
* ThreadController is not a `LinkedList`. It's "MAXIMUM" size (the maximum Threads that it can
120-
store) is defined on ThreadController.h (default is 15)
129+
* ☢ When extending the `Thread` class and overriding the `run()` function,
130+
remember to always call `runned();` at the end, otherwise the thread will hang forever.
121131

122-
* !!!! VERY IMPORTANT !!!! When extending `Thread` class and implementing the function
123-
`run()`, always remember to put `runned();` after all, otherwhise the `Thread` will ALWAYS run.
124-
125-
* It's a good idea, to create a Timer interrupt and call a ThreadController.run() there.
132+
* It's a good idea, to create a `Timer` interrupt and call a `ThreadController.run()` there.
126133
That way, you don't need to worry about reading sensors and doing time-sensitive stuff
127-
on your main code (loop). Check `ControllerWithTimer` example.
134+
in your main code (`loop`). Check `ControllerWithTimer` example.
128135

129136
* Inheriting from `Thread` or even `ThreadController` is always a good idea.
130137
For example, I always create base classes of sensors that extends `Thread`,
131-
so that I can "register" the sensors inside a ThreadController, and forget
132-
about really reading sensors, just getting theirs values within my main code.
133-
Checkout `SensorThread` example.
134-
135-
* Remember that `ThreadController` is in fact, a Thread. If you want to enable
136-
or disable a GROUP of Threads, think about putting all of them inside a ThreadController,
137-
and adding this ThreadController to another ThreadController (YES! One ThreadController
138-
inside another). Check `ControllerInController` example.
139-
140-
* There is a `StaticThreadController` which is better to use when you know exact number of
141-
threads to run. You cannot add or remove threads in runtime, but `StaticThreadController`
142-
doesn't have additional memory overhead to keep all the treads together, doesn't have any
143-
limitations how many threads to store (except of available memory) and also the code may be slighly
144-
more optimized because all the threads always exist and no need to do any runtime checks.
145-
146-
* Check the full example `CustomTimedThread` for a cool application of Threads that runs
138+
so that I can "register" the sensors inside a `ThreadController`, and forget
139+
about reading sensors, just having the values available in my main code.
140+
Check the `SensorThread` example.
141+
142+
* Remember that `ThreadController` is in fact, a `Thread` itself. If you want to group threads and
143+
manage them together (enable or disable), think about putting all of them inside a `ThreadController`,
144+
and adding this `ThreadController` to another `ThreadController` (YES! One inside another).
145+
Check `ControllerInController` example.
146+
147+
* `StaticThreadController` is optimal when you know the exact number of
148+
threads to run. You cannot add or remove threads at runtime, but it
149+
doesn't require additional memory to keep all the treads together, doesn't limit the number of thread
150+
(except for available memory) and the code may be slightly
151+
better optimized because all the threads always exist and no need to do any runtime checks.
152+
153+
* Check the full example `CustomTimedThread` for a cool application of threads that run
147154
for a period, after a button is pressed.
148155

149-
* Running tasks on the Timer interrupts must be tought REALLY carefully
156+
* Running tasks on the `Timer` interrupts must be thought though REALLY carefully
150157

151-
You cannot use "sleep()" inside a interrupt, because it will get into a infinite loop.
158+
- You mustn't use `sleep()` inside an interrupt, because it would cause an infinite loop.
152159

153-
Things must do stuff quickly. Waiting too loooong on a interrupt, means waiting too
154-
loooong on the main code (loop)
160+
- Things execute quickly. Waiting too loooong on a interrupt, means waiting too
161+
loooong on the main code (`loop`)
155162

156-
Things might get "scrambled". Since Timers interrupts actualy "BREAK" your code in half
163+
- Things might get "scrambled". Since Timers interrupts actually "BREAK" your code in half
157164
and start running the interrupt, you might want to call `noInterrupts` and `interrupts`
158165
on places where cannot be interrupted:
159166

@@ -162,44 +169,40 @@ noInterrupts();
162169
// Put the code that CANNOT be interrupted...
163170
interrupts(); // This will enable the interrupts egain. DO NOT FORGET!
164171
```
165-
166-
167172
## Library Reference
168173

169-
### You should know:
170-
171-
- `bool Thread::enabled` - Enables or disables the Thread. (do not stop it from running, but will
172-
return false when shouldRun() is called)
173-
- `void Thread::setInterval()` - Setts the desired interval for the Thread (in Ms).
174-
- `bool Thread::shouldRun()` - Returns true, if the Thread should be runned.
175-
(Basicaly,the logic is: (reached time AND is enabled?).
174+
### Configuration options
175+
#### Thread
176+
- `bool Thread::enabled` - Enables or disables the thread. (doesn't prevent it from running, but will
177+
return `false` when `shouldRun()` is called)
178+
- `void Thread::setInterval()` - Schedules the thread run interval in milliseconds
179+
- `bool Thread::shouldRun()` - Returns true, if the thread should be run.
180+
(Basically,the logic is: (reached time AND is enabled?).
176181
- `void Thread::onRun(<function>)` - The target callback function to be called.
177-
- `void Thread::run()` - This will run the Thread (call the callback function).
178-
- `int Thread::ThreadID` - Theoretically, it's the address of memory. It's unique, and can
182+
- `void Thread::run()` - Runs the thread (executes the callback function).
183+
- `int Thread::ThreadID` - Theoretically, it's the memory address. It's unique, and can
179184
be used to compare if two threads are identical.
180-
- `int Thread::ThreadName` - A human-redable thread name. Default is "Thread ThreadID"
181-
eg.: "Thread 141515"; Note that to enable this attribute, you must uncomment the line that disables it on 'Thread.h';
182-
- protected: `void Thread::runned()` - Used to reset internal timer of the Thread.
183-
This is automaticaly called AFTER a call to `run()`.
184-
185-
186-
- `void ThreadController::run()` - This will run the all `Threads` within the `ThreadController`,
187-
only if needed (if shouldRun returns true);
188-
- `bool ThreadController::add(Thread* _thread)` - This will add a the thread to the ThreadController,
189-
and return `true` if suceeded (it the array is full, returns false).
190-
- `void ThreadController::remove(Thread* _thread)` - This will remove the Thread from the ThreadController.
191-
- `void ThreadController::remove(int index)` - This will remove the thread on the position `index`.
192-
- `void ThreadController::clear()` - This will remove ALL threads from the ThreadController array.
193-
- `int ThreadController::size(bool cached = true)` - Returns how many Threads are allocated
194-
inside the ThreadController. If cached is `false`, will force the calculation of threads.
195-
- `Thread* ThreadController::get(int index)` - Returns the Thread on the position `index`.
196-
197-
198-
- `void StaticThreadController::run()` - This will run the all `Threads` within the `StaicThreadController`,
199-
only if needed (if shouldRun returns true);
200-
- `int StaticThreadController::size()` - Returns how many Threads are allocated inside the StaticThreadController.
201-
- `Thread* ThreadController::get(int index)` - Returns the Thread on the position `index` and `nullptr` if `index`
185+
- `int Thread::ThreadName` - A human-readable thread name.
186+
Default is "Thread ThreadID", eg.: "Thread 141515".
187+
Note that to enable this attribute, you must uncomment the line that disables it on `Thread.h`
188+
- protected: `void Thread::runned()` - Used to reset internal timer of the thread.
189+
This is automatically called AFTER a call to `run()`.
190+
191+
#### ThreadController
192+
- `void ThreadController::run()` - Runs the all threads grouped by the controller,
193+
but only if needed (if `shouldRun()` returns true);
194+
- `bool ThreadController::add(Thread* _thread)` - Adds a the thread to the controller,
195+
and returns `true` if succeeded (returns false if the array is full).
196+
- `void ThreadController::remove(Thread* _thread)` - Removes the thread from the controller
197+
- `void ThreadController::remove(int index)` - Removes the thread at the `index` position
198+
- `void ThreadController::clear()` - Removes ALL threads from the controller
199+
- `int ThreadController::size(bool cached = true)` - Returns number of threads allocated
200+
in the ThreadController. Re-calculates thread count if `cached` is `false`
201+
- `Thread* ThreadController::get(int index)` - Returns the thread at the `index` position
202+
203+
#### StaticThreadController
204+
- `void StaticThreadController::run()` - Runs all the threads within the controller,
205+
but only if needed (if `shouldRun()` returns true);
206+
- `int StaticThreadController::size()` - Returns how many Threads are allocated inside the controller.
207+
- `Thread* ThreadController::get(int index)` - Returns the thread at the `index` position - or `nullptr` if `index`
202208
is out of bounds.
203-
204-
### You don't need to know:
205-
- Nothing, yet ;)

0 commit comments

Comments
 (0)