-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adding documentation for threading basics. * Adding documentation for Shared/Sink/Source semantics. * Adding documentation for threadsafe Serial. * Adding documentation for threadsafe Wire. * Adding download link for multi-threading supporting arduino-cli. * Adding documentation for threadsafe SPI. * Adding download links for all platforms. * Fix: a arduino sketch can contain multiple ino-files, not just a single one. (But you can only define setup/loop once. See #57 (comment). * Adding information on limitation of inot-file names. * Documentation suggestions (#59) * Add questions and suggestions to main readme * Add questions and suggestions to the main docs readme * Add numbers to toc * Add introduction about single-thread limitations * Add reference to example * Add Caveats section * Rephrase benefits paragraph * Add note about single threaded example * Add question about multi core * Perform minor rewording * Add recommendation for naming * Add questions, comments and rephrasing to data exchange * Add note about hierarchy graphic * Add rephrasings and questions to Thread-safe serial * Add rewording and questions to threadsafe wire * Add questions, comments and rephrasing to threadsafe SPI * Clarify on comment * Explain threading and blocking * Remove questions * Update docs/01-threading-basics.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/01-threading-basics.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/01-threading-basics.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update README.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/01-threading-basics.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/05-threadsafe-spi.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/04-threadsafe-wire.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/05-threadsafe-spi.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/05-threadsafe-spi.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/05-threadsafe-spi.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/README.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/05-threadsafe-spi.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> * Update docs/01-threading-basics.md * Update docs/02-data-exchange.md Co-authored-by: Alexander Entinger <consulting@lxrobotics.com> Co-authored-by: Sebastian Romero <s.romero.zh@gmail.com>
- Loading branch information
Showing
7 changed files
with
558 additions
and
26 deletions.
There are no files selected for viewing
This file contains 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 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.