-
Notifications
You must be signed in to change notification settings - Fork 4
Adding documentation. #57
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
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
21941aa
Adding documentation for threading basics.
aentinger 84a9e97
Adding documentation for Shared/Sink/Source semantics.
aentinger 58d7591
Adding documentation for threadsafe Serial.
aentinger a6906ec
Adding documentation for threadsafe Wire.
aentinger e929157
Adding download link for multi-threading supporting arduino-cli.
aentinger 22ab392
Adding documentation for threadsafe SPI.
aentinger b1f3517
Adding download links for all platforms.
aentinger 7ea808b
Fix: a arduino sketch can contain multiple ino-files, not just a sing…
aentinger 7976e7e
Adding information on limitation of inot-file names.
aentinger 8721ef7
Documentation suggestions (#59)
sebromero File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<img src="https://content.arduino.cc/website/Arduino_logo_teal.svg" height="100" align="right"/> | ||
|
||
Threading Basics | ||
================ | ||
## Introduction | ||
Previously Arduino sketches didn't support the concept of multitasking, unless you took specific measures to support it. With this so called single-threaded approach instructions in your Arduino sketch are executed one after another. If an instruction or a function call respectively makes the runtime environment wait for its execution to complete, it's called a "blocking" function. You may have encountered the limitations of this when interacting with multiple sensors and actuators at once. For example if you let a servo motor react to the data read from a distance sensor. While the servo motor is moving to its target position no further reading of the distance sensor can be done because the program waits until the servo is done moving. To solve this issue multitasking can be used which allows to "simultaneously" execute multiple task such as reading from a sensor and controlling a motor. In the context of multitasking a thread is basically a mechanism (provided usually by the operating system) to encapsulate a task to be run concurrently with others. | ||
|
||
In the historic single-threaded execution of Arduino sketches the complete program logic is contained within the `*.ino` file. It contains both a `setup()` function, which is executed only once at program start, and a `loop()` function, which is executed indefinitely. A single-threaded Arduino project can theoretically contain multiple `*.ino` files but you can define `setup()` or `loop()` only once. | ||
In order to support multi-threaded (or parallel) sketch execution a new file type called the `*.inot` file is introduced. | ||
|
||
The advantage of this approach is that a complex and lengthy `loop()` function (potentially consisting of nested [finite state machines](https://en.wikipedia.org/wiki/Finite-state_machine)) found in typical Arduino sketches can be broken up into several, parallelly executed `loop()` functions with a much smaller scope. This not only increases program readability and maintainability but as a result leads to a reduction of software errors (bugs). | ||
|
||
#### Example (Single-Threaded): | ||
This sketch demonstrates how one would implement a program which requires the execution of three different actions on three different periodic intervals. In this example we blink three different LEDs at three different intervals. | ||
|
||
**Blink_Three_LEDs.ino**: | ||
|
||
```C++ | ||
void setup() | ||
{ | ||
pinMode(LED_RED, OUTPUT); | ||
pinMode(LED_GREEN, OUTPUT); | ||
pinMode(LED_BLUE, OUTPUT); | ||
} | ||
|
||
int const DELAY_RED_msec = 900; | ||
int const DELAY_GREEN_msec = 500; | ||
int const DELAY_BLUE_msec = 750; | ||
|
||
void loop() | ||
{ | ||
static unsigned long prev_red = millis(); | ||
static unsigned long prev_green = millis(); | ||
static unsigned long prev_blue = millis(); | ||
|
||
unsigned long const now = millis(); | ||
|
||
if ((now - prev_red) > DELAY_RED_msec) { | ||
prev_red = now; | ||
digitalWrite(LED_RED, !digitalRead(LED_RED)); | ||
} | ||
|
||
if ((now - prev_green) > DELAY_GREEN_msec) { | ||
prev_green = now; | ||
digitalWrite(LED_GREEN, !digitalRead(LED_GREEN)); | ||
} | ||
|
||
if ((now - prev_blue) > DELAY_BLUE_msec) { | ||
prev_blue = now; | ||
digitalWrite(LED_BLUE, !digitalRead(LED_BLUE)); | ||
} | ||
} | ||
``` | ||
You can imagine that with increasing complexity of a sketch it gets quite difficult to keep track of the different states used for the different sub-tasks (here: blinking each of the LEDs). | ||
|
||
#### Example (Multi-Threaded): | ||
|
||
The same functionality can be provided via multi-threaded execution in a much cleaner way. | ||
|
||
**Blink_Three_LEDs.ino** | ||
|
||
```C++ | ||
void setup() { | ||
// Start the task defined in the corresponding .inot file | ||
LedRed.start(); | ||
LedGreen.start(); | ||
LedBlue.start(); | ||
} | ||
|
||
void loop() { | ||
} | ||
``` | ||
**LedRed.inot** | ||
```C++ | ||
void setup() { | ||
pinMode(LED_RED, OUTPUT); | ||
} | ||
|
||
int const DELAY_RED_msec = 900; | ||
|
||
void loop() { | ||
digitalWrite(LED_RED, !digitalRead(LED_RED)); | ||
delay(DELAY_RED_msec); | ||
} | ||
``` | ||
**LedGreen.inot** | ||
```C++ | ||
void setup() { | ||
pinMode(LED_GREEN, OUTPUT); | ||
} | ||
|
||
int const DELAY_GREEN_msec = 500; | ||
|
||
void loop() { | ||
digitalWrite(LED_GREEN, !digitalRead(LED_GREEN)); | ||
delay(DELAY_GREEN_msec); | ||
} | ||
``` | ||
**LedBlue.inot** | ||
```C++ | ||
void setup() { | ||
pinMode(LED_BLUE, OUTPUT); | ||
} | ||
|
||
int const DELAY_BLUE_msec = 750; | ||
|
||
void loop() { | ||
digitalWrite(LED_BLUE, !digitalRead(LED_BLUE)); | ||
delay(DELAY_BLUE_msec); | ||
} | ||
``` | ||
As you can see from the example the name of the `*.inot`-file is used to generate a class and instantiate an object with the **same name** as the `*.inot`-file. Hence the `*.inot`-file can be only named in concordance with the rules to declare a variable in C++. `*.inot`-file names: | ||
* must begin with a letter of the alphabet or an underscore (_). | ||
* can contain letters and numbers after the first initial letter. | ||
* are case sensitive. | ||
* cannot contain spaces or special characters. | ||
* cannot be a C++ keyword (i.e. `register`, `volatile`, `while`, etc.). | ||
|
||
To be consistent with the Arduino programming style we recommend using [camel case](https://en.wikipedia.org/wiki/Camel_case) for the file names. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.